playwright-browserstack 1.62.0__py3-none-win32.whl
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.
- playwright/__init__.py +19 -0
- playwright/__main__.py +33 -0
- playwright/_impl/__init__.py +0 -0
- playwright/_impl/__pyinstaller/__init__.py +20 -0
- playwright/_impl/__pyinstaller/hook-playwright.async_api.py +17 -0
- playwright/_impl/__pyinstaller/hook-playwright.sync_api.py +17 -0
- playwright/_impl/_android.py +704 -0
- playwright/_impl/_api_structures.py +365 -0
- playwright/_impl/_artifact.py +87 -0
- playwright/_impl/_assertions.py +1124 -0
- playwright/_impl/_async_base.py +105 -0
- playwright/_impl/_browser.py +293 -0
- playwright/_impl/_browser_context.py +754 -0
- playwright/_impl/_browser_type.py +368 -0
- playwright/_impl/_cdp_session.py +46 -0
- playwright/_impl/_clock.py +104 -0
- playwright/_impl/_connection.py +764 -0
- playwright/_impl/_console_message.py +98 -0
- playwright/_impl/_credentials.py +57 -0
- playwright/_impl/_debugger.py +54 -0
- playwright/_impl/_dialog.py +63 -0
- playwright/_impl/_disposable.py +96 -0
- playwright/_impl/_download.py +64 -0
- playwright/_impl/_driver.py +41 -0
- playwright/_impl/_element_handle.py +480 -0
- playwright/_impl/_errors.py +64 -0
- playwright/_impl/_event_context_manager.py +33 -0
- playwright/_impl/_fetch.py +626 -0
- playwright/_impl/_file_chooser.py +57 -0
- playwright/_impl/_form_data.py +34 -0
- playwright/_impl/_frame.py +985 -0
- playwright/_impl/_glob.py +65 -0
- playwright/_impl/_greenlets.py +49 -0
- playwright/_impl/_har_router.py +122 -0
- playwright/_impl/_helper.py +601 -0
- playwright/_impl/_impl_to_api_mapping.py +158 -0
- playwright/_impl/_input.py +111 -0
- playwright/_impl/_js_handle.py +336 -0
- playwright/_impl/_json_pipe.py +97 -0
- playwright/_impl/_local_utils.py +95 -0
- playwright/_impl/_locator.py +1024 -0
- playwright/_impl/_map.py +31 -0
- playwright/_impl/_network.py +1017 -0
- playwright/_impl/_object_factory.py +116 -0
- playwright/_impl/_page.py +1637 -0
- playwright/_impl/_path_utils.py +27 -0
- playwright/_impl/_playwright.py +68 -0
- playwright/_impl/_screencast.py +177 -0
- playwright/_impl/_selectors.py +67 -0
- playwright/_impl/_set_input_files_helpers.py +158 -0
- playwright/_impl/_str_utils.py +76 -0
- playwright/_impl/_stream.py +46 -0
- playwright/_impl/_sync_base.py +151 -0
- playwright/_impl/_tracing.py +281 -0
- playwright/_impl/_transport.py +184 -0
- playwright/_impl/_video.py +56 -0
- playwright/_impl/_waiter.py +197 -0
- playwright/_impl/_web_error.py +48 -0
- playwright/_impl/_web_storage.py +58 -0
- playwright/_impl/_writable_stream.py +42 -0
- playwright/_repo_version.py +24 -0
- playwright/async_api/__init__.py +275 -0
- playwright/async_api/_android_generated.py +462 -0
- playwright/async_api/_context_manager.py +57 -0
- playwright/async_api/_generated.py +23875 -0
- playwright/driver/LICENSE +2946 -0
- playwright/driver/README.md +1 -0
- playwright/driver/node.exe +0 -0
- playwright/driver/package/LICENSE +202 -0
- playwright/driver/package/NOTICE +5 -0
- playwright/driver/package/README.md +3 -0
- playwright/driver/package/ThirdPartyNotices.txt +13 -0
- playwright/driver/package/bin/install_media_pack.ps1 +5 -0
- playwright/driver/package/bin/install_webkit_wsl.ps1 +33 -0
- playwright/driver/package/bin/reinstall_chrome_beta_linux.sh +42 -0
- playwright/driver/package/bin/reinstall_chrome_beta_mac.sh +13 -0
- playwright/driver/package/bin/reinstall_chrome_beta_win.ps1 +24 -0
- playwright/driver/package/bin/reinstall_chrome_stable_linux.sh +42 -0
- playwright/driver/package/bin/reinstall_chrome_stable_mac.sh +12 -0
- playwright/driver/package/bin/reinstall_chrome_stable_win.ps1 +24 -0
- playwright/driver/package/bin/reinstall_msedge_beta_linux.sh +48 -0
- playwright/driver/package/bin/reinstall_msedge_beta_mac.sh +11 -0
- playwright/driver/package/bin/reinstall_msedge_beta_win.ps1 +23 -0
- playwright/driver/package/bin/reinstall_msedge_dev_linux.sh +48 -0
- playwright/driver/package/bin/reinstall_msedge_dev_mac.sh +11 -0
- playwright/driver/package/bin/reinstall_msedge_dev_win.ps1 +23 -0
- playwright/driver/package/bin/reinstall_msedge_stable_linux.sh +48 -0
- playwright/driver/package/bin/reinstall_msedge_stable_mac.sh +11 -0
- playwright/driver/package/bin/reinstall_msedge_stable_win.ps1 +24 -0
- playwright/driver/package/browsers.json +75 -0
- playwright/driver/package/cli.js +21 -0
- playwright/driver/package/index.d.ts +17 -0
- playwright/driver/package/index.js +17 -0
- playwright/driver/package/index.mjs +28 -0
- playwright/driver/package/lib/bootstrap.js +88 -0
- playwright/driver/package/lib/coreBundle.js +74830 -0
- playwright/driver/package/lib/entry/cliDaemon.js +5 -0
- playwright/driver/package/lib/entry/dashboardApp.js +3 -0
- playwright/driver/package/lib/entry/mcp.js +10 -0
- playwright/driver/package/lib/entry/oopBrowserDownload.js +3 -0
- playwright/driver/package/lib/package.js +50 -0
- playwright/driver/package/lib/server/chromium/appIcon.png +0 -0
- playwright/driver/package/lib/server/electron/loader.js +118 -0
- playwright/driver/package/lib/serverRegistry.js +7347 -0
- playwright/driver/package/lib/serverRegistry.js.LICENSE +354 -0
- playwright/driver/package/lib/tools/cli-client/channelSessions.js +141 -0
- playwright/driver/package/lib/tools/cli-client/cli.js +6 -0
- playwright/driver/package/lib/tools/cli-client/help.json +708 -0
- playwright/driver/package/lib/tools/cli-client/minimist.js +128 -0
- playwright/driver/package/lib/tools/cli-client/output.js +343 -0
- playwright/driver/package/lib/tools/cli-client/program.js +404 -0
- playwright/driver/package/lib/tools/cli-client/registry.js +176 -0
- playwright/driver/package/lib/tools/cli-client/session.js +258 -0
- playwright/driver/package/lib/tools/dashboard/appIcon.png +0 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/SKILL.md +420 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/SKILL.md +143 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/migration.md +85 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/react.md +67 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/vue.md +75 -0
- playwright/driver/package/lib/tools/skills/playwright-trace/SKILL.md +171 -0
- playwright/driver/package/lib/tools/utils/extension.js +101 -0
- playwright/driver/package/lib/tools/utils/socketConnection.js +108 -0
- playwright/driver/package/lib/utilsBundle.js +90764 -0
- playwright/driver/package/lib/utilsBundle.js.LICENSE +2179 -0
- playwright/driver/package/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
- playwright/driver/package/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/index-CyWAfh-p.js +11 -0
- playwright/driver/package/lib/vite/dashboard/assets/index-DhC616m4.css +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/index.html +29 -0
- playwright/driver/package/lib/vite/dashboard/playwright-logo.svg +24 -0
- playwright/driver/package/lib/vite/htmlReport/index.html +16 -0
- playwright/driver/package/lib/vite/htmlReport/report.css +2 -0
- playwright/driver/package/lib/vite/htmlReport/report.js +32 -0
- playwright/driver/package/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
- playwright/driver/package/lib/vite/recorder/assets/codeMirrorModule-CwYYHbcZ.js +32 -0
- playwright/driver/package/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
- playwright/driver/package/lib/vite/recorder/assets/index-DYjdXIbE.js +129 -0
- playwright/driver/package/lib/vite/recorder/assets/index-l_lX622x.css +1 -0
- playwright/driver/package/lib/vite/recorder/index.html +29 -0
- playwright/driver/package/lib/vite/recorder/playwright-logo.svg +9 -0
- playwright/driver/package/lib/vite/traceViewer/assets/codeMirrorModule-By56iMx7.js +32 -0
- playwright/driver/package/lib/vite/traceViewer/assets/defaultSettingsView-B34OrIms.js +181 -0
- playwright/driver/package/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
- playwright/driver/package/lib/vite/traceViewer/assets/xtermModule-COQkjINf.js +7 -0
- playwright/driver/package/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
- playwright/driver/package/lib/vite/traceViewer/defaultSettingsView.BLFoOugd.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/index.Dl36UVQT.js +1 -0
- playwright/driver/package/lib/vite/traceViewer/index.html +44 -0
- playwright/driver/package/lib/vite/traceViewer/manifest.webmanifest +16 -0
- playwright/driver/package/lib/vite/traceViewer/playwright-logo.svg +9 -0
- playwright/driver/package/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
- playwright/driver/package/lib/vite/traceViewer/snapshot.html +10 -0
- playwright/driver/package/lib/vite/traceViewer/sw.bundle.js +4 -0
- playwright/driver/package/lib/vite/traceViewer/uiMode.C7UW1sC9.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/uiMode.D962mr9b.js +5 -0
- playwright/driver/package/lib/vite/traceViewer/uiMode.html +18 -0
- playwright/driver/package/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
- playwright/driver/package/lib/webp_codec.LICENSE +173 -0
- playwright/driver/package/lib/webp_codec.wasm +0 -0
- playwright/driver/package/lib/xdg-open +1267 -0
- playwright/driver/package/package.json +34 -0
- playwright/driver/package/types/protocol.d.ts +24842 -0
- playwright/driver/package/types/structs.d.ts +47 -0
- playwright/driver/package/types/types.d.ts +26188 -0
- playwright/py.typed +0 -0
- playwright/sync_api/__init__.py +275 -0
- playwright/sync_api/_android_generated.py +494 -0
- playwright/sync_api/_context_manager.py +98 -0
- playwright/sync_api/_generated.py +24045 -0
- playwright_browserstack-1.62.0.dist-info/METADATA +82 -0
- playwright_browserstack-1.62.0.dist-info/RECORD +192 -0
- playwright_browserstack-1.62.0.dist-info/WHEEL +5 -0
- playwright_browserstack-1.62.0.dist-info/entry_points.txt +5 -0
- playwright_browserstack-1.62.0.dist-info/licenses/LICENSE +202 -0
- playwright_browserstack-1.62.0.dist-info/licenses/LICENSE.txt +51 -0
- playwright_browserstack-1.62.0.dist-info/licenses/NOTICE +18 -0
- playwright_browserstack-1.62.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,754 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import asyncio
|
|
16
|
+
import json
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from types import SimpleNamespace
|
|
19
|
+
from typing import (
|
|
20
|
+
TYPE_CHECKING,
|
|
21
|
+
Any,
|
|
22
|
+
Callable,
|
|
23
|
+
Dict,
|
|
24
|
+
List,
|
|
25
|
+
Literal,
|
|
26
|
+
Optional,
|
|
27
|
+
Pattern,
|
|
28
|
+
Sequence,
|
|
29
|
+
Set,
|
|
30
|
+
Union,
|
|
31
|
+
cast,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
from playwright._impl._api_structures import (
|
|
35
|
+
Cookie,
|
|
36
|
+
Geolocation,
|
|
37
|
+
SetCookieParam,
|
|
38
|
+
StorageState,
|
|
39
|
+
WebErrorLocation,
|
|
40
|
+
)
|
|
41
|
+
from playwright._impl._cdp_session import CDPSession
|
|
42
|
+
from playwright._impl._clock import Clock
|
|
43
|
+
from playwright._impl._connection import (
|
|
44
|
+
ChannelOwner,
|
|
45
|
+
from_channel,
|
|
46
|
+
from_nullable_channel,
|
|
47
|
+
)
|
|
48
|
+
from playwright._impl._console_message import ConsoleMessage
|
|
49
|
+
from playwright._impl._credentials import Credentials
|
|
50
|
+
from playwright._impl._debugger import Debugger
|
|
51
|
+
from playwright._impl._dialog import Dialog
|
|
52
|
+
from playwright._impl._disposable import Disposable, DisposableStub
|
|
53
|
+
from playwright._impl._errors import Error, TargetClosedError
|
|
54
|
+
from playwright._impl._event_context_manager import EventContextManagerImpl
|
|
55
|
+
from playwright._impl._fetch import APIRequestContext
|
|
56
|
+
from playwright._impl._frame import Frame
|
|
57
|
+
from playwright._impl._har_router import HarRouter
|
|
58
|
+
from playwright._impl._helper import (
|
|
59
|
+
HarContentPolicy,
|
|
60
|
+
HarMode,
|
|
61
|
+
RouteFromHarNotFoundPolicy,
|
|
62
|
+
RouteHandler,
|
|
63
|
+
RouteHandlerCallback,
|
|
64
|
+
TimeoutSettings,
|
|
65
|
+
URLMatch,
|
|
66
|
+
WebSocketRouteHandlerCallback,
|
|
67
|
+
async_readfile,
|
|
68
|
+
async_writefile,
|
|
69
|
+
create_task_and_ignore_exception,
|
|
70
|
+
locals_to_params,
|
|
71
|
+
parse_error,
|
|
72
|
+
to_impl,
|
|
73
|
+
)
|
|
74
|
+
from playwright._impl._network import (
|
|
75
|
+
Request,
|
|
76
|
+
Response,
|
|
77
|
+
Route,
|
|
78
|
+
WebSocketRoute,
|
|
79
|
+
WebSocketRouteHandler,
|
|
80
|
+
serialize_headers,
|
|
81
|
+
)
|
|
82
|
+
from playwright._impl._page import BindingCall, Page, Worker
|
|
83
|
+
from playwright._impl._str_utils import escape_regex_flags
|
|
84
|
+
from playwright._impl._tracing import Tracing
|
|
85
|
+
from playwright._impl._waiter import Waiter
|
|
86
|
+
from playwright._impl._web_error import WebError
|
|
87
|
+
|
|
88
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
89
|
+
from playwright._impl._browser import Browser
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class BrowserContext(ChannelOwner):
|
|
93
|
+
Events = SimpleNamespace(
|
|
94
|
+
# Deprecated in v1.56, never emitted anymore.
|
|
95
|
+
BackgroundPage="backgroundpage",
|
|
96
|
+
Close="close",
|
|
97
|
+
Console="console",
|
|
98
|
+
Dialog="dialog",
|
|
99
|
+
Download="download",
|
|
100
|
+
FrameAttached="frameattached",
|
|
101
|
+
FrameDetached="framedetached",
|
|
102
|
+
FrameNavigated="framenavigated",
|
|
103
|
+
Page="page",
|
|
104
|
+
PageClose="pageclose",
|
|
105
|
+
PageLoad="pageload",
|
|
106
|
+
WebError="weberror",
|
|
107
|
+
ServiceWorker="serviceworker",
|
|
108
|
+
Request="request",
|
|
109
|
+
Response="response",
|
|
110
|
+
RequestFailed="requestfailed",
|
|
111
|
+
RequestFinished="requestfinished",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def __init__(
|
|
115
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
116
|
+
) -> None:
|
|
117
|
+
super().__init__(parent, type, guid, initializer)
|
|
118
|
+
# Browser is null for browser contexts created outside of normal browser, e.g. android or electron.
|
|
119
|
+
# circular import workaround:
|
|
120
|
+
self._browser: Optional["Browser"] = None
|
|
121
|
+
if parent.__class__.__name__ == "Browser":
|
|
122
|
+
self._browser = cast("Browser", parent)
|
|
123
|
+
self._pages: List[Page] = []
|
|
124
|
+
self._routes: List[RouteHandler] = []
|
|
125
|
+
self._web_socket_routes: List[WebSocketRouteHandler] = []
|
|
126
|
+
self._bindings: Dict[str, Any] = {}
|
|
127
|
+
self._timeout_settings = TimeoutSettings(None)
|
|
128
|
+
self._owner_page: Optional[Page] = None
|
|
129
|
+
self._options: Dict[str, Any] = initializer["options"]
|
|
130
|
+
self._service_workers: Set[Worker] = set()
|
|
131
|
+
self._base_url: Optional[str] = self._options.get("baseURL")
|
|
132
|
+
self._videos_dir: Optional[str] = self._options.get("recordVideo")
|
|
133
|
+
self._tracing = cast(Tracing, from_channel(initializer["tracing"]))
|
|
134
|
+
self._debugger: Debugger = cast(Debugger, from_channel(initializer["debugger"]))
|
|
135
|
+
self._request: APIRequestContext = from_channel(initializer["requestContext"])
|
|
136
|
+
self._request._timeout_settings = self._timeout_settings
|
|
137
|
+
self._clock = Clock(self)
|
|
138
|
+
self._credentials = Credentials(self)
|
|
139
|
+
self._channel.on(
|
|
140
|
+
"bindingCall",
|
|
141
|
+
lambda params: self._on_binding(from_channel(params["binding"])),
|
|
142
|
+
)
|
|
143
|
+
self._channel.on("close", lambda _: self._on_close())
|
|
144
|
+
self._channel.on(
|
|
145
|
+
"page", lambda params: self._on_page(from_channel(params["page"]))
|
|
146
|
+
)
|
|
147
|
+
self._channel.on(
|
|
148
|
+
"route",
|
|
149
|
+
lambda params: self._loop.create_task(
|
|
150
|
+
self._on_route(
|
|
151
|
+
from_channel(params.get("route")),
|
|
152
|
+
)
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
self._channel.on(
|
|
156
|
+
"webSocketRoute",
|
|
157
|
+
lambda params: self._loop.create_task(
|
|
158
|
+
self._on_web_socket_route(
|
|
159
|
+
from_channel(params["webSocketRoute"]),
|
|
160
|
+
)
|
|
161
|
+
),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
self._channel.on(
|
|
165
|
+
"serviceWorker",
|
|
166
|
+
lambda params: self._on_service_worker(from_channel(params["worker"])),
|
|
167
|
+
)
|
|
168
|
+
self._channel.on(
|
|
169
|
+
"console",
|
|
170
|
+
lambda event: self._on_console_message(event),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
self._channel.on(
|
|
174
|
+
"dialog", lambda params: self._on_dialog(from_channel(params["dialog"]))
|
|
175
|
+
)
|
|
176
|
+
self._channel.on(
|
|
177
|
+
"pageError",
|
|
178
|
+
lambda params: self._on_page_error(
|
|
179
|
+
parse_error(params["error"]["error"]),
|
|
180
|
+
from_nullable_channel(params["page"]),
|
|
181
|
+
cast(
|
|
182
|
+
WebErrorLocation,
|
|
183
|
+
params.get("location") or {"url": "", "line": 0, "column": 0},
|
|
184
|
+
),
|
|
185
|
+
),
|
|
186
|
+
)
|
|
187
|
+
self._channel.on(
|
|
188
|
+
"request",
|
|
189
|
+
lambda params: self._on_request(
|
|
190
|
+
from_channel(params["request"]),
|
|
191
|
+
from_nullable_channel(params.get("page")),
|
|
192
|
+
),
|
|
193
|
+
)
|
|
194
|
+
self._channel.on(
|
|
195
|
+
"response",
|
|
196
|
+
lambda params: self._on_response(
|
|
197
|
+
from_channel(params["response"]),
|
|
198
|
+
from_nullable_channel(params.get("page")),
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
self._channel.on(
|
|
202
|
+
"requestFailed",
|
|
203
|
+
lambda params: self._on_request_failed(
|
|
204
|
+
from_channel(params["request"]),
|
|
205
|
+
params["responseEndTiming"],
|
|
206
|
+
params.get("failureText"),
|
|
207
|
+
from_nullable_channel(params.get("page")),
|
|
208
|
+
),
|
|
209
|
+
)
|
|
210
|
+
self._channel.on(
|
|
211
|
+
"requestFinished",
|
|
212
|
+
lambda params: self._on_request_finished(
|
|
213
|
+
from_channel(params["request"]),
|
|
214
|
+
from_nullable_channel(params.get("response")),
|
|
215
|
+
params["responseEndTiming"],
|
|
216
|
+
from_nullable_channel(params.get("page")),
|
|
217
|
+
),
|
|
218
|
+
)
|
|
219
|
+
self._closed_future: asyncio.Future = asyncio.Future()
|
|
220
|
+
self.once(
|
|
221
|
+
self.Events.Close, lambda context: self._closed_future.set_result(True)
|
|
222
|
+
)
|
|
223
|
+
self._close_reason: Optional[str] = None
|
|
224
|
+
self._har_routers: List[HarRouter] = []
|
|
225
|
+
self._set_event_to_subscription_mapping(
|
|
226
|
+
{
|
|
227
|
+
BrowserContext.Events.Console: "console",
|
|
228
|
+
BrowserContext.Events.Dialog: "dialog",
|
|
229
|
+
BrowserContext.Events.Request: "request",
|
|
230
|
+
BrowserContext.Events.Response: "response",
|
|
231
|
+
BrowserContext.Events.RequestFinished: "requestFinished",
|
|
232
|
+
BrowserContext.Events.RequestFailed: "requestFailed",
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
self._closing_or_closed = False
|
|
236
|
+
|
|
237
|
+
def __repr__(self) -> str:
|
|
238
|
+
return f"<BrowserContext browser={self.browser}>"
|
|
239
|
+
|
|
240
|
+
def _on_page(self, page: Page) -> None:
|
|
241
|
+
self._pages.append(page)
|
|
242
|
+
self.emit(BrowserContext.Events.Page, page)
|
|
243
|
+
if page._opener and not page._opener.is_closed():
|
|
244
|
+
page._opener.emit(Page.Events.Popup, page)
|
|
245
|
+
|
|
246
|
+
async def _on_route(self, route: Route) -> None:
|
|
247
|
+
route._context = self
|
|
248
|
+
page = route.request._safe_page()
|
|
249
|
+
route_handlers = self._routes.copy()
|
|
250
|
+
for route_handler in route_handlers:
|
|
251
|
+
# If the page or the context was closed we stall all requests right away.
|
|
252
|
+
if (page and page._close_was_called) or self._closing_or_closed:
|
|
253
|
+
return
|
|
254
|
+
if not route_handler.matches(route.request.url):
|
|
255
|
+
continue
|
|
256
|
+
if route_handler not in self._routes:
|
|
257
|
+
continue
|
|
258
|
+
if route_handler.will_expire:
|
|
259
|
+
self._routes.remove(route_handler)
|
|
260
|
+
try:
|
|
261
|
+
handled = await route_handler.handle(route)
|
|
262
|
+
finally:
|
|
263
|
+
if len(self._routes) == 0:
|
|
264
|
+
create_task_and_ignore_exception(
|
|
265
|
+
self._loop,
|
|
266
|
+
self._connection.wrap_api_call(
|
|
267
|
+
lambda: self._update_interception_patterns(), True
|
|
268
|
+
),
|
|
269
|
+
)
|
|
270
|
+
if handled:
|
|
271
|
+
return
|
|
272
|
+
try:
|
|
273
|
+
# If the page is closed or unrouteAll() was called without waiting and interception disabled,
|
|
274
|
+
# the method will throw an error - silence it.
|
|
275
|
+
await route._inner_continue(True)
|
|
276
|
+
except Exception:
|
|
277
|
+
pass
|
|
278
|
+
|
|
279
|
+
async def _on_web_socket_route(self, web_socket_route: WebSocketRoute) -> None:
|
|
280
|
+
route_handler = next(
|
|
281
|
+
(
|
|
282
|
+
route_handler
|
|
283
|
+
for route_handler in self._web_socket_routes
|
|
284
|
+
if route_handler.matches(web_socket_route.url)
|
|
285
|
+
),
|
|
286
|
+
None,
|
|
287
|
+
)
|
|
288
|
+
if route_handler:
|
|
289
|
+
await route_handler.handle(web_socket_route)
|
|
290
|
+
else:
|
|
291
|
+
web_socket_route.connect_to_server()
|
|
292
|
+
|
|
293
|
+
def _on_binding(self, binding_call: BindingCall) -> None:
|
|
294
|
+
func = self._bindings.get(binding_call._initializer["name"])
|
|
295
|
+
if func is None:
|
|
296
|
+
return
|
|
297
|
+
asyncio.create_task(binding_call.call(func))
|
|
298
|
+
|
|
299
|
+
def set_default_navigation_timeout(self, timeout: float) -> None:
|
|
300
|
+
return self._set_default_navigation_timeout_impl(timeout)
|
|
301
|
+
|
|
302
|
+
def _set_default_navigation_timeout_impl(self, timeout: Optional[float]) -> None:
|
|
303
|
+
self._timeout_settings.set_default_navigation_timeout(timeout)
|
|
304
|
+
|
|
305
|
+
def set_default_timeout(self, timeout: float) -> None:
|
|
306
|
+
return self._set_default_timeout_impl(timeout)
|
|
307
|
+
|
|
308
|
+
def _set_default_timeout_impl(self, timeout: Optional[float]) -> None:
|
|
309
|
+
self._timeout_settings.set_default_timeout(timeout)
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def pages(self) -> List[Page]:
|
|
313
|
+
return self._pages.copy()
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def browser(self) -> Optional["Browser"]:
|
|
317
|
+
return self._browser
|
|
318
|
+
|
|
319
|
+
async def _initialize_har_from_options(
|
|
320
|
+
self,
|
|
321
|
+
record_har_path: Optional[Union[Path, str]],
|
|
322
|
+
record_har_content: Optional[HarContentPolicy],
|
|
323
|
+
record_har_omit_content: Optional[bool],
|
|
324
|
+
record_har_url_filter: Optional[Union[Pattern[str], str]],
|
|
325
|
+
record_har_mode: Optional[HarMode],
|
|
326
|
+
) -> None:
|
|
327
|
+
if not record_har_path:
|
|
328
|
+
return
|
|
329
|
+
record_har_path = str(record_har_path)
|
|
330
|
+
default_policy: HarContentPolicy = (
|
|
331
|
+
"attach" if record_har_path.endswith(".zip") else "embed"
|
|
332
|
+
)
|
|
333
|
+
content_policy: HarContentPolicy = record_har_content or (
|
|
334
|
+
"omit" if record_har_omit_content is True else default_policy
|
|
335
|
+
)
|
|
336
|
+
await self._tracing._record_into_har(
|
|
337
|
+
har=record_har_path,
|
|
338
|
+
page=None,
|
|
339
|
+
url=record_har_url_filter,
|
|
340
|
+
update_content=content_policy,
|
|
341
|
+
update_mode=(record_har_mode or "full"),
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
async def new_page(self) -> Page:
|
|
345
|
+
if self._owner_page:
|
|
346
|
+
raise Error("Please use browser.new_context()")
|
|
347
|
+
return from_channel(await self._channel.send("newPage", None))
|
|
348
|
+
|
|
349
|
+
async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
|
|
350
|
+
if urls is None:
|
|
351
|
+
urls = []
|
|
352
|
+
if isinstance(urls, str):
|
|
353
|
+
urls = [urls]
|
|
354
|
+
return await self._channel.send("cookies", None, dict(urls=urls))
|
|
355
|
+
|
|
356
|
+
async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
|
|
357
|
+
await self._channel.send("addCookies", None, dict(cookies=cookies))
|
|
358
|
+
|
|
359
|
+
async def clear_cookies(
|
|
360
|
+
self,
|
|
361
|
+
name: Union[str, Pattern[str]] = None,
|
|
362
|
+
domain: Union[str, Pattern[str]] = None,
|
|
363
|
+
path: Union[str, Pattern[str]] = None,
|
|
364
|
+
) -> None:
|
|
365
|
+
await self._channel.send(
|
|
366
|
+
"clearCookies",
|
|
367
|
+
None,
|
|
368
|
+
{
|
|
369
|
+
"name": name if isinstance(name, str) else None,
|
|
370
|
+
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
|
|
371
|
+
"nameRegexFlags": (
|
|
372
|
+
escape_regex_flags(name) if isinstance(name, Pattern) else None
|
|
373
|
+
),
|
|
374
|
+
"domain": domain if isinstance(domain, str) else None,
|
|
375
|
+
"domainRegexSource": (
|
|
376
|
+
domain.pattern if isinstance(domain, Pattern) else None
|
|
377
|
+
),
|
|
378
|
+
"domainRegexFlags": (
|
|
379
|
+
escape_regex_flags(domain) if isinstance(domain, Pattern) else None
|
|
380
|
+
),
|
|
381
|
+
"path": path if isinstance(path, str) else None,
|
|
382
|
+
"pathRegexSource": path.pattern if isinstance(path, Pattern) else None,
|
|
383
|
+
"pathRegexFlags": (
|
|
384
|
+
escape_regex_flags(path) if isinstance(path, Pattern) else None
|
|
385
|
+
),
|
|
386
|
+
},
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
async def grant_permissions(
|
|
390
|
+
self, permissions: Sequence[str], origin: str = None
|
|
391
|
+
) -> None:
|
|
392
|
+
await self._channel.send("grantPermissions", None, locals_to_params(locals()))
|
|
393
|
+
|
|
394
|
+
async def clear_permissions(self) -> None:
|
|
395
|
+
await self._channel.send("clearPermissions", None)
|
|
396
|
+
|
|
397
|
+
async def set_geolocation(self, geolocation: Geolocation = None) -> None:
|
|
398
|
+
await self._channel.send("setGeolocation", None, locals_to_params(locals()))
|
|
399
|
+
|
|
400
|
+
async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
|
|
401
|
+
await self._channel.send(
|
|
402
|
+
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
async def set_offline(self, offline: bool) -> None:
|
|
406
|
+
await self._channel.send("setOffline", None, dict(offline=offline))
|
|
407
|
+
|
|
408
|
+
async def add_init_script(
|
|
409
|
+
self, script: str = None, path: Union[str, Path] = None
|
|
410
|
+
) -> Disposable:
|
|
411
|
+
if path:
|
|
412
|
+
script = (await async_readfile(path)).decode()
|
|
413
|
+
if not isinstance(script, str):
|
|
414
|
+
raise Error("Either path or script parameter must be specified")
|
|
415
|
+
return from_channel(
|
|
416
|
+
await self._channel.send("addInitScript", None, dict(source=script))
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
async def expose_binding(self, name: str, callback: Callable) -> Disposable:
|
|
420
|
+
for page in self._pages:
|
|
421
|
+
if name in page._bindings:
|
|
422
|
+
raise Error(
|
|
423
|
+
f'Function "{name}" has been already registered in one of the pages'
|
|
424
|
+
)
|
|
425
|
+
if name in self._bindings:
|
|
426
|
+
raise Error(f'Function "{name}" has been already registered')
|
|
427
|
+
self._bindings[name] = callback
|
|
428
|
+
return from_channel(
|
|
429
|
+
await self._channel.send("exposeBinding", None, dict(name=name))
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
async def expose_function(self, name: str, callback: Callable) -> Disposable:
|
|
433
|
+
return await self.expose_binding(name, lambda source, *args: callback(*args))
|
|
434
|
+
|
|
435
|
+
async def route(
|
|
436
|
+
self, url: URLMatch, handler: RouteHandlerCallback, times: int = None
|
|
437
|
+
) -> DisposableStub:
|
|
438
|
+
self._routes.insert(
|
|
439
|
+
0,
|
|
440
|
+
RouteHandler(
|
|
441
|
+
self._base_url,
|
|
442
|
+
url,
|
|
443
|
+
handler,
|
|
444
|
+
True if self._dispatcher_fiber else False,
|
|
445
|
+
times,
|
|
446
|
+
),
|
|
447
|
+
)
|
|
448
|
+
await self._update_interception_patterns()
|
|
449
|
+
return DisposableStub(lambda: self.unroute(url, handler), self)
|
|
450
|
+
|
|
451
|
+
async def unroute(
|
|
452
|
+
self, url: URLMatch, handler: Optional[RouteHandlerCallback] = None
|
|
453
|
+
) -> None:
|
|
454
|
+
removed = []
|
|
455
|
+
remaining = []
|
|
456
|
+
for route in self._routes:
|
|
457
|
+
if route.url != url or (handler and route.handler != handler):
|
|
458
|
+
remaining.append(route)
|
|
459
|
+
else:
|
|
460
|
+
removed.append(route)
|
|
461
|
+
await self._unroute_internal(removed, remaining, "default")
|
|
462
|
+
|
|
463
|
+
async def _unroute_internal(
|
|
464
|
+
self,
|
|
465
|
+
removed: List[RouteHandler],
|
|
466
|
+
remaining: List[RouteHandler],
|
|
467
|
+
behavior: Literal["default", "ignoreErrors", "wait"] = None,
|
|
468
|
+
) -> None:
|
|
469
|
+
self._routes = remaining
|
|
470
|
+
if behavior is not None and behavior != "default":
|
|
471
|
+
await asyncio.gather(*map(lambda router: router.stop(behavior), removed)) # type: ignore
|
|
472
|
+
await self._update_interception_patterns()
|
|
473
|
+
|
|
474
|
+
async def route_web_socket(
|
|
475
|
+
self, url: URLMatch, handler: WebSocketRouteHandlerCallback
|
|
476
|
+
) -> None:
|
|
477
|
+
self._web_socket_routes.insert(
|
|
478
|
+
0,
|
|
479
|
+
WebSocketRouteHandler(self._base_url, url, handler),
|
|
480
|
+
)
|
|
481
|
+
await self._update_web_socket_interception_patterns()
|
|
482
|
+
|
|
483
|
+
def _dispose_har_routers(self) -> None:
|
|
484
|
+
for router in self._har_routers:
|
|
485
|
+
router.dispose()
|
|
486
|
+
self._har_routers = []
|
|
487
|
+
|
|
488
|
+
async def unroute_all(
|
|
489
|
+
self, behavior: Literal["default", "ignoreErrors", "wait"] = None
|
|
490
|
+
) -> None:
|
|
491
|
+
await self._unroute_internal(self._routes, [], behavior)
|
|
492
|
+
self._dispose_har_routers()
|
|
493
|
+
|
|
494
|
+
async def route_from_har(
|
|
495
|
+
self,
|
|
496
|
+
har: Union[Path, str],
|
|
497
|
+
url: Union[Pattern[str], str] = None,
|
|
498
|
+
notFound: RouteFromHarNotFoundPolicy = None,
|
|
499
|
+
update: bool = None,
|
|
500
|
+
updateContent: Literal["attach", "embed"] = None,
|
|
501
|
+
updateMode: HarMode = None,
|
|
502
|
+
) -> None:
|
|
503
|
+
if update:
|
|
504
|
+
await self._tracing._record_into_har(
|
|
505
|
+
har=har,
|
|
506
|
+
page=None,
|
|
507
|
+
url=url,
|
|
508
|
+
update_content=updateContent,
|
|
509
|
+
update_mode=updateMode,
|
|
510
|
+
)
|
|
511
|
+
return
|
|
512
|
+
router = await HarRouter.create(
|
|
513
|
+
local_utils=self._connection.local_utils,
|
|
514
|
+
file=str(har),
|
|
515
|
+
not_found_action=notFound or "abort",
|
|
516
|
+
url_matcher=url,
|
|
517
|
+
)
|
|
518
|
+
self._har_routers.append(router)
|
|
519
|
+
await router.add_context_route(self)
|
|
520
|
+
|
|
521
|
+
async def _update_interception_patterns(self) -> None:
|
|
522
|
+
patterns = RouteHandler.prepare_interception_patterns(self._routes)
|
|
523
|
+
await self._channel.send(
|
|
524
|
+
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
async def _update_web_socket_interception_patterns(self) -> None:
|
|
528
|
+
patterns = WebSocketRouteHandler.prepare_interception_patterns(
|
|
529
|
+
self._web_socket_routes
|
|
530
|
+
)
|
|
531
|
+
await self._channel.send(
|
|
532
|
+
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
def expect_event(
|
|
536
|
+
self,
|
|
537
|
+
event: str,
|
|
538
|
+
predicate: Callable = None,
|
|
539
|
+
timeout: float = None,
|
|
540
|
+
) -> EventContextManagerImpl:
|
|
541
|
+
if timeout is None:
|
|
542
|
+
timeout = self._timeout_settings.timeout()
|
|
543
|
+
waiter = Waiter(self, f"browser_context.expect_event({event})")
|
|
544
|
+
waiter.reject_on_timeout(
|
|
545
|
+
timeout, f'Timeout {timeout}ms exceeded while waiting for event "{event}"'
|
|
546
|
+
)
|
|
547
|
+
if event != BrowserContext.Events.Close:
|
|
548
|
+
waiter.reject_on_event(
|
|
549
|
+
self, BrowserContext.Events.Close, lambda: TargetClosedError()
|
|
550
|
+
)
|
|
551
|
+
waiter.wait_for_event(self, event, predicate)
|
|
552
|
+
return EventContextManagerImpl(waiter.result())
|
|
553
|
+
|
|
554
|
+
def _on_close(self) -> None:
|
|
555
|
+
self._closing_or_closed = True
|
|
556
|
+
if self._browser:
|
|
557
|
+
if self in self._browser._contexts:
|
|
558
|
+
self._browser._contexts.remove(self)
|
|
559
|
+
assert self._browser._browser_type is not None
|
|
560
|
+
if (
|
|
561
|
+
self
|
|
562
|
+
in self._browser._browser_type._playwright.selectors._contexts_for_selectors
|
|
563
|
+
):
|
|
564
|
+
self._browser._browser_type._playwright.selectors._contexts_for_selectors.remove(
|
|
565
|
+
self
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
self._dispose_har_routers()
|
|
569
|
+
self._tracing._reset_stack_counter()
|
|
570
|
+
self.emit(BrowserContext.Events.Close, self)
|
|
571
|
+
|
|
572
|
+
def is_closed(self) -> bool:
|
|
573
|
+
return self._closing_or_closed
|
|
574
|
+
|
|
575
|
+
async def close(self, reason: str = None) -> None:
|
|
576
|
+
if self._closing_or_closed:
|
|
577
|
+
return
|
|
578
|
+
self._close_reason = reason
|
|
579
|
+
self._closing_or_closed = True
|
|
580
|
+
|
|
581
|
+
await self.request.dispose(reason=reason)
|
|
582
|
+
|
|
583
|
+
async def _inner_close() -> None:
|
|
584
|
+
await self._tracing._export_all_hars()
|
|
585
|
+
|
|
586
|
+
await self._channel._connection.wrap_api_call(_inner_close, True)
|
|
587
|
+
await self._channel.send("close", None, {"reason": reason})
|
|
588
|
+
await self._closed_future
|
|
589
|
+
|
|
590
|
+
async def storage_state(
|
|
591
|
+
self,
|
|
592
|
+
path: Union[str, Path] = None,
|
|
593
|
+
indexedDB: bool = None,
|
|
594
|
+
credentials: bool = None,
|
|
595
|
+
) -> StorageState:
|
|
596
|
+
result = await self._channel.send_return_as_dict(
|
|
597
|
+
"storageState", None, {"indexedDB": indexedDB, "credentials": credentials}
|
|
598
|
+
)
|
|
599
|
+
if path:
|
|
600
|
+
await async_writefile(path, json.dumps(result))
|
|
601
|
+
return result
|
|
602
|
+
|
|
603
|
+
async def set_storage_state(
|
|
604
|
+
self, storageState: Union[StorageState, str, Path]
|
|
605
|
+
) -> None:
|
|
606
|
+
if isinstance(storageState, (str, Path)):
|
|
607
|
+
state = json.loads(await async_readfile(storageState))
|
|
608
|
+
else:
|
|
609
|
+
state = storageState
|
|
610
|
+
await self._channel.send("setStorageState", None, {"storageState": state})
|
|
611
|
+
|
|
612
|
+
def _effective_close_reason(self) -> Optional[str]:
|
|
613
|
+
if self._close_reason:
|
|
614
|
+
return self._close_reason
|
|
615
|
+
if self._browser:
|
|
616
|
+
return self._browser._close_reason
|
|
617
|
+
return None
|
|
618
|
+
|
|
619
|
+
async def wait_for_event(
|
|
620
|
+
self, event: str, predicate: Callable = None, timeout: float = None
|
|
621
|
+
) -> Any:
|
|
622
|
+
async with self.expect_event(event, predicate, timeout) as event_info:
|
|
623
|
+
pass
|
|
624
|
+
return await event_info
|
|
625
|
+
|
|
626
|
+
def expect_console_message(
|
|
627
|
+
self,
|
|
628
|
+
predicate: Callable[[ConsoleMessage], bool] = None,
|
|
629
|
+
timeout: float = None,
|
|
630
|
+
) -> EventContextManagerImpl[ConsoleMessage]:
|
|
631
|
+
return self.expect_event(Page.Events.Console, predicate, timeout)
|
|
632
|
+
|
|
633
|
+
def expect_page(
|
|
634
|
+
self,
|
|
635
|
+
predicate: Callable[[Page], bool] = None,
|
|
636
|
+
timeout: float = None,
|
|
637
|
+
) -> EventContextManagerImpl[Page]:
|
|
638
|
+
return self.expect_event(BrowserContext.Events.Page, predicate, timeout)
|
|
639
|
+
|
|
640
|
+
def _on_service_worker(self, worker: Worker) -> None:
|
|
641
|
+
worker._context = self
|
|
642
|
+
self._service_workers.add(worker)
|
|
643
|
+
self.emit(BrowserContext.Events.ServiceWorker, worker)
|
|
644
|
+
|
|
645
|
+
def _on_request_failed(
|
|
646
|
+
self,
|
|
647
|
+
request: Request,
|
|
648
|
+
response_end_timing: float,
|
|
649
|
+
failure_text: Optional[str],
|
|
650
|
+
page: Optional[Page],
|
|
651
|
+
) -> None:
|
|
652
|
+
request._failure_text = failure_text
|
|
653
|
+
request._set_response_end_timing(response_end_timing)
|
|
654
|
+
self.emit(BrowserContext.Events.RequestFailed, request)
|
|
655
|
+
if page:
|
|
656
|
+
page.emit(Page.Events.RequestFailed, request)
|
|
657
|
+
|
|
658
|
+
def _on_request_finished(
|
|
659
|
+
self,
|
|
660
|
+
request: Request,
|
|
661
|
+
response: Optional[Response],
|
|
662
|
+
response_end_timing: float,
|
|
663
|
+
page: Optional[Page],
|
|
664
|
+
) -> None:
|
|
665
|
+
request._set_response_end_timing(response_end_timing)
|
|
666
|
+
self.emit(BrowserContext.Events.RequestFinished, request)
|
|
667
|
+
if page:
|
|
668
|
+
page.emit(Page.Events.RequestFinished, request)
|
|
669
|
+
if response:
|
|
670
|
+
response._finished_future.set_result(True)
|
|
671
|
+
|
|
672
|
+
def _on_console_message(self, event: Dict) -> None:
|
|
673
|
+
message = ConsoleMessage(event, self._loop, self._dispatcher_fiber)
|
|
674
|
+
worker = message.worker
|
|
675
|
+
if worker:
|
|
676
|
+
worker.emit(Worker.Events.Console, message)
|
|
677
|
+
page = message.page
|
|
678
|
+
if page:
|
|
679
|
+
page.emit(Page.Events.Console, message)
|
|
680
|
+
self.emit(BrowserContext.Events.Console, message)
|
|
681
|
+
|
|
682
|
+
def _on_dialog(self, dialog: Dialog) -> None:
|
|
683
|
+
has_listeners = self.emit(BrowserContext.Events.Dialog, dialog)
|
|
684
|
+
page = dialog.page
|
|
685
|
+
if page:
|
|
686
|
+
has_listeners = page.emit(Page.Events.Dialog, dialog) or has_listeners
|
|
687
|
+
if not has_listeners:
|
|
688
|
+
# Although we do similar handling on the server side, we still need this logic
|
|
689
|
+
# on the client side due to a possible race condition between two async calls:
|
|
690
|
+
# a) removing "dialog" listener subscription (client->server)
|
|
691
|
+
# b) actual "dialog" event (server->client)
|
|
692
|
+
if dialog.type == "beforeunload":
|
|
693
|
+
create_task_and_ignore_exception(self._loop, dialog.accept())
|
|
694
|
+
else:
|
|
695
|
+
create_task_and_ignore_exception(self._loop, dialog.dismiss())
|
|
696
|
+
|
|
697
|
+
def _on_page_error(
|
|
698
|
+
self, error: Error, page: Optional[Page], location: WebErrorLocation
|
|
699
|
+
) -> None:
|
|
700
|
+
self.emit(
|
|
701
|
+
BrowserContext.Events.WebError,
|
|
702
|
+
WebError(self._loop, self._dispatcher_fiber, page, error, location),
|
|
703
|
+
)
|
|
704
|
+
if page:
|
|
705
|
+
page.emit(Page.Events.PageError, error)
|
|
706
|
+
|
|
707
|
+
def _on_request(self, request: Request, page: Optional[Page]) -> None:
|
|
708
|
+
self.emit(BrowserContext.Events.Request, request)
|
|
709
|
+
if page:
|
|
710
|
+
page.emit(Page.Events.Request, request)
|
|
711
|
+
|
|
712
|
+
def _on_response(self, response: Response, page: Optional[Page]) -> None:
|
|
713
|
+
self.emit(BrowserContext.Events.Response, response)
|
|
714
|
+
if page:
|
|
715
|
+
page.emit(Page.Events.Response, response)
|
|
716
|
+
|
|
717
|
+
@property
|
|
718
|
+
def background_pages(self) -> List[Page]:
|
|
719
|
+
return []
|
|
720
|
+
|
|
721
|
+
@property
|
|
722
|
+
def service_workers(self) -> List[Worker]:
|
|
723
|
+
return list(self._service_workers)
|
|
724
|
+
|
|
725
|
+
async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
|
|
726
|
+
page = to_impl(page)
|
|
727
|
+
params = {}
|
|
728
|
+
if isinstance(page, Page):
|
|
729
|
+
params["page"] = page._channel
|
|
730
|
+
elif isinstance(page, Frame):
|
|
731
|
+
params["frame"] = page._channel
|
|
732
|
+
else:
|
|
733
|
+
raise Error("page: expected Page or Frame")
|
|
734
|
+
return from_channel(await self._channel.send("newCDPSession", None, params))
|
|
735
|
+
|
|
736
|
+
@property
|
|
737
|
+
def tracing(self) -> Tracing:
|
|
738
|
+
return self._tracing
|
|
739
|
+
|
|
740
|
+
@property
|
|
741
|
+
def debugger(self) -> Debugger:
|
|
742
|
+
return self._debugger
|
|
743
|
+
|
|
744
|
+
@property
|
|
745
|
+
def request(self) -> "APIRequestContext":
|
|
746
|
+
return self._request
|
|
747
|
+
|
|
748
|
+
@property
|
|
749
|
+
def clock(self) -> Clock:
|
|
750
|
+
return self._clock
|
|
751
|
+
|
|
752
|
+
@property
|
|
753
|
+
def credentials(self) -> Credentials:
|
|
754
|
+
return self._credentials
|