How to use _updateExtraHTTPHeaders method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

crPage.js

Source: crPage.js Github

copy
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4  value: true
5});
6exports.CRPage = void 0;
7
8var dom = _interopRequireWildcard(require("../dom"));
9
10var _helper = require("../helper");
11
12var _eventsHelper = require("../../utils/eventsHelper");
13
14var network = _interopRequireWildcard(require("../network"));
15
16var _crConnection = require("./crConnection");
17
18var _crExecutionContext = require("./crExecutionContext");
19
20var _crNetworkManager = require("./crNetworkManager");
21
22var _page = require("../page");
23
24var _crProtocolHelper = require("./crProtocolHelper");
25
26var dialog = _interopRequireWildcard(require("../dialog"));
27
28var _path = _interopRequireDefault(require("path"));
29
30var _crInput = require("./crInput");
31
32var _crAccessibility = require("./crAccessibility");
33
34var _crCoverage = require("./crCoverage");
35
36var _crPdf = require("./crPdf");
37
38var _crBrowser = require("./crBrowser");
39
40var _stackTrace = require("../../utils/stackTrace");
41
42var _utils = require("../../utils/utils");
43
44var _videoRecorder = require("./videoRecorder");
45
46var _crDragDrop = require("./crDragDrop");
47
48var _registry = require("../../utils/registry");
49
50function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
51
52function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
53
54function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
55
56/**
57 * Copyright 2017 Google Inc. All rights reserved.
58 * Modifications copyright (c) Microsoft Corporation.
59 *
60 * Licensed under the Apache License, Version 2.0 (the "License");
61 * you may not use this file except in compliance with the License.
62 * You may obtain a copy of the License at
63 *
64 *     http://www.apache.org/licenses/LICENSE-2.0
65 *
66 * Unless required by applicable law or agreed to in writing, software
67 * distributed under the License is distributed on an "AS IS" BASIS,
68 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69 * See the License for the specific language governing permissions and
70 * limitations under the License.
71 */
72const UTILITY_WORLD_NAME = '__playwright_utility_world__';
73
74class CRPage {
75  // Holds window features for the next popup being opened via window.open,
76  // until the popup target arrives. This could be racy if two oopifs
77  // simultaneously call window.open with window features: the order
78  // of their Page.windowOpen events is not guaranteed to match the order
79  // of new popup targets.
80  static mainFrameSession(page) {
81    const crPage = page._delegate;
82    return crPage._mainFrameSession;
83  }
84
85  constructor(client, targetId, browserContext, opener, hasUIWindow, isBackgroundPage) {
86    this._mainFrameSession = void 0;
87    this._sessions = new Map();
88    this._page = void 0;
89    this.rawMouse = void 0;
90    this.rawKeyboard = void 0;
91    this.rawTouchscreen = void 0;
92    this._targetId = void 0;
93    this._opener = void 0;
94    this._pdf = void 0;
95    this._coverage = void 0;
96    this._browserContext = void 0;
97    this._pagePromise = void 0;
98    this._initializedPage = null;
99    this._isBackgroundPage = void 0;
100    this._nextWindowOpenPopupFeatures = [];
101    this._targetId = targetId;
102    this._opener = opener;
103    this._isBackgroundPage = isBackgroundPage;
104    const dragManager = new _crDragDrop.DragManager(this);
105    this.rawKeyboard = new _crInput.RawKeyboardImpl(client, browserContext._browser._isMac, dragManager);
106    this.rawMouse = new _crInput.RawMouseImpl(this, client, dragManager);
107    this.rawTouchscreen = new _crInput.RawTouchscreenImpl(client);
108    this._pdf = new _crPdf.CRPDF(client);
109    this._coverage = new _crCoverage.CRCoverage(client);
110    this._browserContext = browserContext;
111    this._page = new _page.Page(this, browserContext);
112    this._mainFrameSession = new FrameSession(this, client, targetId, null);
113
114    this._sessions.set(targetId, this._mainFrameSession);
115
116    client.once(_crConnection.CRSessionEvents.Disconnected, () => this._page._didDisconnect());
117
118    if (opener && !browserContext._options.noDefaultViewport) {
119      const features = opener._nextWindowOpenPopupFeatures.shift() || [];
120
121      const viewportSize = _helper.helper.getViewportSizeFromWindowFeatures(features);
122
123      if (viewportSize) this._page._state.emulatedSize = {
124        viewport: viewportSize,
125        screen: viewportSize
126      };
127    } // Note: it is important to call |reportAsNew| before resolving pageOrError promise,
128    // so that anyone who awaits pageOrError got a ready and reported page.
129
130
131    this._pagePromise = this._mainFrameSession._initialize(hasUIWindow).then(async r => {
132      await this._page.initOpener(this._opener);
133      return r;
134    }).catch(async e => {
135      await this._page.initOpener(this._opener);
136      throw e;
137    }).then(() => {
138      this._initializedPage = this._page;
139
140      this._reportAsNew();
141
142      return this._page;
143    }).catch(e => {
144      this._reportAsNew(e);
145
146      return e;
147    });
148  }
149
150  _reportAsNew(error) {
151    if (this._isBackgroundPage) {
152      if (!error) this._browserContext.emit(_crBrowser.CRBrowserContext.CREvents.BackgroundPage, this._page);
153    } else {
154      this._page.reportAsNew(error);
155    }
156  }
157
158  async _forAllFrameSessions(cb) {
159    const frameSessions = Array.from(this._sessions.values());
160    await Promise.all(frameSessions.map(frameSession => {
161      if (frameSession._isMainFrame()) return cb(frameSession);
162      return cb(frameSession).catch(e => {
163        // Broadcasting a message to the closed iframe shoule be a noop.
164        if (e.message && (e.message.includes('Target closed.') || e.message.includes('Session closed.'))) return;
165        throw e;
166      });
167    }));
168  }
169
170  _sessionForFrame(frame) {
171    // Frame id equals target id.
172    while (!this._sessions.has(frame._id)) {
173      const parent = frame.parentFrame();
174      if (!parent) throw new Error(`Frame has been detached.`);
175      frame = parent;
176    }
177
178    return this._sessions.get(frame._id);
179  }
180
181  _sessionForHandle(handle) {
182    const frame = handle._context.frame;
183    return this._sessionForFrame(frame);
184  }
185
186  willBeginDownload() {
187    this._mainFrameSession._willBeginDownload();
188  }
189
190  async pageOrError() {
191    return this._pagePromise;
192  }
193
194  didClose() {
195    for (const session of this._sessions.values()) session.dispose();
196
197    this._page._didClose();
198  }
199
200  async navigateFrame(frame, url, referrer) {
201    return this._sessionForFrame(frame)._navigate(frame, url, referrer);
202  }
203
204  async exposeBinding(binding) {
205    await this._forAllFrameSessions(frame => frame._initBinding(binding));
206    await Promise.all(this._page.frames().map(frame => frame.evaluateExpression(binding.source, false, {}).catch(e => {})));
207  }
208
209  async updateExtraHTTPHeaders() {
210    await this._forAllFrameSessions(frame => frame._updateExtraHTTPHeaders(false));
211  }
212
213  async updateGeolocation() {
214    await this._forAllFrameSessions(frame => frame._updateGeolocation(false));
215  }
216
217  async updateOffline() {
218    await this._forAllFrameSessions(frame => frame._updateOffline(false));
219  }
220
221  async updateHttpCredentials() {
222    await this._forAllFrameSessions(frame => frame._updateHttpCredentials(false));
223  }
224
225  async setEmulatedSize(emulatedSize) {
226    (0, _utils.assert)(this._page._state.emulatedSize === emulatedSize);
227    await this._mainFrameSession._updateViewport();
228  }
229
230  async bringToFront() {
231    await this._mainFrameSession._client.send('Page.bringToFront');
232  }
233
234  async updateEmulateMedia() {
235    await this._forAllFrameSessions(frame => frame._updateEmulateMedia(false));
236  }
237
238  async updateRequestInterception() {
239    await this._forAllFrameSessions(frame => frame._updateRequestInterception());
240  }
241
242  async setFileChooserIntercepted(enabled) {
243    await this._forAllFrameSessions(frame => frame._setFileChooserIntercepted(enabled));
244  }
245
246  async reload() {
247    await this._mainFrameSession._client.send('Page.reload');
248  }
249
250  async _go(delta) {
251    const history = await this._mainFrameSession._client.send('Page.getNavigationHistory');
252    const entry = history.entries[history.currentIndex + delta];
253    if (!entry) return false;
254    await this._mainFrameSession._client.send('Page.navigateToHistoryEntry', {
255      entryId: entry.id
256    });
257    return true;
258  }
259
260  goBack() {
261    return this._go(-1);
262  }
263
264  goForward() {
265    return this._go(+1);
266  }
267
268  async evaluateOnNewDocument(source, world = 'main') {
269    await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(source, world));
270  }
271
272  async closePage(runBeforeUnload) {
273    if (runBeforeUnload) await this._mainFrameSession._client.send('Page.close');else await this._browserContext._browser._closePage(this);
274  }
275
276  async setBackgroundColor(color) {
277    await this._mainFrameSession._client.send('Emulation.setDefaultBackgroundColorOverride', {
278      color
279    });
280  }
281
282  async takeScreenshot(progress, format, documentRect, viewportRect, quality, fitsViewport) {
283    const {
284      visualViewport
285    } = await this._mainFrameSession._client.send('Page.getLayoutMetrics');
286
287    if (!documentRect) {
288      documentRect = {
289        x: visualViewport.pageX + viewportRect.x,
290        y: visualViewport.pageY + viewportRect.y,
291        ..._helper.helper.enclosingIntSize({
292          width: viewportRect.width / visualViewport.scale,
293          height: viewportRect.height / visualViewport.scale
294        })
295      };
296    } // When taking screenshots with documentRect (based on the page content, not viewport),
297    // ignore current page scale.
298
299
300    const clip = { ...documentRect,
301      scale: viewportRect ? visualViewport.scale : 1
302    };
303    progress.throwIfAborted();
304    const result = await this._mainFrameSession._client.send('Page.captureScreenshot', {
305      format,
306      quality,
307      clip,
308      captureBeyondViewport: !fitsViewport
309    });
310    return Buffer.from(result.data, 'base64');
311  }
312
313  async getContentFrame(handle) {
314    return this._sessionForHandle(handle)._getContentFrame(handle);
315  }
316
317  async getOwnerFrame(handle) {
318    return this._sessionForHandle(handle)._getOwnerFrame(handle);
319  }
320
321  isElementHandle(remoteObject) {
322    return remoteObject.subtype === 'node';
323  }
324
325  async getBoundingBox(handle) {
326    return this._sessionForHandle(handle)._getBoundingBox(handle);
327  }
328
329  async scrollRectIntoViewIfNeeded(handle, rect) {
330    return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect);
331  }
332
333  async setScreencastOptions(options) {
334    if (options) {
335      await this._mainFrameSession._startScreencast(this, {
336        format: 'jpeg',
337        quality: options.quality,
338        maxWidth: options.width,
339        maxHeight: options.height
340      });
341    } else {
342      await this._mainFrameSession._stopScreencast(this);
343    }
344  }
345
346  rafCountForStablePosition() {
347    return 1;
348  }
349
350  async getContentQuads(handle) {
351    return this._sessionForHandle(handle)._getContentQuads(handle);
352  }
353
354  async setInputFiles(handle, files) {
355    await handle.evaluateInUtility(([injected, node, files]) => injected.setInputFiles(node, files), files);
356  }
357
358  async adoptElementHandle(handle, to) {
359    return this._sessionForHandle(handle)._adoptElementHandle(handle, to);
360  }
361
362  async getAccessibilityTree(needle) {
363    return (0, _crAccessibility.getAccessibilityTree)(this._mainFrameSession._client, needle);
364  }
365
366  async inputActionEpilogue() {
367    await this._mainFrameSession._client.send('Page.enable').catch(e => {});
368  }
369
370  async pdf(options) {
371    return this._pdf.generate(options);
372  }
373
374  coverage() {
375    return this._coverage;
376  }
377
378  async getFrameElement(frame) {
379    let parent = frame.parentFrame();
380    if (!parent) throw new Error('Frame has been detached.');
381
382    const parentSession = this._sessionForFrame(parent);
383
384    const {
385      backendNodeId
386    } = await parentSession._client.send('DOM.getFrameOwner', {
387      frameId: frame._id
388    }).catch(e => {
389      if (e instanceof Error && e.message.includes('Frame with the given id was not found.')) (0, _stackTrace.rewriteErrorMessage)(e, 'Frame has been detached.');
390      throw e;
391    });
392    parent = frame.parentFrame();
393    if (!parent) throw new Error('Frame has been detached.');
394    return parentSession._adoptBackendNodeId(backendNodeId, await parent._mainContext());
395  }
396
397}
398
399exports.CRPage = CRPage;
400
401class FrameSession {
402  // Marks the oopif session that remote -> local transition has happened in the parent.
403  // See Target.detachedFromTarget handler for details.
404  constructor(crPage, client, targetId, parentSession) {
405    this._client = void 0;
406    this._crPage = void 0;
407    this._page = void 0;
408    this._networkManager = void 0;
409    this._contextIdToContext = new Map();
410    this._eventListeners = [];
411    this._targetId = void 0;
412    this._firstNonInitialNavigationCommittedPromise = void 0;
413
414    this._firstNonInitialNavigationCommittedFulfill = () => {};
415
416    this._firstNonInitialNavigationCommittedReject = e => {};
417
418    this._windowId = void 0;
419    this._swappedIn = false;
420    this._videoRecorder = null;
421    this._screencastId = null;
422    this._screencastClients = new Set();
423    this._client = client;
424    this._crPage = crPage;
425    this._page = crPage._page;
426    this._targetId = targetId;
427    this._networkManager = new _crNetworkManager.CRNetworkManager(client, this._page, parentSession ? parentSession._networkManager : null);
428    this._firstNonInitialNavigationCommittedPromise = new Promise((f, r) => {
429      this._firstNonInitialNavigationCommittedFulfill = f;
430      this._firstNonInitialNavigationCommittedReject = r;
431    });
432    client.once(_crConnection.CRSessionEvents.Disconnected, () => {
433      this._firstNonInitialNavigationCommittedReject(new Error('Page closed'));
434    });
435  }
436
437  _isMainFrame() {
438    return this._targetId === this._crPage._targetId;
439  }
440
441  _addRendererListeners() {
442    this._eventListeners.push(...[_eventsHelper.eventsHelper.addEventListener(this._client, 'Log.entryAdded', event => this._onLogEntryAdded(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameDetached', event => this._onFrameDetached(event.frameId, event.reason)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame, false)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameRequestedNavigation', event => this._onFrameRequestedNavigation(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.javascriptDialogOpening', event => this._onDialog(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.bindingCalled', event => this._onBindingCalled(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.consoleAPICalled', event => this._onConsoleAPI(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.executionContextsCleared', event => this._onExecutionContextsCleared()), _eventsHelper.eventsHelper.addEventListener(this._client, 'Target.attachedToTarget', event => this._onAttachedToTarget(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Target.detachedFromTarget', event => this._onDetachedFromTarget(event))]);
443  }
444
445  _addBrowserListeners() {
446    this._eventListeners.push(...[_eventsHelper.eventsHelper.addEventListener(this._client, 'Inspector.targetCrashed', event => this._onTargetCrashed()), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.screencastFrame', event => this._onScreencastFrame(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.windowOpen', event => this._onWindowOpen(event))]);
447  }
448
449  async _initialize(hasUIWindow) {
450    if (hasUIWindow && !this._crPage._browserContext._browser.isClank() && !this._crPage._browserContext._options.noDefaultViewport) {
451      const {
452        windowId
453      } = await this._client.send('Browser.getWindowForTarget');
454      this._windowId = windowId;
455    }
456
457    let screencastOptions;
458
459    if (this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
460      const screencastId = (0, _utils.createGuid)();
461
462      const outputFile = _path.default.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + '.webm');
463
464      screencastOptions = { // validateBrowserContextOptions ensures correct video size.
465        ...this._crPage._browserContext._options.recordVideo.size,
466        outputFile
467      };
468      await this._crPage._browserContext._ensureVideosPath(); // Note: it is important to start video recorder before sending Page.startScreencast,
469      // and it is equally important to send Page.startScreencast before sending Runtime.runIfWaitingForDebugger.
470
471      await this._createVideoRecorder(screencastId, screencastOptions);
472
473      this._crPage.pageOrError().then(p => {
474        if (p instanceof Error) this._stopVideoRecording().catch(() => {});
475      });
476    }
477
478    let lifecycleEventsEnabled;
479    if (!this._isMainFrame()) this._addRendererListeners();
480
481    this._addBrowserListeners();
482
483    const promises = [this._client.send('Page.enable'), this._client.send('Page.getFrameTree').then(({
484      frameTree
485    }) => {
486      if (this._isMainFrame()) {
487        this._handleFrameTree(frameTree);
488
489        this._addRendererListeners();
490      }
491
492      const localFrames = this._isMainFrame() ? this._page.frames() : [this._page._frameManager.frame(this._targetId)];
493
494      for (const frame of localFrames) {
495        // Note: frames might be removed before we send these.
496        this._client._sendMayFail('Page.createIsolatedWorld', {
497          frameId: frame._id,
498          grantUniveralAccess: true,
499          worldName: UTILITY_WORLD_NAME
500        });
501
502        for (const binding of this._crPage._browserContext._pageBindings.values()) frame.evaluateExpression(binding.source, false, undefined).catch(e => {});
503
504        for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources) frame.evaluateExpression(source, false, undefined, 'main').catch(e => {});
505      }
506
507      const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':';
508
509      if (isInitialEmptyPage) {
510        // Ignore lifecycle events for the initial empty page. It is never the final page
511        // hence we are going to get more lifecycle updates after the actual navigation has
512        // started (even if the target url is about:blank).
513        lifecycleEventsEnabled.catch(e => {}).then(() => {
514          this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));
515        });
516      } else {
517        this._firstNonInitialNavigationCommittedFulfill();
518
519        this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));
520      }
521    }), this._client.send('Log.enable', {}), lifecycleEventsEnabled = this._client.send('Page.setLifecycleEventsEnabled', {
522      enabled: true
523    }), this._client.send('Runtime.enable', {}), this._client.send('Page.addScriptToEvaluateOnNewDocument', {
524      source: '',
525      worldName: UTILITY_WORLD_NAME
526    }), this._networkManager.initialize(), this._client.send('Target.setAutoAttach', {
527      autoAttach: true,
528      waitForDebuggerOnStart: true,
529      flatten: true
530    })];
531    if (this._isMainFrame()) promises.push(this._client.send('Emulation.setFocusEmulationEnabled', {
532      enabled: true
533    }));
534    const options = this._crPage._browserContext._options;
535    if (options.bypassCSP) promises.push(this._client.send('Page.setBypassCSP', {
536      enabled: true
537    }));
538    if (options.ignoreHTTPSErrors) promises.push(this._client.send('Security.setIgnoreCertificateErrors', {
539      ignore: true
540    }));
541    if (this._isMainFrame()) promises.push(this._updateViewport());
542    if (options.hasTouch) promises.push(this._client.send('Emulation.setTouchEmulationEnabled', {
543      enabled: true
544    }));
545    if (options.javaScriptEnabled === false) promises.push(this._client.send('Emulation.setScriptExecutionDisabled', {
546      value: true
547    }));
548    if (options.userAgent || options.locale) promises.push(this._client.send('Emulation.setUserAgentOverride', {
549      userAgent: options.userAgent || '',
550      acceptLanguage: options.locale
551    }));
552    if (options.locale) promises.push(emulateLocale(this._client, options.locale));
553    if (options.timezoneId) promises.push(emulateTimezone(this._client, options.timezoneId));
554    promises.push(this._updateGeolocation(true));
555    promises.push(this._updateExtraHTTPHeaders(true));
556    promises.push(this._updateRequestInterception());
557    promises.push(this._updateOffline(true));
558    promises.push(this._updateHttpCredentials(true));
559    promises.push(this._updateEmulateMedia(true));
560
561    for (const binding of this._crPage._page.allBindings()) promises.push(this._initBinding(binding));
562
563    for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources) promises.push(this._evaluateOnNewDocument(source, 'main'));
564
565    for (const source of this._crPage._page._evaluateOnNewDocumentSources) promises.push(this._evaluateOnNewDocument(source, 'main'));
566
567    if (screencastOptions) promises.push(this._startVideoRecording(screencastOptions));
568    promises.push(this._client.send('Runtime.runIfWaitingForDebugger'));
569    promises.push(this._firstNonInitialNavigationCommittedPromise);
570    await Promise.all(promises);
571  }
572
573  dispose() {
574    _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
575
576    this._networkManager.dispose();
577
578    this._crPage._sessions.delete(this._targetId);
579  }
580
581  async _navigate(frame, url, referrer) {
582    const response = await this._client.send('Page.navigate', {
583      url,
584      referrer,
585      frameId: frame._id
586    });
587    if (response.errorText) throw new Error(`${response.errorText} at ${url}`);
588    return {
589      newDocumentId: response.loaderId
590    };
591  }
592
593  _onLifecycleEvent(event) {
594    if (this._eventBelongsToStaleFrame(event.frameId)) return;
595    if (event.name === 'load') this._page._frameManager.frameLifecycleEvent(event.frameId, 'load');else if (event.name === 'DOMContentLoaded') this._page._frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded');
596  }
597
598  _onFrameStoppedLoading(frameId) {
599    if (this._eventBelongsToStaleFrame(frameId)) return;
600
601    this._page._frameManager.frameStoppedLoading(frameId);
602  }
603
604  _handleFrameTree(frameTree) {
605    this._onFrameAttached(frameTree.frame.id, frameTree.frame.parentId || null);
606
607    this._onFrameNavigated(frameTree.frame, true);
608
609    if (!frameTree.childFrames) return;
610
611    for (const child of frameTree.childFrames) this._handleFrameTree(child);
612  }
613
614  _eventBelongsToStaleFrame(frameId) {
615    const frame = this._page._frameManager.frame(frameId); // Subtree may be already gone because some ancestor navigation destroyed the oopif.
616
617
618    if (!frame) return true; // When frame goes remote, parent process may still send some events
619    // related to the local frame before it sends frameDetached.
620    // In this case, we already have a new session for this frame, so events
621    // in the old session should be ignored.
622
623    const session = this._crPage._sessionForFrame(frame);
624
625    return session && session !== this && !session._swappedIn;
626  }
627
628  _onFrameAttached(frameId, parentFrameId) {
629    const frameSession = this._crPage._sessions.get(frameId);
630
631    if (frameSession && frameId !== this._targetId) {
632      // This is a remote -> local frame transition.
633      frameSession._swappedIn = true;
634
635      const frame = this._page._frameManager.frame(frameId); // Frame or even a whole subtree may be already gone, because some ancestor did navigate.
636
637
638      if (frame) this._page._frameManager.removeChildFramesRecursively(frame);
639      return;
640    }
641
642    if (parentFrameId && !this._page._frameManager.frame(parentFrameId)) {
643      // Parent frame may be gone already because some ancestor frame navigated and
644      // destroyed the whole subtree of some oopif, while oopif's process is still sending us events.
645      // Be careful to not confuse this with "main frame navigated cross-process" scenario
646      // where parentFrameId is null.
647      return;
648    }
649
650    this._page._frameManager.frameAttached(frameId, parentFrameId);
651  }
652
653  _onFrameNavigated(framePayload, initial) {
654    if (this._eventBelongsToStaleFrame(framePayload.id)) return;
655
656    this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url + (framePayload.urlFragment || ''), framePayload.name || '', framePayload.loaderId, initial);
657
658    if (!initial) this._firstNonInitialNavigationCommittedFulfill();
659  }
660
661  _onFrameRequestedNavigation(payload) {
662    if (this._eventBelongsToStaleFrame(payload.frameId)) return;
663    if (payload.disposition === 'currentTab') this._page._frameManager.frameRequestedNavigation(payload.frameId);
664  }
665
666  _onFrameNavigatedWithinDocument(frameId, url) {
667    if (this._eventBelongsToStaleFrame(frameId)) return;
668
669    this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);
670  }
671
672  _onFrameDetached(frameId, reason) {
673    if (this._crPage._sessions.has(frameId)) {
674      // This is a local -> remote frame transtion, where
675      // Page.frameDetached arrives after Target.attachedToTarget.
676      // We've already handled the new target and frame reattach - nothing to do here.
677      return;
678    }
679
680    if (reason === 'swap') {
681      // This is a local -> remote frame transtion, where
682      // Page.frameDetached arrives before Target.attachedToTarget.
683      // We should keep the frame in the tree, and it will be used for the new target.
684      const frame = this._page._frameManager.frame(frameId);
685
686      if (frame) this._page._frameManager.removeChildFramesRecursively(frame);
687      return;
688    } // Just a regular frame detach.
689
690
691    this._page._frameManager.frameDetached(frameId);
692  }
693
694  _onExecutionContextCreated(contextPayload) {
695    const frame = contextPayload.auxData ? this._page._frameManager.frame(contextPayload.auxData.frameId) : null;
696    if (!frame || this._eventBelongsToStaleFrame(frame._id)) return;
697    const delegate = new _crExecutionContext.CRExecutionContext(this._client, contextPayload);
698    let worldName = null;
699    if (contextPayload.auxData && !!contextPayload.auxData.isDefault) worldName = 'main';else if (contextPayload.name === UTILITY_WORLD_NAME) worldName = 'utility';
700    const context = new dom.FrameExecutionContext(delegate, frame, worldName);
701    context[contextDelegateSymbol] = delegate;
702    if (worldName) frame._contextCreated(worldName, context);
703
704    this._contextIdToContext.set(contextPayload.id, context);
705  }
706
707  _onExecutionContextDestroyed(executionContextId) {
708    const context = this._contextIdToContext.get(executionContextId);
709
710    if (!context) return;
711
712    this._contextIdToContext.delete(executionContextId);
713
714    context.frame._contextDestroyed(context);
715  }
716
717  _onExecutionContextsCleared() {
718    for (const contextId of Array.from(this._contextIdToContext.keys())) this._onExecutionContextDestroyed(contextId);
719  }
720
721  _onAttachedToTarget(event) {
722    const session = _crConnection.CRConnection.fromSession(this._client).session(event.sessionId);
723
724    if (event.targetInfo.type === 'iframe') {
725      // Frame id equals target id.
726      const targetId = event.targetInfo.targetId;
727
728      const frame = this._page._frameManager.frame(targetId);
729
730      if (!frame) return; // Subtree may be already gone due to renderer/browser race.
731
732      this._page._frameManager.removeChildFramesRecursively(frame);
733
734      const frameSession = new FrameSession(this._crPage, session, targetId, this);
735
736      this._crPage._sessions.set(targetId, frameSession);
737
738      frameSession._initialize(false).catch(e => e);
739
740      return;
741    }
742
743    if (event.targetInfo.type !== 'worker') {
744      // Ideally, detaching should resume any target, but there is a bug in the backend.
745      session._sendMayFail('Runtime.runIfWaitingForDebugger').then(() => {
746        this._client._sendMayFail('Target.detachFromTarget', {
747          sessionId: event.sessionId
748        });
749      });
750
751      return;
752    }
753
754    const url = event.targetInfo.url;
755    const worker = new _page.Worker(this._page, url);
756
757    this._page._addWorker(event.sessionId, worker);
758
759    session.once('Runtime.executionContextCreated', async event => {
760      worker._createExecutionContext(new _crExecutionContext.CRExecutionContext(session, event.context));
761    }); // This might fail if the target is closed before we initialize.
762
763    session._sendMayFail('Runtime.enable');
764
765    session._sendMayFail('Network.enable');
766
767    session._sendMayFail('Runtime.runIfWaitingForDebugger');
768
769    session.on('Runtime.consoleAPICalled', event => {
770      const args = event.args.map(o => worker._existingExecutionContext.createHandle(o));
771
772      this._page._addConsoleMessage(event.type, args, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));
773    });
774    session.on('Runtime.exceptionThrown', exception => this._page.emit(_page.Page.Events.PageError, (0, _crProtocolHelper.exceptionToError)(exception.exceptionDetails))); // TODO: attribute workers to the right frame.
775
776    this._networkManager.instrumentNetworkEvents(session, this._page._frameManager.frame(this._targetId));
777  }
778
779  _onDetachedFromTarget(event) {
780    // This might be a worker...
781    this._page._removeWorker(event.sessionId); // ... or an oopif.
782
783
784    const childFrameSession = this._crPage._sessions.get(event.targetId);
785
786    if (!childFrameSession) return; // Usually, we get frameAttached in this session first and mark child as swappedIn.
787
788    if (childFrameSession._swappedIn) {
789      childFrameSession.dispose();
790      return;
791    } // However, sometimes we get detachedFromTarget before frameAttached.
792    // In this case we don't know wheter this is a remote frame detach,
793    // or just a remote -> local transition. In the latter case, frameAttached
794    // is already inflight, so let's make a safe roundtrip to ensure it arrives.
795
796
797    this._client.send('Page.enable').catch(e => null).then(() => {
798      // Child was not swapped in - that means frameAttached did not happen and
799      // this is remote detach rather than remote -> local swap.
800      if (!childFrameSession._swappedIn) this._page._frameManager.frameDetached(event.targetId);
801      childFrameSession.dispose();
802    });
803  }
804
805  _onWindowOpen(event) {
806    this._crPage._nextWindowOpenPopupFeatures.push(event.windowFeatures);
807  }
808
809  async _onConsoleAPI(event) {
810    if (event.executionContextId === 0) {
811      // DevTools protocol stores the last 1000 console messages. These
812      // messages are always reported even for removed execution contexts. In
813      // this case, they are marked with executionContextId = 0 and are
814      // reported upon enabling Runtime agent.
815      //
816      // Ignore these messages since:
817      // - there's no execution context we can use to operate with message
818      //   arguments
819      // - these messages are reported before Playwright clients can subscribe
820      //   to the 'console'
821      //   page event.
822      //
823      // @see https://github.com/GoogleChrome/puppeteer/issues/3865
824      return;
825    }
826
827    const context = this._contextIdToContext.get(event.executionContextId);
828
829    if (!context) return;
830    const values = event.args.map(arg => context.createHandle(arg));
831
832    this._page._addConsoleMessage(event.type, values, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));
833  }
834
835  async _initBinding(binding) {
836    await Promise.all([this._client.send('Runtime.addBinding', {
837      name: binding.name
838    }), this._client.send('Page.addScriptToEvaluateOnNewDocument', {
839      source: binding.source
840    })]);
841  }
842
843  async _onBindingCalled(event) {
844    const pageOrError = await this._crPage.pageOrError();
845
846    if (!(pageOrError instanceof Error)) {
847      const context = this._contextIdToContext.get(event.executionContextId);
848
849      if (context) await this._page._onBindingCalled(event.payload, context);
850    }
851  }
852
853  _onDialog(event) {
854    if (!this._page._frameManager.frame(this._targetId)) return; // Our frame/subtree may be gone already.
855
856    this._page.emit(_page.Page.Events.Dialog, new dialog.Dialog(this._page, event.type, event.message, async (accept, promptText) => {
857      await this._client.send('Page.handleJavaScriptDialog', {
858        accept,
859        promptText
860      });
861    }, event.defaultPrompt));
862  }
863
864  _handleException(exceptionDetails) {
865    this._page.firePageError((0, _crProtocolHelper.exceptionToError)(exceptionDetails));
866  }
867
868  async _onTargetCrashed() {
869    this._client._markAsCrashed();
870
871    this._page._didCrash();
872  }
873
874  _onLogEntryAdded(event) {
875    const {
876      level,
877      text,
878      args,
879      source,
880      url,
881      lineNumber
882    } = event.entry;
883    if (args) args.map(arg => (0, _crProtocolHelper.releaseObject)(this._client, arg.objectId));
884
885    if (source !== 'worker') {
886      const location = {
887        url: url || '',
888        lineNumber: lineNumber || 0,
889        columnNumber: 0
890      };
891
892      this._page._addConsoleMessage(level, [], location, text);
893    }
894  }
895
896  async _onFileChooserOpened(event) {
897    const frame = this._page._frameManager.frame(event.frameId);
898
899    if (!frame) return;
900    let handle;
901
902    try {
903      const utilityContext = await frame._utilityContext();
904      handle = await this._adoptBackendNodeId(event.backendNodeId, utilityContext);
905    } catch (e) {
906      // During async processing, frame/context may go away. We should not throw.
907      return;
908    }
909
910    await this._page._onFileChooserOpened(handle);
911  }
912
913  _willBeginDownload() {
914    const originPage = this._crPage._initializedPage;
915
916    if (!originPage) {
917      // Resume the page creation with an error. The page will automatically close right
918      // after the download begins.
919      this._firstNonInitialNavigationCommittedReject(new Error('Starting new page download'));
920    }
921  }
922
923  _onScreencastFrame(payload) {
924    this._page.throttleScreencastFrameAck(() => {
925      this._client.send('Page.screencastFrameAck', {
926        sessionId: payload.sessionId
927      }).catch(() => {});
928    });
929
930    const buffer = Buffer.from(payload.data, 'base64');
931
932    this._page.emit(_page.Page.Events.ScreencastFrame, {
933      buffer,
934      timestamp: payload.metadata.timestamp,
935      width: payload.metadata.deviceWidth,
936      height: payload.metadata.deviceHeight
937    });
938  }
939
940  async _createVideoRecorder(screencastId, options) {
941    (0, _utils.assert)(!this._screencastId);
942
943    const ffmpegPath = _registry.registry.findExecutable('ffmpeg').executablePathOrDie(this._page._browserContext._browser.options.sdkLanguage);
944
945    this._videoRecorder = await _videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
946    this._screencastId = screencastId;
947  }
948
949  async _startVideoRecording(options) {
950    const screencastId = this._screencastId;
951    (0, _utils.assert)(screencastId);
952
953    this._page.once(_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {}));
954
955    const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));
956    await this._startScreencast(this._videoRecorder, {
957      format: 'jpeg',
958      quality: 90,
959      maxWidth: options.width,
960      maxHeight: options.height
961    }); // Wait for the first frame before reporting video to the client.
962
963    gotFirstFrame.then(() => {
964      this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage.pageOrError());
965    });
966  }
967
968  async _stopVideoRecording() {
969    if (!this._screencastId) return;
970    const screencastId = this._screencastId;
971    this._screencastId = null;
972    const recorder = this._videoRecorder;
973    this._videoRecorder = null;
974    await this._stopScreencast(recorder);
975    await recorder.stop().catch(() => {}); // Keep the video artifact in the map utntil encoding is fully finished, if the context
976    // starts closing before the video is fully written to disk it will wait for it.
977
978    const video = this._crPage._browserContext._browser._takeVideo(screencastId);
979
980    video === null || video === void 0 ? void 0 : video.reportFinished();
981  }
982
983  async _startScreencast(client, options = {}) {
984    this._screencastClients.add(client);
985
986    if (this._screencastClients.size === 1) await this._client.send('Page.startScreencast', options);
987  }
988
989  async _stopScreencast(client) {
990    this._screencastClients.delete(client);
991
992    if (!this._screencastClients.size) await this._client._sendMayFail('Page.stopScreencast');
993  }
994
995  async _updateExtraHTTPHeaders(initial) {
996    const headers = network.mergeHeaders([this._crPage._browserContext._options.extraHTTPHeaders, this._page._state.extraHTTPHeaders]);
997    if (!initial || headers.length) await this._client.send('Network.setExtraHTTPHeaders', {
998      headers: (0, _utils.headersArrayToObject)(headers, false
999      /* lowerCase */
1000      )
1001    });
1002  }
1003
1004  async _updateGeolocation(initial) {
1005    const geolocation = this._crPage._browserContext._options.geolocation;
1006    if (!initial || geolocation) await this._client.send('Emulation.setGeolocationOverride', geolocation || {});
1007  }
1008
1009  async _updateOffline(initial) {
1010    const offline = !!this._crPage._browserContext._options.offline;
1011    if (!initial || offline) await this._networkManager.setOffline(offline);
1012  }
1013
1014  async _updateHttpCredentials(initial) {
1015    const credentials = this._crPage._browserContext._options.httpCredentials || null;
1016    if (!initial || credentials) await this._networkManager.authenticate(credentials);
1017  }
1018
1019  async _updateViewport() {
1020    if (this._crPage._browserContext._browser.isClank()) return;
1021    (0, _utils.assert)(this._isMainFrame());
1022    const options = this._crPage._browserContext._options;
1023    const emulatedSize = this._page._state.emulatedSize;
1024    if (emulatedSize === null) return;
1025    const viewportSize = emulatedSize.viewport;
1026    const screenSize = emulatedSize.screen;
1027    const isLandscape = viewportSize.width > viewportSize.height;
1028    const promises = [this._client.send('Emulation.setDeviceMetricsOverride', {
1029      mobile: !!options.isMobile,
1030      width: viewportSize.width,
1031      height: viewportSize.height,
1032      screenWidth: screenSize.width,
1033      screenHeight: screenSize.height,
1034      deviceScaleFactor: options.deviceScaleFactor || 1,
1035      screenOrientation: isLandscape ? {
1036        angle: 90,
1037        type: 'landscapePrimary'
1038      } : {
1039        angle: 0,
1040        type: 'portraitPrimary'
1041      }
1042    })];
1043
1044    if (this._windowId) {
1045      let insets = {
1046        width: 0,
1047        height: 0
1048      };
1049
1050      if (this._crPage._browserContext._browser.options.headful) {
1051        // TODO: popup windows have their own insets.
1052        insets = {
1053          width: 24,
1054          height: 88
1055        };
1056        if (process.platform === 'win32') insets = {
1057          width: 16,
1058          height: 88
1059        };else if (process.platform === 'linux') insets = {
1060          width: 8,
1061          height: 85
1062        };else if (process.platform === 'darwin') insets = {
1063          width: 2,
1064          height: 80
1065        };
1066
1067        if (this._crPage._browserContext.isPersistentContext()) {
1068          // FIXME: Chrome bug: OOPIF router is confused when hit target is
1069          // outside browser window.
1070          // Account for the infobar here to work around the bug.
1071          insets.height += 46;
1072        }
1073      }
1074
1075      promises.push(this.setWindowBounds({
1076        width: viewportSize.width + insets.width,
1077        height: viewportSize.height + insets.height
1078      }));
1079    }
1080
1081    await Promise.all(promises);
1082  }
1083
1084  async windowBounds() {
1085    const {
1086      bounds
1087    } = await this._client.send('Browser.getWindowBounds', {
1088      windowId: this._windowId
1089    });
1090    return bounds;
1091  }
1092
1093  async setWindowBounds(bounds) {
1094    return await this._client.send('Browser.setWindowBounds', {
1095      windowId: this._windowId,
1096      bounds
1097    });
1098  }
1099
1100  async _updateEmulateMedia(initial) {
1101    if (this._crPage._browserContext._browser.isClank()) return;
1102    const colorScheme = this._page._state.colorScheme === null ? '' : this._page._state.colorScheme;
1103    const reducedMotion = this._page._state.reducedMotion === null ? '' : this._page._state.reducedMotion;
1104    const forcedColors = this._page._state.forcedColors === null ? '' : this._page._state.forcedColors;
1105    const features = [{
1106      name: 'prefers-color-scheme',
1107      value: colorScheme
1108    }, {
1109      name: 'prefers-reduced-motion',
1110      value: reducedMotion
1111    }, {
1112      name: 'forced-colors',
1113      value: forcedColors
1114    }]; // Empty string disables the override.
1115
1116    await this._client.send('Emulation.setEmulatedMedia', {
1117      media: this._page._state.mediaType || '',
1118      features
1119    });
1120  }
1121
1122  async _updateRequestInterception() {
1123    await this._networkManager.setRequestInterception(this._page._needsRequestInterception());
1124  }
1125
1126  async _setFileChooserIntercepted(enabled) {
1127    await this._client.send('Page.setInterceptFileChooserDialog', {
1128      enabled
1129    }).catch(e => {}); // target can be closed.
1130  }
1131
1132  async _evaluateOnNewDocument(source, world) {
1133    const worldName = world === 'utility' ? UTILITY_WORLD_NAME : undefined;
1134    await this._client.send('Page.addScriptToEvaluateOnNewDocument', {
1135      source,
1136      worldName
1137    });
1138  }
1139
1140  async _getContentFrame(handle) {
1141    const nodeInfo = await this._client.send('DOM.describeNode', {
1142      objectId: handle._objectId
1143    });
1144    if (!nodeInfo || typeof nodeInfo.node.frameId !== 'string') return null;
1145    return this._page._frameManager.frame(nodeInfo.node.frameId);
1146  }
1147
1148  async _getOwnerFrame(handle) {
1149    // document.documentElement has frameId of the owner frame.
1150    const documentElement = await handle.evaluateHandle(node => {
1151      const doc = node;
1152      if (doc.documentElement && doc.documentElement.ownerDocument === doc) return doc.documentElement;
1153      return node.ownerDocument ? node.ownerDocument.documentElement : null;
1154    });
1155    if (!documentElement) return null;
1156    if (!documentElement._objectId) return null;
1157    const nodeInfo = await this._client.send('DOM.describeNode', {
1158      objectId: documentElement._objectId
1159    });
1160    const frameId = nodeInfo && typeof nodeInfo.node.frameId === 'string' ? nodeInfo.node.frameId : null;
1161    documentElement.dispose();
1162    return frameId;
1163  }
1164
1165  async _getBoundingBox(handle) {
1166    const result = await this._client._sendMayFail('DOM.getBoxModel', {
1167      objectId: handle._objectId
1168    });
1169    if (!result) return null;
1170    const quad = result.model.border;
1171    const x = Math.min(quad[0], quad[2], quad[4], quad[6]);
1172    const y = Math.min(quad[1], quad[3], quad[5], quad[7]);
1173    const width = Math.max(quad[0], quad[2], quad[4], quad[6]) - x;
1174    const height = Math.max(quad[1], quad[3], quad[5], quad[7]) - y;
1175    const position = await this._framePosition();
1176    if (!position) return null;
1177    return {
1178      x: x + position.x,
1179      y: y + position.y,
1180      width,
1181      height
1182    };
1183  }
1184
1185  async _framePosition() {
1186    const frame = this._page._frameManager.frame(this._targetId);
1187
1188    if (!frame) return null;
1189    if (frame === this._page.mainFrame()) return {
1190      x: 0,
1191      y: 0
1192    };
1193    const element = await frame.frameElement();
1194    const box = await element.boundingBox();
1195    return box;
1196  }
1197
1198  async _scrollRectIntoViewIfNeeded(handle, rect) {
1199    return await this._client.send('DOM.scrollIntoViewIfNeeded', {
1200      objectId: handle._objectId,
1201      rect
1202    }).then(() => 'done').catch(e => {
1203      if (e instanceof Error && e.message.includes('Node does not have a layout object')) return 'error:notvisible';
1204      if (e instanceof Error && e.message.includes('Node is detached from document')) return 'error:notconnected';
1205      throw e;
1206    });
1207  }
1208
1209  async _getContentQuads(handle) {
1210    const result = await this._client._sendMayFail('DOM.getContentQuads', {
1211      objectId: handle._objectId
1212    });
1213    if (!result) return null;
1214    const position = await this._framePosition();
1215    if (!position) return null;
1216    return result.quads.map(quad => [{
1217      x: quad[0] + position.x,
1218      y: quad[1] + position.y
1219    }, {
1220      x: quad[2] + position.x,
1221      y: quad[3] + position.y
1222    }, {
1223      x: quad[4] + position.x,
1224      y: quad[5] + position.y
1225    }, {
1226      x: quad[6] + position.x,
1227      y: quad[7] + position.y
1228    }]);
1229  }
1230
1231  async _adoptElementHandle(handle, to) {
1232    const nodeInfo = await this._client.send('DOM.describeNode', {
1233      objectId: handle._objectId
1234    });
1235    return this._adoptBackendNodeId(nodeInfo.node.backendNodeId, to);
1236  }
1237
1238  async _adoptBackendNodeId(backendNodeId, to) {
1239    const result = await this._client._sendMayFail('DOM.resolveNode', {
1240      backendNodeId,
1241      executionContextId: to[contextDelegateSymbol]._contextId
1242    });
1243    if (!result || result.object.subtype === 'null') throw new Error(dom.kUnableToAdoptErrorMessage);
1244    return to.createHandle(result.object).asElement();
1245  }
1246
1247}
1248
1249async function emulateLocale(session, locale) {
1250  try {
1251    await session.send('Emulation.setLocaleOverride', {
1252      locale
1253    });
1254  } catch (exception) {
1255    // All pages in the same renderer share locale. All such pages belong to the same
1256    // context and if locale is overridden for one of them its value is the same as
1257    // we are trying to set so it's not a problem.
1258    if (exception.message.includes('Another locale override is already in effect')) return;
1259    throw exception;
1260  }
1261}
1262
1263async function emulateTimezone(session, timezoneId) {
1264  try {
1265    await session.send('Emulation.setTimezoneOverride', {
1266      timezoneId: timezoneId
1267    });
1268  } catch (exception) {
1269    if (exception.message.includes('Timezone override is already in effect')) return;
1270    if (exception.message.includes('Invalid timezone')) throw new Error(`Invalid timezone ID: ${timezoneId}`);
1271    throw exception;
1272  }
1273}
1274
1275const contextDelegateSymbol = Symbol('delegate');
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)