mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 13:45:36 +03:00
24bc0e39b8
Juggler code had a bug where we subscribed to window and tab events, but did not iterate collections of current windows and tabs. As a result, we were sometimes failing to set viewport size for the initial window, and implemented an artificial promise to workaround the problem. This patch: - starts calling `onOpenWindow` and `onOpenTabListener` callbacks for *all* windows and tabs - current and future, eliminating the race condition. This worked too well and we started overriding window sizes that were set by users with `window.open(url, 'width=300;height=400')` (we have a test for this). To fix this, we now plumb `CHROME_WITH_SIZE` flag from appWindow and override viewport iff this flag is not set. After this patch, we will use the `onTabOpened` event to move user agent emulation to the browser-side. References #3995
136 lines
4.4 KiB
JavaScript
136 lines
4.4 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
|
|
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
class Helper {
|
|
|
|
addObserver(handler, topic) {
|
|
Services.obs.addObserver(handler, topic);
|
|
return () => Services.obs.removeObserver(handler, topic);
|
|
}
|
|
|
|
addMessageListener(receiver, eventName, handler) {
|
|
receiver.addMessageListener(eventName, handler);
|
|
return () => receiver.removeMessageListener(eventName, handler);
|
|
}
|
|
|
|
addEventListener(receiver, eventName, handler) {
|
|
receiver.addEventListener(eventName, handler);
|
|
return () => receiver.removeEventListener(eventName, handler);
|
|
}
|
|
|
|
awaitEvent(receiver, eventName) {
|
|
return new Promise(resolve => {
|
|
receiver.addEventListener(eventName, function listener() {
|
|
receiver.removeEventListener(eventName, listener);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
on(receiver, eventName, handler) {
|
|
// The toolkit/modules/EventEmitter.jsm dispatches event name as a first argument.
|
|
// Fire event listeners without it for convenience.
|
|
const handlerWrapper = (_, ...args) => handler(...args);
|
|
receiver.on(eventName, handlerWrapper);
|
|
return () => receiver.off(eventName, handlerWrapper);
|
|
}
|
|
|
|
addProgressListener(progress, listener, flags) {
|
|
progress.addProgressListener(listener, flags);
|
|
return () => progress.removeProgressListener(listener);
|
|
}
|
|
|
|
removeListeners(listeners) {
|
|
for (const tearDown of listeners)
|
|
tearDown.call(null);
|
|
listeners.splice(0, listeners.length);
|
|
}
|
|
|
|
generateId() {
|
|
const string = uuidGen.generateUUID().toString();
|
|
return string.substring(1, string.length - 1);
|
|
}
|
|
|
|
getLoadContext(channel) {
|
|
let loadContext = null;
|
|
try {
|
|
if (channel.notificationCallbacks)
|
|
loadContext = channel.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
|
} catch (e) {}
|
|
try {
|
|
if (!loadContext && channel.loadGroup)
|
|
loadContext = channel.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
|
} catch (e) { }
|
|
return loadContext;
|
|
}
|
|
|
|
getNetworkErrorStatusText(status) {
|
|
if (!status)
|
|
return null;
|
|
for (const key of Object.keys(Cr)) {
|
|
if (Cr[key] === status)
|
|
return key;
|
|
}
|
|
// Security module. The following is taken from
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/How_to_check_the_secruity_state_of_an_XMLHTTPRequest_over_SSL
|
|
if ((status & 0xff0000) === 0x5a0000) {
|
|
// NSS_SEC errors (happen below the base value because of negative vals)
|
|
if ((status & 0xffff) < Math.abs(Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE)) {
|
|
// The bases are actually negative, so in our positive numeric space, we
|
|
// need to subtract the base off our value.
|
|
const nssErr = Math.abs(Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE) - (status & 0xffff);
|
|
switch (nssErr) {
|
|
case 11:
|
|
return 'SEC_ERROR_EXPIRED_CERTIFICATE';
|
|
case 12:
|
|
return 'SEC_ERROR_REVOKED_CERTIFICATE';
|
|
case 13:
|
|
return 'SEC_ERROR_UNKNOWN_ISSUER';
|
|
case 20:
|
|
return 'SEC_ERROR_UNTRUSTED_ISSUER';
|
|
case 21:
|
|
return 'SEC_ERROR_UNTRUSTED_CERT';
|
|
case 36:
|
|
return 'SEC_ERROR_CA_CERT_INVALID';
|
|
case 90:
|
|
return 'SEC_ERROR_INADEQUATE_KEY_USAGE';
|
|
case 176:
|
|
return 'SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED';
|
|
default:
|
|
return 'SEC_ERROR_UNKNOWN';
|
|
}
|
|
}
|
|
const sslErr = Math.abs(Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE) - (status & 0xffff);
|
|
switch (sslErr) {
|
|
case 3:
|
|
return 'SSL_ERROR_NO_CERTIFICATE';
|
|
case 4:
|
|
return 'SSL_ERROR_BAD_CERTIFICATE';
|
|
case 8:
|
|
return 'SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE';
|
|
case 9:
|
|
return 'SSL_ERROR_UNSUPPORTED_VERSION';
|
|
case 12:
|
|
return 'SSL_ERROR_BAD_CERT_DOMAIN';
|
|
default:
|
|
return 'SSL_ERROR_UNKNOWN';
|
|
}
|
|
}
|
|
return '<unknown error>';
|
|
}
|
|
|
|
browsingContextToFrameId(browsingContext) {
|
|
if (!browsingContext)
|
|
return undefined;
|
|
return 'frame-' + browsingContext.id;
|
|
}
|
|
}
|
|
|
|
var EXPORTED_SYMBOLS = [ "Helper" ];
|
|
this.Helper = Helper;
|
|
|