patchright-core 1.48.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/README.md +3 -0
  2. package/ThirdPartyNotices.txt +1548 -0
  3. package/bin/PrintDeps.exe +0 -0
  4. package/bin/README.md +2 -0
  5. package/bin/install_media_pack.ps1 +5 -0
  6. package/bin/reinstall_chrome_beta_linux.sh +40 -0
  7. package/bin/reinstall_chrome_beta_mac.sh +13 -0
  8. package/bin/reinstall_chrome_beta_win.ps1 +24 -0
  9. package/bin/reinstall_chrome_stable_linux.sh +40 -0
  10. package/bin/reinstall_chrome_stable_mac.sh +12 -0
  11. package/bin/reinstall_chrome_stable_win.ps1 +24 -0
  12. package/bin/reinstall_msedge_beta_linux.sh +40 -0
  13. package/bin/reinstall_msedge_beta_mac.sh +11 -0
  14. package/bin/reinstall_msedge_beta_win.ps1 +23 -0
  15. package/bin/reinstall_msedge_dev_linux.sh +40 -0
  16. package/bin/reinstall_msedge_dev_mac.sh +11 -0
  17. package/bin/reinstall_msedge_dev_win.ps1 +23 -0
  18. package/bin/reinstall_msedge_stable_linux.sh +40 -0
  19. package/bin/reinstall_msedge_stable_mac.sh +11 -0
  20. package/bin/reinstall_msedge_stable_win.ps1 +24 -0
  21. package/browsers.json +57 -0
  22. package/cli.js +18 -0
  23. package/index.d.ts +17 -0
  24. package/index.js +33 -0
  25. package/index.mjs +28 -0
  26. package/lib/androidServerImpl.js +69 -0
  27. package/lib/browserServerImpl.js +92 -0
  28. package/lib/cli/driver.js +95 -0
  29. package/lib/cli/program.js +589 -0
  30. package/lib/cli/programWithTestStub.js +67 -0
  31. package/lib/client/accessibility.js +50 -0
  32. package/lib/client/android.js +473 -0
  33. package/lib/client/api.js +285 -0
  34. package/lib/client/artifact.js +79 -0
  35. package/lib/client/browser.js +145 -0
  36. package/lib/client/browserContext.js +583 -0
  37. package/lib/client/browserType.js +241 -0
  38. package/lib/client/cdpSession.js +53 -0
  39. package/lib/client/channelOwner.js +235 -0
  40. package/lib/client/clientHelper.js +57 -0
  41. package/lib/client/clientInstrumentation.js +50 -0
  42. package/lib/client/clock.js +69 -0
  43. package/lib/client/connection.js +333 -0
  44. package/lib/client/consoleMessage.js +55 -0
  45. package/lib/client/coverage.js +41 -0
  46. package/lib/client/dialog.js +57 -0
  47. package/lib/client/download.js +62 -0
  48. package/lib/client/electron.js +135 -0
  49. package/lib/client/elementHandle.js +321 -0
  50. package/lib/client/errors.js +77 -0
  51. package/lib/client/eventEmitter.js +314 -0
  52. package/lib/client/events.js +94 -0
  53. package/lib/client/fetch.js +391 -0
  54. package/lib/client/fileChooser.js +45 -0
  55. package/lib/client/frame.js +504 -0
  56. package/lib/client/harRouter.js +99 -0
  57. package/lib/client/input.js +111 -0
  58. package/lib/client/jsHandle.js +121 -0
  59. package/lib/client/jsonPipe.js +35 -0
  60. package/lib/client/localUtils.js +36 -0
  61. package/lib/client/locator.js +441 -0
  62. package/lib/client/network.js +762 -0
  63. package/lib/client/page.js +770 -0
  64. package/lib/client/playwright.js +80 -0
  65. package/lib/client/selectors.js +67 -0
  66. package/lib/client/stream.js +54 -0
  67. package/lib/client/tracing.js +134 -0
  68. package/lib/client/types.js +24 -0
  69. package/lib/client/video.js +51 -0
  70. package/lib/client/waiter.js +158 -0
  71. package/lib/client/webError.js +37 -0
  72. package/lib/client/worker.js +71 -0
  73. package/lib/client/writableStream.js +54 -0
  74. package/lib/common/socksProxy.js +569 -0
  75. package/lib/common/timeoutSettings.js +73 -0
  76. package/lib/common/types.js +5 -0
  77. package/lib/generated/clockSource.js +7 -0
  78. package/lib/generated/consoleApiSource.js +7 -0
  79. package/lib/generated/injectedScriptSource.js +7 -0
  80. package/lib/generated/pollingRecorderSource.js +7 -0
  81. package/lib/generated/utilityScriptSource.js +7 -0
  82. package/lib/generated/webSocketMockSource.js +7 -0
  83. package/lib/image_tools/colorUtils.js +98 -0
  84. package/lib/image_tools/compare.js +108 -0
  85. package/lib/image_tools/imageChannel.js +70 -0
  86. package/lib/image_tools/stats.js +102 -0
  87. package/lib/inProcessFactory.js +54 -0
  88. package/lib/inprocess.js +20 -0
  89. package/lib/outofprocess.js +67 -0
  90. package/lib/protocol/debug.js +27 -0
  91. package/lib/protocol/serializers.js +173 -0
  92. package/lib/protocol/transport.js +82 -0
  93. package/lib/protocol/validator.js +2760 -0
  94. package/lib/protocol/validatorPrimitives.js +139 -0
  95. package/lib/remote/playwrightConnection.js +274 -0
  96. package/lib/remote/playwrightServer.js +110 -0
  97. package/lib/server/accessibility.js +62 -0
  98. package/lib/server/android/android.js +441 -0
  99. package/lib/server/android/backendAdb.js +172 -0
  100. package/lib/server/artifact.js +104 -0
  101. package/lib/server/bidi/bidiBrowser.js +311 -0
  102. package/lib/server/bidi/bidiChromium.js +124 -0
  103. package/lib/server/bidi/bidiConnection.js +206 -0
  104. package/lib/server/bidi/bidiExecutionContext.js +159 -0
  105. package/lib/server/bidi/bidiFirefox.js +104 -0
  106. package/lib/server/bidi/bidiInput.js +158 -0
  107. package/lib/server/bidi/bidiNetworkManager.js +338 -0
  108. package/lib/server/bidi/bidiOverCdp.js +103 -0
  109. package/lib/server/bidi/bidiPage.js +529 -0
  110. package/lib/server/bidi/bidiPdf.js +140 -0
  111. package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
  112. package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
  113. package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
  114. package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
  115. package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
  116. package/lib/server/browser.js +148 -0
  117. package/lib/server/browserContext.js +666 -0
  118. package/lib/server/browserType.js +335 -0
  119. package/lib/server/chromium/appIcon.png +0 -0
  120. package/lib/server/chromium/chromium.js +350 -0
  121. package/lib/server/chromium/chromiumSwitches.js +36 -0
  122. package/lib/server/chromium/crAccessibility.js +237 -0
  123. package/lib/server/chromium/crBrowser.js +522 -0
  124. package/lib/server/chromium/crConnection.js +228 -0
  125. package/lib/server/chromium/crCoverage.js +246 -0
  126. package/lib/server/chromium/crDevTools.js +104 -0
  127. package/lib/server/chromium/crDragDrop.js +143 -0
  128. package/lib/server/chromium/crExecutionContext.js +149 -0
  129. package/lib/server/chromium/crInput.js +171 -0
  130. package/lib/server/chromium/crNetworkManager.js +809 -0
  131. package/lib/server/chromium/crPage.js +1235 -0
  132. package/lib/server/chromium/crPdf.js +153 -0
  133. package/lib/server/chromium/crProtocolHelper.js +133 -0
  134. package/lib/server/chromium/crServiceWorker.js +111 -0
  135. package/lib/server/chromium/defaultFontFamilies.js +145 -0
  136. package/lib/server/chromium/videoRecorder.js +155 -0
  137. package/lib/server/clock.js +133 -0
  138. package/lib/server/codegen/csharp.js +299 -0
  139. package/lib/server/codegen/java.js +235 -0
  140. package/lib/server/codegen/javascript.js +223 -0
  141. package/lib/server/codegen/jsonl.js +47 -0
  142. package/lib/server/codegen/language.js +88 -0
  143. package/lib/server/codegen/languages.js +30 -0
  144. package/lib/server/codegen/python.js +265 -0
  145. package/lib/server/codegen/types.js +5 -0
  146. package/lib/server/console.js +57 -0
  147. package/lib/server/cookieStore.js +185 -0
  148. package/lib/server/debugController.js +234 -0
  149. package/lib/server/debugger.js +132 -0
  150. package/lib/server/deviceDescriptors.js +26 -0
  151. package/lib/server/deviceDescriptorsSource.json +1669 -0
  152. package/lib/server/dialog.js +71 -0
  153. package/lib/server/dispatchers/androidDispatcher.js +193 -0
  154. package/lib/server/dispatchers/artifactDispatcher.js +118 -0
  155. package/lib/server/dispatchers/browserContextDispatcher.js +368 -0
  156. package/lib/server/dispatchers/browserDispatcher.js +170 -0
  157. package/lib/server/dispatchers/browserTypeDispatcher.js +55 -0
  158. package/lib/server/dispatchers/cdpSessionDispatcher.js +48 -0
  159. package/lib/server/dispatchers/debugControllerDispatcher.js +103 -0
  160. package/lib/server/dispatchers/dialogDispatcher.js +44 -0
  161. package/lib/server/dispatchers/dispatcher.js +395 -0
  162. package/lib/server/dispatchers/electronDispatcher.js +93 -0
  163. package/lib/server/dispatchers/elementHandlerDispatcher.js +228 -0
  164. package/lib/server/dispatchers/frameDispatcher.js +286 -0
  165. package/lib/server/dispatchers/jsHandleDispatcher.js +97 -0
  166. package/lib/server/dispatchers/jsonPipeDispatcher.js +59 -0
  167. package/lib/server/dispatchers/localUtilsDispatcher.js +413 -0
  168. package/lib/server/dispatchers/networkDispatchers.js +221 -0
  169. package/lib/server/dispatchers/pageDispatcher.js +367 -0
  170. package/lib/server/dispatchers/playwrightDispatcher.js +107 -0
  171. package/lib/server/dispatchers/selectorsDispatcher.js +36 -0
  172. package/lib/server/dispatchers/streamDispatcher.js +62 -0
  173. package/lib/server/dispatchers/tracingDispatcher.js +54 -0
  174. package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
  175. package/lib/server/dispatchers/writableStreamDispatcher.js +58 -0
  176. package/lib/server/dom.js +845 -0
  177. package/lib/server/download.js +60 -0
  178. package/lib/server/electron/electron.js +296 -0
  179. package/lib/server/electron/loader.js +57 -0
  180. package/lib/server/errors.js +68 -0
  181. package/lib/server/fetch.js +656 -0
  182. package/lib/server/fileChooser.js +42 -0
  183. package/lib/server/fileUploadUtils.js +75 -0
  184. package/lib/server/firefox/ffAccessibility.js +216 -0
  185. package/lib/server/firefox/ffBrowser.js +460 -0
  186. package/lib/server/firefox/ffConnection.js +168 -0
  187. package/lib/server/firefox/ffExecutionContext.js +135 -0
  188. package/lib/server/firefox/ffInput.js +150 -0
  189. package/lib/server/firefox/ffNetworkManager.js +233 -0
  190. package/lib/server/firefox/ffPage.js +559 -0
  191. package/lib/server/firefox/firefox.js +99 -0
  192. package/lib/server/formData.js +75 -0
  193. package/lib/server/frameSelectors.js +171 -0
  194. package/lib/server/frames.js +1808 -0
  195. package/lib/server/har/harRecorder.js +139 -0
  196. package/lib/server/har/harTracer.js +542 -0
  197. package/lib/server/helper.js +103 -0
  198. package/lib/server/index.js +114 -0
  199. package/lib/server/input.js +310 -0
  200. package/lib/server/instrumentation.js +70 -0
  201. package/lib/server/isomorphic/utilityScriptSerializers.js +226 -0
  202. package/lib/server/javascript.js +299 -0
  203. package/lib/server/launchApp.js +91 -0
  204. package/lib/server/macEditingCommands.js +139 -0
  205. package/lib/server/network.js +617 -0
  206. package/lib/server/page.js +819 -0
  207. package/lib/server/pipeTransport.js +85 -0
  208. package/lib/server/playwright.js +88 -0
  209. package/lib/server/progress.js +102 -0
  210. package/lib/server/protocolError.js +49 -0
  211. package/lib/server/recorder/contextRecorder.js +299 -0
  212. package/lib/server/recorder/recorderApp.js +196 -0
  213. package/lib/server/recorder/recorderCollection.js +116 -0
  214. package/lib/server/recorder/recorderFrontend.js +5 -0
  215. package/lib/server/recorder/recorderInTraceViewer.js +144 -0
  216. package/lib/server/recorder/recorderRunner.js +155 -0
  217. package/lib/server/recorder/recorderUtils.js +112 -0
  218. package/lib/server/recorder/throttledFile.js +46 -0
  219. package/lib/server/recorder.js +329 -0
  220. package/lib/server/registry/browserFetcher.js +168 -0
  221. package/lib/server/registry/dependencies.js +322 -0
  222. package/lib/server/registry/index.js +1005 -0
  223. package/lib/server/registry/nativeDeps.js +490 -0
  224. package/lib/server/registry/oopDownloadBrowserMain.js +138 -0
  225. package/lib/server/screenshotter.js +348 -0
  226. package/lib/server/selectors.js +73 -0
  227. package/lib/server/socksClientCertificatesInterceptor.js +340 -0
  228. package/lib/server/socksInterceptor.js +100 -0
  229. package/lib/server/trace/recorder/snapshotter.js +172 -0
  230. package/lib/server/trace/recorder/snapshotterInjected.js +493 -0
  231. package/lib/server/trace/recorder/tracing.js +542 -0
  232. package/lib/server/trace/test/inMemorySnapshotter.js +93 -0
  233. package/lib/server/trace/viewer/traceViewer.js +213 -0
  234. package/lib/server/transport.js +191 -0
  235. package/lib/server/types.js +24 -0
  236. package/lib/server/usKeyboardLayout.js +555 -0
  237. package/lib/server/webkit/webkit.js +87 -0
  238. package/lib/server/webkit/wkAccessibility.js +194 -0
  239. package/lib/server/webkit/wkBrowser.js +329 -0
  240. package/lib/server/webkit/wkConnection.js +173 -0
  241. package/lib/server/webkit/wkExecutionContext.js +143 -0
  242. package/lib/server/webkit/wkInput.js +169 -0
  243. package/lib/server/webkit/wkInterceptableRequest.js +162 -0
  244. package/lib/server/webkit/wkPage.js +1219 -0
  245. package/lib/server/webkit/wkProvisionalPage.js +94 -0
  246. package/lib/server/webkit/wkWorkers.js +104 -0
  247. package/lib/third_party/diff_match_patch.js +2222 -0
  248. package/lib/third_party/pixelmatch.js +255 -0
  249. package/lib/utils/ascii.js +31 -0
  250. package/lib/utils/comparators.js +171 -0
  251. package/lib/utils/crypto.js +174 -0
  252. package/lib/utils/debug.js +46 -0
  253. package/lib/utils/debugLogger.js +91 -0
  254. package/lib/utils/env.js +49 -0
  255. package/lib/utils/eventsHelper.js +38 -0
  256. package/lib/utils/expectUtils.js +33 -0
  257. package/lib/utils/fileUtils.js +205 -0
  258. package/lib/utils/happy-eyeballs.js +194 -0
  259. package/lib/utils/headers.js +52 -0
  260. package/lib/utils/hostPlatform.js +133 -0
  261. package/lib/utils/httpServer.js +237 -0
  262. package/lib/utils/index.js +368 -0
  263. package/lib/utils/isomorphic/cssParser.js +250 -0
  264. package/lib/utils/isomorphic/cssTokenizer.js +979 -0
  265. package/lib/utils/isomorphic/locatorGenerators.js +642 -0
  266. package/lib/utils/isomorphic/locatorParser.js +179 -0
  267. package/lib/utils/isomorphic/locatorUtils.js +62 -0
  268. package/lib/utils/isomorphic/mimeType.js +29 -0
  269. package/lib/utils/isomorphic/recorderUtils.js +195 -0
  270. package/lib/utils/isomorphic/selectorParser.js +397 -0
  271. package/lib/utils/isomorphic/stringUtils.js +139 -0
  272. package/lib/utils/isomorphic/traceUtils.js +39 -0
  273. package/lib/utils/isomorphic/urlMatch.js +120 -0
  274. package/lib/utils/linuxUtils.js +78 -0
  275. package/lib/utils/manualPromise.js +109 -0
  276. package/lib/utils/multimap.js +75 -0
  277. package/lib/utils/network.js +160 -0
  278. package/lib/utils/processLauncher.js +248 -0
  279. package/lib/utils/profiler.js +53 -0
  280. package/lib/utils/rtti.js +44 -0
  281. package/lib/utils/semaphore.js +51 -0
  282. package/lib/utils/spawnAsync.js +45 -0
  283. package/lib/utils/stackTrace.js +121 -0
  284. package/lib/utils/task.js +58 -0
  285. package/lib/utils/time.js +37 -0
  286. package/lib/utils/timeoutRunner.js +66 -0
  287. package/lib/utils/traceUtils.js +44 -0
  288. package/lib/utils/userAgent.js +105 -0
  289. package/lib/utils/wsServer.js +127 -0
  290. package/lib/utils/zipFile.js +75 -0
  291. package/lib/utils/zones.js +62 -0
  292. package/lib/utilsBundle.js +82 -0
  293. package/lib/utilsBundleImpl/index.js +53 -0
  294. package/lib/utilsBundleImpl/xdg-open +1066 -0
  295. package/lib/vite/htmlReport/index.html +66 -0
  296. package/lib/vite/recorder/assets/codeMirrorModule-baozm8ur.js +24 -0
  297. package/lib/vite/recorder/assets/codeMirrorModule-ez37Vkbh.css +1 -0
  298. package/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  299. package/lib/vite/recorder/assets/index-2ElAIWFB.js +42 -0
  300. package/lib/vite/recorder/assets/index-BW-aOBcL.css +1 -0
  301. package/lib/vite/recorder/index.html +29 -0
  302. package/lib/vite/recorder/playwright-logo.svg +9 -0
  303. package/lib/vite/traceViewer/assets/codeMirrorModule-Bh1rfd2w.js +24 -0
  304. package/lib/vite/traceViewer/assets/inspectorTab-7GHnKvSD.js +64 -0
  305. package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
  306. package/lib/vite/traceViewer/assets/workbench-DPQnTHYP.js +9 -0
  307. package/lib/vite/traceViewer/assets/xtermModule-BeNbaIVa.js +9 -0
  308. package/lib/vite/traceViewer/codeMirrorModule.ez37Vkbh.css +1 -0
  309. package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  310. package/lib/vite/traceViewer/embedded.BlHoW5LY.js +2 -0
  311. package/lib/vite/traceViewer/embedded.html +18 -0
  312. package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
  313. package/lib/vite/traceViewer/index.CrbWWHbf.css +1 -0
  314. package/lib/vite/traceViewer/index.DaWVfou1.js +2 -0
  315. package/lib/vite/traceViewer/index.html +29 -0
  316. package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
  317. package/lib/vite/traceViewer/playwright-logo.svg +9 -0
  318. package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
  319. package/lib/vite/traceViewer/recorder.C4zxcvd2.js +2 -0
  320. package/lib/vite/traceViewer/recorder.html +17 -0
  321. package/lib/vite/traceViewer/snapshot.html +21 -0
  322. package/lib/vite/traceViewer/sw.bundle.js +3 -0
  323. package/lib/vite/traceViewer/uiMode.CAYqod-m.css +1 -0
  324. package/lib/vite/traceViewer/uiMode.html +20 -0
  325. package/lib/vite/traceViewer/uiMode.mTXWniJb.js +5 -0
  326. package/lib/vite/traceViewer/workbench.D3JVcA9K.css +1 -0
  327. package/lib/vite/traceViewer/xtermModule.DSXBckUd.css +32 -0
  328. package/lib/zipBundle.js +25 -0
  329. package/lib/zipBundleImpl.js +5 -0
  330. package/package.json +44 -0
  331. package/types/protocol.d.ts +21571 -0
  332. package/types/structs.d.ts +45 -0
  333. package/types/types.d.ts +22519 -0
@@ -0,0 +1,460 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FFBrowserContext = exports.FFBrowser = void 0;
7
+ var _errors = require("../errors");
8
+ var _utils = require("../../utils");
9
+ var _browser = require("../browser");
10
+ var _browserContext = require("../browserContext");
11
+ var network = _interopRequireWildcard(require("../network"));
12
+ var _page = require("../page");
13
+ var _ffConnection = require("./ffConnection");
14
+ var _ffPage = require("./ffPage");
15
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
+ /**
18
+ * Copyright 2018 Google Inc. All rights reserved.
19
+ * Modifications copyright (c) Microsoft Corporation.
20
+ *
21
+ * Licensed under the Apache License, Version 2.0 (the 'License');
22
+ * you may not use this file except in compliance with the License.
23
+ * You may obtain a copy of the License at
24
+ *
25
+ * http://www.apache.org/licenses/LICENSE-2.0
26
+ *
27
+ * Unless required by applicable law or agreed to in writing, software
28
+ * distributed under the License is distributed on an 'AS IS' BASIS,
29
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30
+ * See the License for the specific language governing permissions and
31
+ * limitations under the License.
32
+ */
33
+
34
+ class FFBrowser extends _browser.Browser {
35
+ static async connect(parent, transport, options) {
36
+ var _options$originalLaun;
37
+ const connection = new _ffConnection.FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
38
+ const browser = new FFBrowser(parent, connection, options);
39
+ if (options.__testHookOnConnectToBrowser) await options.__testHookOnConnectToBrowser();
40
+ let firefoxUserPrefs = (_options$originalLaun = options.originalLaunchOptions.firefoxUserPrefs) !== null && _options$originalLaun !== void 0 ? _options$originalLaun : {};
41
+ if (Object.keys(kBandaidFirefoxUserPrefs).length) firefoxUserPrefs = {
42
+ ...kBandaidFirefoxUserPrefs,
43
+ ...firefoxUserPrefs
44
+ };
45
+ const promises = [browser.session.send('Browser.enable', {
46
+ attachToDefaultContext: !!options.persistent,
47
+ userPrefs: Object.entries(firefoxUserPrefs).map(([name, value]) => ({
48
+ name,
49
+ value
50
+ }))
51
+ }), browser._initVersion()];
52
+ if (options.persistent) {
53
+ browser._defaultContext = new FFBrowserContext(browser, undefined, options.persistent);
54
+ promises.push(browser._defaultContext._initialize());
55
+ }
56
+ const proxy = options.originalLaunchOptions.proxyOverride || options.proxy;
57
+ if (proxy) promises.push(browser.session.send('Browser.setBrowserProxy', toJugglerProxyOptions(proxy)));
58
+ await Promise.all(promises);
59
+ return browser;
60
+ }
61
+ constructor(parent, connection, options) {
62
+ super(parent, options);
63
+ this._connection = void 0;
64
+ this.session = void 0;
65
+ this._ffPages = void 0;
66
+ this._contexts = void 0;
67
+ this._version = '';
68
+ this._userAgent = '';
69
+ this._connection = connection;
70
+ this.session = connection.rootSession;
71
+ this._ffPages = new Map();
72
+ this._contexts = new Map();
73
+ this._connection.on(_ffConnection.ConnectionEvents.Disconnected, () => this._onDisconnect());
74
+ this.session.on('Browser.attachedToTarget', this._onAttachedToTarget.bind(this));
75
+ this.session.on('Browser.detachedFromTarget', this._onDetachedFromTarget.bind(this));
76
+ this.session.on('Browser.downloadCreated', this._onDownloadCreated.bind(this));
77
+ this.session.on('Browser.downloadFinished', this._onDownloadFinished.bind(this));
78
+ this.session.on('Browser.videoRecordingFinished', this._onVideoRecordingFinished.bind(this));
79
+ }
80
+ async _initVersion() {
81
+ const result = await this.session.send('Browser.getInfo');
82
+ this._version = result.version.substring(result.version.indexOf('/') + 1);
83
+ this._userAgent = result.userAgent;
84
+ }
85
+ isConnected() {
86
+ return !this._connection._closed;
87
+ }
88
+ async doCreateNewContext(options) {
89
+ if (options.isMobile) throw new Error('options.isMobile is not supported in Firefox');
90
+ const {
91
+ browserContextId
92
+ } = await this.session.send('Browser.createBrowserContext', {
93
+ removeOnDetach: true
94
+ });
95
+ const context = new FFBrowserContext(this, browserContextId, options);
96
+ await context._initialize();
97
+ this._contexts.set(browserContextId, context);
98
+ return context;
99
+ }
100
+ contexts() {
101
+ return Array.from(this._contexts.values());
102
+ }
103
+ version() {
104
+ return this._version;
105
+ }
106
+ userAgent() {
107
+ return this._userAgent;
108
+ }
109
+ _onDetachedFromTarget(payload) {
110
+ const ffPage = this._ffPages.get(payload.targetId);
111
+ this._ffPages.delete(payload.targetId);
112
+ ffPage.didClose();
113
+ }
114
+ _onAttachedToTarget(payload) {
115
+ const {
116
+ targetId,
117
+ browserContextId,
118
+ openerId,
119
+ type
120
+ } = payload.targetInfo;
121
+ (0, _utils.assert)(type === 'page');
122
+ const context = browserContextId ? this._contexts.get(browserContextId) : this._defaultContext;
123
+ (0, _utils.assert)(context, `Unknown context id:${browserContextId}, _defaultContext: ${this._defaultContext}`);
124
+ const session = this._connection.createSession(payload.sessionId);
125
+ const opener = openerId ? this._ffPages.get(openerId) : null;
126
+ const ffPage = new _ffPage.FFPage(session, context, opener);
127
+ this._ffPages.set(targetId, ffPage);
128
+ }
129
+ _onDownloadCreated(payload) {
130
+ const ffPage = this._ffPages.get(payload.pageTargetId);
131
+ if (!ffPage) return;
132
+
133
+ // Abort the navigation that turned into download.
134
+ ffPage._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
135
+ let originPage = ffPage._initializedPage;
136
+ // If it's a new window download, report it on the opener page.
137
+ if (!originPage) {
138
+ // Resume the page creation with an error. The page will automatically close right
139
+ // after the download begins.
140
+ ffPage._markAsError(new Error('Starting new page download'));
141
+ if (ffPage._opener) originPage = ffPage._opener._initializedPage;
142
+ }
143
+ if (!originPage) return;
144
+ this._downloadCreated(originPage, payload.uuid, payload.url, payload.suggestedFileName);
145
+ }
146
+ _onDownloadFinished(payload) {
147
+ const error = payload.canceled ? 'canceled' : payload.error;
148
+ this._downloadFinished(payload.uuid, error);
149
+ }
150
+ _onVideoRecordingFinished(payload) {
151
+ var _this$_takeVideo;
152
+ (_this$_takeVideo = this._takeVideo(payload.screencastId)) === null || _this$_takeVideo === void 0 || _this$_takeVideo.reportFinished();
153
+ }
154
+ _onDisconnect() {
155
+ for (const video of this._idToVideo.values()) video.artifact.reportFinished(new _errors.TargetClosedError());
156
+ this._idToVideo.clear();
157
+ for (const ffPage of this._ffPages.values()) ffPage.didClose();
158
+ this._ffPages.clear();
159
+ this._didClose();
160
+ }
161
+ }
162
+ exports.FFBrowser = FFBrowser;
163
+ class FFBrowserContext extends _browserContext.BrowserContext {
164
+ constructor(browser, browserContextId, options) {
165
+ super(browser, options, browserContextId);
166
+ }
167
+ async _initialize() {
168
+ (0, _utils.assert)(!this._ffPages().length);
169
+ const browserContextId = this._browserContextId;
170
+ const promises = [super._initialize(), this._browser.session.send('Browser.addBinding', {
171
+ browserContextId: this._browserContextId,
172
+ name: _page.PageBinding.kPlaywrightBinding,
173
+ script: ''
174
+ })];
175
+ if (this._options.acceptDownloads !== 'internal-browser-default') {
176
+ promises.push(this._browser.session.send('Browser.setDownloadOptions', {
177
+ browserContextId,
178
+ downloadOptions: {
179
+ behavior: this._options.acceptDownloads === 'accept' ? 'saveToDisk' : 'cancel',
180
+ downloadsDir: this._browser.options.downloadsPath
181
+ }
182
+ }));
183
+ }
184
+ if (this._options.viewport) {
185
+ const viewport = {
186
+ viewportSize: {
187
+ width: this._options.viewport.width,
188
+ height: this._options.viewport.height
189
+ },
190
+ deviceScaleFactor: this._options.deviceScaleFactor || 1
191
+ };
192
+ promises.push(this._browser.session.send('Browser.setDefaultViewport', {
193
+ browserContextId,
194
+ viewport
195
+ }));
196
+ }
197
+ if (this._options.hasTouch) promises.push(this._browser.session.send('Browser.setTouchOverride', {
198
+ browserContextId,
199
+ hasTouch: true
200
+ }));
201
+ if (this._options.userAgent) promises.push(this._browser.session.send('Browser.setUserAgentOverride', {
202
+ browserContextId,
203
+ userAgent: this._options.userAgent
204
+ }));
205
+ if (this._options.bypassCSP) promises.push(this._browser.session.send('Browser.setBypassCSP', {
206
+ browserContextId,
207
+ bypassCSP: true
208
+ }));
209
+ if (this._options.ignoreHTTPSErrors || this._options.internalIgnoreHTTPSErrors) promises.push(this._browser.session.send('Browser.setIgnoreHTTPSErrors', {
210
+ browserContextId,
211
+ ignoreHTTPSErrors: true
212
+ }));
213
+ if (this._options.javaScriptEnabled === false) promises.push(this._browser.session.send('Browser.setJavaScriptDisabled', {
214
+ browserContextId,
215
+ javaScriptDisabled: true
216
+ }));
217
+ if (this._options.locale) promises.push(this._browser.session.send('Browser.setLocaleOverride', {
218
+ browserContextId,
219
+ locale: this._options.locale
220
+ }));
221
+ if (this._options.timezoneId) promises.push(this._browser.session.send('Browser.setTimezoneOverride', {
222
+ browserContextId,
223
+ timezoneId: this._options.timezoneId
224
+ }));
225
+ if (this._options.extraHTTPHeaders || this._options.locale) promises.push(this.setExtraHTTPHeaders(this._options.extraHTTPHeaders || []));
226
+ if (this._options.httpCredentials) promises.push(this.setHTTPCredentials(this._options.httpCredentials));
227
+ if (this._options.geolocation) promises.push(this.setGeolocation(this._options.geolocation));
228
+ if (this._options.offline) promises.push(this.setOffline(this._options.offline));
229
+ if (this._options.colorScheme !== 'no-override') {
230
+ promises.push(this._browser.session.send('Browser.setColorScheme', {
231
+ browserContextId,
232
+ colorScheme: this._options.colorScheme !== undefined ? this._options.colorScheme : 'light'
233
+ }));
234
+ }
235
+ if (this._options.reducedMotion !== 'no-override') {
236
+ promises.push(this._browser.session.send('Browser.setReducedMotion', {
237
+ browserContextId,
238
+ reducedMotion: this._options.reducedMotion !== undefined ? this._options.reducedMotion : 'no-preference'
239
+ }));
240
+ }
241
+ if (this._options.forcedColors !== 'no-override') {
242
+ promises.push(this._browser.session.send('Browser.setForcedColors', {
243
+ browserContextId,
244
+ forcedColors: this._options.forcedColors !== undefined ? this._options.forcedColors : 'none'
245
+ }));
246
+ }
247
+ if (this._options.recordVideo) {
248
+ promises.push(this._ensureVideosPath().then(() => {
249
+ return this._browser.session.send('Browser.setVideoRecordingOptions', {
250
+ // validateBrowserContextOptions ensures correct video size.
251
+ options: {
252
+ ...this._options.recordVideo.size,
253
+ dir: this._options.recordVideo.dir
254
+ },
255
+ browserContextId: this._browserContextId
256
+ });
257
+ }));
258
+ }
259
+ const proxy = this._options.proxyOverride || this._options.proxy;
260
+ if (proxy) {
261
+ promises.push(this._browser.session.send('Browser.setContextProxy', {
262
+ browserContextId: this._browserContextId,
263
+ ...toJugglerProxyOptions(proxy)
264
+ }));
265
+ }
266
+ await Promise.all(promises);
267
+ }
268
+ _ffPages() {
269
+ return Array.from(this._browser._ffPages.values()).filter(ffPage => ffPage._browserContext === this);
270
+ }
271
+ pages() {
272
+ return this._ffPages().map(ffPage => ffPage._initializedPage).filter(pageOrNull => !!pageOrNull);
273
+ }
274
+ async newPageDelegate() {
275
+ (0, _browserContext.assertBrowserContextIsNotOwned)(this);
276
+ const {
277
+ targetId
278
+ } = await this._browser.session.send('Browser.newPage', {
279
+ browserContextId: this._browserContextId
280
+ }).catch(e => {
281
+ if (e.message.includes('Failed to override timezone')) throw new Error(`Invalid timezone ID: ${this._options.timezoneId}`);
282
+ throw e;
283
+ });
284
+ return this._browser._ffPages.get(targetId);
285
+ }
286
+ async doGetCookies(urls) {
287
+ const {
288
+ cookies
289
+ } = await this._browser.session.send('Browser.getCookies', {
290
+ browserContextId: this._browserContextId
291
+ });
292
+ return network.filterCookies(cookies.map(c => {
293
+ const copy = {
294
+ ...c
295
+ };
296
+ delete copy.size;
297
+ delete copy.session;
298
+ return copy;
299
+ }), urls);
300
+ }
301
+ async addCookies(cookies) {
302
+ const cc = network.rewriteCookies(cookies).map(c => ({
303
+ ...c,
304
+ expires: c.expires === -1 ? undefined : c.expires
305
+ }));
306
+ await this._browser.session.send('Browser.setCookies', {
307
+ browserContextId: this._browserContextId,
308
+ cookies: cc
309
+ });
310
+ }
311
+ async doClearCookies() {
312
+ await this._browser.session.send('Browser.clearCookies', {
313
+ browserContextId: this._browserContextId
314
+ });
315
+ }
316
+ async doGrantPermissions(origin, permissions) {
317
+ const webPermissionToProtocol = new Map([['geolocation', 'geo'], ['persistent-storage', 'persistent-storage'], ['push', 'push'], ['notifications', 'desktop-notification']]);
318
+ const filtered = permissions.map(permission => {
319
+ const protocolPermission = webPermissionToProtocol.get(permission);
320
+ if (!protocolPermission) throw new Error('Unknown permission: ' + permission);
321
+ return protocolPermission;
322
+ });
323
+ await this._browser.session.send('Browser.grantPermissions', {
324
+ origin: origin,
325
+ browserContextId: this._browserContextId,
326
+ permissions: filtered
327
+ });
328
+ }
329
+ async doClearPermissions() {
330
+ await this._browser.session.send('Browser.resetPermissions', {
331
+ browserContextId: this._browserContextId
332
+ });
333
+ }
334
+ async setGeolocation(geolocation) {
335
+ (0, _browserContext.verifyGeolocation)(geolocation);
336
+ this._options.geolocation = geolocation;
337
+ await this._browser.session.send('Browser.setGeolocationOverride', {
338
+ browserContextId: this._browserContextId,
339
+ geolocation: geolocation || null
340
+ });
341
+ }
342
+ async setExtraHTTPHeaders(headers) {
343
+ this._options.extraHTTPHeaders = headers;
344
+ let allHeaders = this._options.extraHTTPHeaders;
345
+ if (this._options.locale) allHeaders = network.mergeHeaders([allHeaders, network.singleHeader('Accept-Language', this._options.locale)]);
346
+ await this._browser.session.send('Browser.setExtraHTTPHeaders', {
347
+ browserContextId: this._browserContextId,
348
+ headers: allHeaders
349
+ });
350
+ }
351
+ async setUserAgent(userAgent) {
352
+ await this._browser.session.send('Browser.setUserAgentOverride', {
353
+ browserContextId: this._browserContextId,
354
+ userAgent: userAgent || null
355
+ });
356
+ }
357
+ async setOffline(offline) {
358
+ this._options.offline = offline;
359
+ await this._browser.session.send('Browser.setOnlineOverride', {
360
+ browserContextId: this._browserContextId,
361
+ override: offline ? 'offline' : 'online'
362
+ });
363
+ }
364
+ async doSetHTTPCredentials(httpCredentials) {
365
+ this._options.httpCredentials = httpCredentials;
366
+ let credentials = null;
367
+ if (httpCredentials) {
368
+ const {
369
+ username,
370
+ password,
371
+ origin
372
+ } = httpCredentials;
373
+ credentials = {
374
+ username,
375
+ password,
376
+ origin
377
+ };
378
+ }
379
+ await this._browser.session.send('Browser.setHTTPCredentials', {
380
+ browserContextId: this._browserContextId,
381
+ credentials
382
+ });
383
+ }
384
+ async doAddInitScript(initScript) {
385
+ await this._updateInitScripts();
386
+ }
387
+ async doRemoveNonInternalInitScripts() {
388
+ await this._updateInitScripts();
389
+ }
390
+ async _updateInitScripts() {
391
+ const bindingScripts = [...this._pageBindings.values()].map(binding => binding.initScript.source);
392
+ const initScripts = this.initScripts.map(script => script.source);
393
+ await this._browser.session.send('Browser.setInitScripts', {
394
+ browserContextId: this._browserContextId,
395
+ scripts: [...bindingScripts, ...initScripts].map(script => ({
396
+ script
397
+ }))
398
+ });
399
+ }
400
+ async doUpdateRequestInterception() {
401
+ await Promise.all([this._browser.session.send('Browser.setRequestInterception', {
402
+ browserContextId: this._browserContextId,
403
+ enabled: !!this._requestInterceptor
404
+ }), this._browser.session.send('Browser.setCacheDisabled', {
405
+ browserContextId: this._browserContextId,
406
+ cacheDisabled: !!this._requestInterceptor
407
+ })]);
408
+ }
409
+ onClosePersistent() {}
410
+ async clearCache() {
411
+ // Clearing only the context cache does not work: https://bugzilla.mozilla.org/show_bug.cgi?id=1819147
412
+ await this._browser.session.send('Browser.clearCache');
413
+ }
414
+ async doClose(reason) {
415
+ if (!this._browserContextId) {
416
+ if (this._options.recordVideo) {
417
+ await this._browser.session.send('Browser.setVideoRecordingOptions', {
418
+ options: undefined,
419
+ browserContextId: this._browserContextId
420
+ });
421
+ }
422
+ // Closing persistent context should close the browser.
423
+ await this._browser.close({
424
+ reason
425
+ });
426
+ } else {
427
+ await this._browser.session.send('Browser.removeBrowserContext', {
428
+ browserContextId: this._browserContextId
429
+ });
430
+ this._browser._contexts.delete(this._browserContextId);
431
+ }
432
+ }
433
+ async cancelDownload(uuid) {
434
+ await this._browser.session.send('Browser.cancelDownload', {
435
+ uuid
436
+ });
437
+ }
438
+ }
439
+ exports.FFBrowserContext = FFBrowserContext;
440
+ function toJugglerProxyOptions(proxy) {
441
+ const proxyServer = new URL(proxy.server);
442
+ let port = parseInt(proxyServer.port, 10);
443
+ let type = 'http';
444
+ if (proxyServer.protocol === 'socks5:') type = 'socks';else if (proxyServer.protocol === 'socks4:') type = 'socks4';else if (proxyServer.protocol === 'https:') type = 'https';
445
+ if (proxyServer.port === '') {
446
+ if (proxyServer.protocol === 'http:') port = 80;else if (proxyServer.protocol === 'https:') port = 443;
447
+ }
448
+ return {
449
+ type,
450
+ bypass: proxy.bypass ? proxy.bypass.split(',').map(domain => domain.trim()) : [],
451
+ host: proxyServer.hostname,
452
+ port,
453
+ username: proxy.username,
454
+ password: proxy.password
455
+ };
456
+ }
457
+
458
+ // Prefs for quick fixes that didn't make it to the build.
459
+ // Should all be moved to `playwright.cfg`.
460
+ const kBandaidFirefoxUserPrefs = {};
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.kBrowserCloseMessageId = exports.FFSession = exports.FFConnection = exports.ConnectionEvents = void 0;
7
+ var _events = require("events");
8
+ var _debugLogger = require("../../utils/debugLogger");
9
+ var _helper = require("../helper");
10
+ var _protocolError = require("../protocolError");
11
+ /**
12
+ * Copyright 2017 Google Inc. All rights reserved.
13
+ * Modifications copyright (c) Microsoft Corporation.
14
+ *
15
+ * Licensed under the Apache License, Version 2.0 (the 'License');
16
+ * you may not use this file except in compliance with the License.
17
+ * You may obtain a copy of the License at
18
+ *
19
+ * http://www.apache.org/licenses/LICENSE-2.0
20
+ *
21
+ * Unless required by applicable law or agreed to in writing, software
22
+ * distributed under the License is distributed on an 'AS IS' BASIS,
23
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ * See the License for the specific language governing permissions and
25
+ * limitations under the License.
26
+ */
27
+
28
+ const ConnectionEvents = exports.ConnectionEvents = {
29
+ Disconnected: Symbol('Disconnected')
30
+ };
31
+
32
+ // FFPlaywright uses this special id to issue Browser.close command which we
33
+ // should ignore.
34
+ const kBrowserCloseMessageId = exports.kBrowserCloseMessageId = -9999;
35
+ class FFConnection extends _events.EventEmitter {
36
+ constructor(transport, protocolLogger, browserLogsCollector) {
37
+ super();
38
+ this._lastId = void 0;
39
+ this._transport = void 0;
40
+ this._protocolLogger = void 0;
41
+ this._browserLogsCollector = void 0;
42
+ this._browserDisconnectedLogs = void 0;
43
+ this.rootSession = void 0;
44
+ this._sessions = void 0;
45
+ this._closed = void 0;
46
+ this.setMaxListeners(0);
47
+ this._transport = transport;
48
+ this._protocolLogger = protocolLogger;
49
+ this._browserLogsCollector = browserLogsCollector;
50
+ this._lastId = 0;
51
+ this._sessions = new Map();
52
+ this._closed = false;
53
+ this.rootSession = new FFSession(this, '', message => this._rawSend(message));
54
+ this._sessions.set('', this.rootSession);
55
+ this._transport.onmessage = this._onMessage.bind(this);
56
+ // onclose should be set last, since it can be immediately called.
57
+ this._transport.onclose = this._onClose.bind(this);
58
+ }
59
+ nextMessageId() {
60
+ return ++this._lastId;
61
+ }
62
+ _rawSend(message) {
63
+ this._protocolLogger('send', message);
64
+ this._transport.send(message);
65
+ }
66
+ async _onMessage(message) {
67
+ this._protocolLogger('receive', message);
68
+ if (message.id === kBrowserCloseMessageId) return;
69
+ const session = this._sessions.get(message.sessionId || '');
70
+ if (session) session.dispatchMessage(message);
71
+ }
72
+ _onClose(reason) {
73
+ this._closed = true;
74
+ this._transport.onmessage = undefined;
75
+ this._transport.onclose = undefined;
76
+ this._browserDisconnectedLogs = _helper.helper.formatBrowserLogs(this._browserLogsCollector.recentLogs(), reason);
77
+ this.rootSession.dispose();
78
+ Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
79
+ }
80
+ close() {
81
+ if (!this._closed) this._transport.close();
82
+ }
83
+ createSession(sessionId) {
84
+ const session = new FFSession(this, sessionId, message => this._rawSend({
85
+ ...message,
86
+ sessionId
87
+ }));
88
+ this._sessions.set(sessionId, session);
89
+ return session;
90
+ }
91
+ }
92
+ exports.FFConnection = FFConnection;
93
+ class FFSession extends _events.EventEmitter {
94
+ constructor(connection, sessionId, rawSend) {
95
+ super();
96
+ this._connection = void 0;
97
+ this._disposed = false;
98
+ this._callbacks = void 0;
99
+ this._sessionId = void 0;
100
+ this._rawSend = void 0;
101
+ this._crashed = false;
102
+ this.on = void 0;
103
+ this.addListener = void 0;
104
+ this.off = void 0;
105
+ this.removeListener = void 0;
106
+ this.once = void 0;
107
+ this.setMaxListeners(0);
108
+ this._callbacks = new Map();
109
+ this._connection = connection;
110
+ this._sessionId = sessionId;
111
+ this._rawSend = rawSend;
112
+ this.on = super.on;
113
+ this.addListener = super.addListener;
114
+ this.off = super.removeListener;
115
+ this.removeListener = super.removeListener;
116
+ this.once = super.once;
117
+ }
118
+ markAsCrashed() {
119
+ this._crashed = true;
120
+ }
121
+ async send(method, params) {
122
+ if (this._crashed || this._disposed || this._connection._closed || this._connection._browserDisconnectedLogs) throw new _protocolError.ProtocolError(this._crashed ? 'crashed' : 'closed', undefined, this._connection._browserDisconnectedLogs);
123
+ const id = this._connection.nextMessageId();
124
+ this._rawSend({
125
+ method,
126
+ params,
127
+ id
128
+ });
129
+ return new Promise((resolve, reject) => {
130
+ this._callbacks.set(id, {
131
+ resolve,
132
+ reject,
133
+ error: new _protocolError.ProtocolError('error', method)
134
+ });
135
+ });
136
+ }
137
+ sendMayFail(method, params) {
138
+ return this.send(method, params).catch(error => _debugLogger.debugLogger.log('error', error));
139
+ }
140
+ dispatchMessage(object) {
141
+ if (object.id) {
142
+ const callback = this._callbacks.get(object.id);
143
+ // Callbacks could be all rejected if someone has called `.dispose()`.
144
+ if (callback) {
145
+ this._callbacks.delete(object.id);
146
+ if (object.error) {
147
+ callback.error.setMessage(object.error.message);
148
+ callback.reject(callback.error);
149
+ } else {
150
+ callback.resolve(object.result);
151
+ }
152
+ }
153
+ } else {
154
+ Promise.resolve().then(() => this.emit(object.method, object.params));
155
+ }
156
+ }
157
+ dispose() {
158
+ this._disposed = true;
159
+ this._connection._sessions.delete(this._sessionId);
160
+ for (const callback of this._callbacks.values()) {
161
+ callback.error.type = this._crashed ? 'crashed' : 'closed';
162
+ callback.error.logs = this._connection._browserDisconnectedLogs;
163
+ callback.reject(callback.error);
164
+ }
165
+ this._callbacks.clear();
166
+ }
167
+ }
168
+ exports.FFSession = FFSession;