chore: update browser patches as of Dec 13, 2022 (#20297)

This commit is contained in:
Andrey Lushnikov 2023-01-23 11:29:48 -08:00 коммит произвёл GitHub
Родитель ba0189f8d7
Коммит 6c5317bd31
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
27 изменённых файлов: 2520 добавлений и 2047 удалений

Просмотреть файл

@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/mozilla/gecko-dev" REMOTE_URL="https://github.com/mozilla/gecko-dev"
BASE_BRANCH="release" BASE_BRANCH="release"
BASE_REVISION="fd854580ffc6fba6a0acdf335c96a1b24b976cb9" BASE_REVISION="e2956def6c181ca7375897992c5c821a5a6c886d"

Просмотреть файл

@ -6,6 +6,16 @@ const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerat
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
class Helper { class Helper {
decorateAsEventEmitter(objectToDecorate) {
const { EventEmitter } = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
const emitter = new EventEmitter();
objectToDecorate.on = emitter.on.bind(emitter);
objectToDecorate.addEventListener = emitter.on.bind(emitter);
objectToDecorate.off = emitter.off.bind(emitter);
objectToDecorate.removeEventListener = emitter.off.bind(emitter);
objectToDecorate.once = emitter.once.bind(emitter);
objectToDecorate.emit = emitter.emit.bind(emitter);
}
addObserver(handler, topic) { addObserver(handler, topic) {
Services.obs.addObserver(handler, topic); Services.obs.addObserver(handler, topic);
@ -19,7 +29,15 @@ class Helper {
addEventListener(receiver, eventName, handler) { addEventListener(receiver, eventName, handler) {
receiver.addEventListener(eventName, handler); receiver.addEventListener(eventName, handler);
return () => receiver.removeEventListener(eventName, handler); return () => {
try {
receiver.removeEventListener(eventName, handler);
} catch (e) {
// This could fail when window has navigated cross-process
// and we remove the listener from WindowProxy.
dump(`WARNING: removeEventListener throws ${e} at ${new Error().stack}\n`);
}
};
} }
awaitEvent(receiver, eventName) { awaitEvent(receiver, eventName) {

Просмотреть файл

@ -0,0 +1,35 @@
"use strict";
const { TargetRegistry } = ChromeUtils.import('chrome://juggler/content/TargetRegistry.js');
const { Helper } = ChromeUtils.import('chrome://juggler/content/Helper.js');
const helper = new Helper();
var EXPORTED_SYMBOLS = ['JugglerFrameParent'];
class JugglerFrameParent extends JSWindowActorParent {
constructor() {
super();
}
receiveMessage() { }
async actorCreated() {
// Only interested in main frames for now.
if (this.browsingContext.parent)
return;
this._target = TargetRegistry.instance()?.targetForBrowserId(this.browsingContext.browserId);
if (!this._target)
return;
this.actorName = `browser::page[${this._target.id()}]/${this.browsingContext.browserId}/${this.browsingContext.id}/${this._target.nextActorSequenceNumber()}`;
this._target.setActor(this);
}
didDestroy() {
if (!this._target)
return;
this._target.removeActor(this);
}
}

Просмотреть файл

@ -4,7 +4,6 @@
"use strict"; "use strict";
const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm'); const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
@ -41,7 +40,7 @@ class PageNetwork {
} }
constructor(target) { constructor(target) {
EventEmitter.decorate(this); helper.decorateAsEventEmitter(this);
this._target = target; this._target = target;
this._extraHTTPHeaders = null; this._extraHTTPHeaders = null;
this._responseStorage = new ResponseStorage(MAX_RESPONSE_STORAGE_SIZE, MAX_RESPONSE_STORAGE_SIZE / 10); this._responseStorage = new ResponseStorage(MAX_RESPONSE_STORAGE_SIZE, MAX_RESPONSE_STORAGE_SIZE / 10);
@ -217,8 +216,9 @@ class NetworkRequest {
_onInternalRedirect(newChannel) { _onInternalRedirect(newChannel) {
// Intercepted requests produce "internal redirects" - this is both for our own // Intercepted requests produce "internal redirects" - this is both for our own
// interception and service workers. // interception and service workers.
// An internal redirect has the same channelId, inherits notificationCallbacks and // An internal redirect does not necessarily have the same channelId,
// listener, and should be used instead of an old channel. // but inherits notificationCallbacks and the listener,
// and should be used instead of an old channel.
this._networkObserver._channelToRequest.delete(this.httpChannel); this._networkObserver._channelToRequest.delete(this.httpChannel);
this.httpChannel = newChannel; this.httpChannel = newChannel;
this._networkObserver._channelToRequest.set(this.httpChannel, this); this._networkObserver._channelToRequest.set(this.httpChannel, this);
@ -363,7 +363,7 @@ class NetworkRequest {
} }
const browserContext = pageNetwork._target.browserContext(); const browserContext = pageNetwork._target.browserContext();
if (browserContext.settings.onlineOverride === 'offline') { if (browserContext.crossProcessCookie.settings.onlineOverride === 'offline') {
// Implement offline. // Implement offline.
this.abort(Cr.NS_ERROR_OFFLINE); this.abort(Cr.NS_ERROR_OFFLINE);
return; return;
@ -458,7 +458,7 @@ class NetworkRequest {
const browserContext = pageNetwork._target.browserContext(); const browserContext = pageNetwork._target.browserContext();
if (browserContext.requestInterceptionEnabled) if (browserContext.requestInterceptionEnabled)
return true; return true;
if (browserContext.settings.onlineOverride === 'offline') if (browserContext.crossProcessCookie.settings.onlineOverride === 'offline')
return true; return true;
return false; return false;
} }
@ -581,7 +581,7 @@ class NetworkObserver {
} }
constructor(targetRegistry) { constructor(targetRegistry) {
EventEmitter.decorate(this); helper.decorateAsEventEmitter(this);
NetworkObserver._instance = this; NetworkObserver._instance = this;
this._targetRegistry = targetRegistry; this._targetRegistry = targetRegistry;

Просмотреть файл

@ -9,6 +9,12 @@
const SIMPLE_CHANNEL_MESSAGE_NAME = 'juggler:simplechannel'; const SIMPLE_CHANNEL_MESSAGE_NAME = 'juggler:simplechannel';
class SimpleChannel { class SimpleChannel {
static createForActor(actor) {
const channel = new SimpleChannel('');
channel.bindToActor(actor);
return channel;
}
static createForMessageManager(name, mm) { static createForMessageManager(name, mm) {
const channel = new SimpleChannel(name); const channel = new SimpleChannel(name);
@ -32,15 +38,34 @@ class SimpleChannel {
this._pendingMessages = new Map(); this._pendingMessages = new Map();
this._handlers = new Map(); this._handlers = new Map();
this._bufferedIncomingMessages = []; this._bufferedIncomingMessages = [];
this._bufferedOutgoingMessages = [];
this.transport = { this.transport = {
sendMessage: null, sendMessage: null,
dispose: null, dispose: () => {},
}; };
this._ready = false; this._ready = false;
this._disposed = false; this._disposed = false;
} }
bindToActor(actor) {
this.resetTransport();
this._name = actor.actorName;
const oldReceiveMessage = actor.receiveMessage;
actor.receiveMessage = message => this._onMessage(message.data);
this.setTransport({
sendMessage: obj => actor.sendAsyncMessage(SIMPLE_CHANNEL_MESSAGE_NAME, obj),
dispose: () => actor.receiveMessage = oldReceiveMessage,
});
}
resetTransport() {
this.transport.dispose();
this.transport = {
sendMessage: null,
dispose: () => {},
};
this._ready = false;
}
setTransport(transport) { setTransport(transport) {
this.transport = transport; this.transport = transport;
// connection handshake: // connection handshake:
@ -59,9 +84,8 @@ class SimpleChannel {
if (this._ready) if (this._ready)
return; return;
this._ready = true; this._ready = true;
for (const msg of this._bufferedOutgoingMessages) for (const { message } of this._pendingMessages.values())
this.transport.sendMessage(msg); this.transport.sendMessage(message);
this._bufferedOutgoingMessages = [];
} }
dispose() { dispose() {
@ -121,14 +145,12 @@ class SimpleChannel {
if (this._disposed) if (this._disposed)
throw new Error(`ERROR: channel ${this._name} is already disposed! Cannot send "${methodName}" to "${namespace}"`); throw new Error(`ERROR: channel ${this._name} is already disposed! Cannot send "${methodName}" to "${namespace}"`);
const id = ++this._messageId; const id = ++this._messageId;
const promise = new Promise((resolve, reject) => {
this._pendingMessages.set(id, {connectorId, resolve, reject, methodName, namespace});
});
const message = {requestId: id, methodName, params, namespace}; const message = {requestId: id, methodName, params, namespace};
const promise = new Promise((resolve, reject) => {
this._pendingMessages.set(id, {connectorId, resolve, reject, methodName, namespace, message});
});
if (this._ready) if (this._ready)
this.transport.sendMessage(message); this.transport.sendMessage(message);
else
this._bufferedOutgoingMessages.push(message);
return promise; return promise;
} }
@ -143,12 +165,19 @@ class SimpleChannel {
return; return;
} }
if (data.responseId) { if (data.responseId) {
const {resolve, reject} = this._pendingMessages.get(data.responseId); const message = this._pendingMessages.get(data.responseId);
if (!message) {
// During corss-process navigation, we might receive a response for
// the message sent by another process.
// TODO: consider events that are marked as "no-response" to avoid
// unneeded responses altogether.
return;
}
this._pendingMessages.delete(data.responseId); this._pendingMessages.delete(data.responseId);
if (data.error) if (data.error)
reject(new Error(data.error)); message.reject(new Error(data.error));
else else
resolve(data.result); message.resolve(data.result);
} else if (data.requestId) { } else if (data.requestId) {
const namespace = data.namespace; const namespace = data.namespace;
const handler = this._handlers.get(namespace); const handler = this._handlers.get(namespace);
@ -169,9 +198,7 @@ class SimpleChannel {
return; return;
} }
} else { } else {
dump(` dump(`WARNING: unknown message in channel "${this._name}": ${JSON.stringify(data)}\n`);
ERROR: unknown message in channel "${this._name}": ${JSON.stringify(data)}
`);
} }
} }
} }

Просмотреть файл

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js'); const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
@ -38,7 +37,7 @@ class DownloadInterceptor {
if (!(request instanceof Ci.nsIChannel)) if (!(request instanceof Ci.nsIChannel))
return false; return false;
const channel = request.QueryInterface(Ci.nsIChannel); const channel = request.QueryInterface(Ci.nsIChannel);
let pageTarget = this._registry._browserBrowsingContextToTarget.get(channel.loadInfo.browsingContext.top); let pageTarget = this._registry._browserIdToTarget.get(channel.loadInfo.browsingContext.top.browserId);
if (!pageTarget) if (!pageTarget)
return false; return false;
@ -57,7 +56,7 @@ class DownloadInterceptor {
try { try {
file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
} catch (e) { } catch (e) {
dump(`interceptDownloadRequest failed to create file: ${e}\n`); dump(`WARNING: interceptDownloadRequest failed to create file: ${e}\n`);
return false; return false;
} }
} }
@ -68,6 +67,7 @@ class DownloadInterceptor {
uuid, uuid,
browserContextId: browserContext.browserContextId, browserContextId: browserContext.browserContextId,
pageTargetId: pageTarget.id(), pageTargetId: pageTarget.id(),
frameId: helper.browsingContextToFrameId(channel.loadInfo.browsingContext),
url: request.name, url: request.name,
suggestedFileName: externalAppHandler.suggestedFileName, suggestedFileName: externalAppHandler.suggestedFileName,
}; };
@ -103,13 +103,18 @@ class DownloadInterceptor {
const screencastService = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService); const screencastService = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
class TargetRegistry { class TargetRegistry {
static instance() {
return TargetRegistry._instance || null;
}
constructor() { constructor() {
EventEmitter.decorate(this); helper.decorateAsEventEmitter(this);
TargetRegistry._instance = this;
this._browserContextIdToBrowserContext = new Map(); this._browserContextIdToBrowserContext = new Map();
this._userContextIdToBrowserContext = new Map(); this._userContextIdToBrowserContext = new Map();
this._browserToTarget = new Map(); this._browserToTarget = new Map();
this._browserBrowsingContextToTarget = new Map(); this._browserIdToTarget = new Map();
this._browserProxy = null; this._browserProxy = null;
@ -136,20 +141,14 @@ class TargetRegistry {
} }
}, 'oop-frameloader-crashed'); }, 'oop-frameloader-crashed');
Services.mm.addMessageListener('juggler:content-ready', { helper.addObserver((browsingContext, topic, why) => {
receiveMessage: message => { if (why === 'replace') {
const linkedBrowser = message.target; // Top-level browsingContext is replaced on cross-process navigations.
const target = this._browserToTarget.get(linkedBrowser); const target = this._browserIdToTarget.get(browsingContext.browserId);
if (!target) if (target)
return; target.replaceTopBrowsingContext(browsingContext);
}
return { }, 'browsing-context-attached');
initScripts: target.browserContext().initScripts,
bindings: target.browserContext().bindings,
settings: target.browserContext().settings,
};
},
});
const onTabOpenListener = (appWindow, window, event) => { const onTabOpenListener = (appWindow, window, event) => {
const tab = event.target; const tab = event.target;
@ -161,7 +160,7 @@ class TargetRegistry {
if (openerContext) { if (openerContext) {
// Popups usually have opener context. Get top context for the case when opener is // Popups usually have opener context. Get top context for the case when opener is
// an iframe. // an iframe.
openerTarget = this._browserBrowsingContextToTarget.get(openerContext.top); openerTarget = this._browserIdToTarget.get(openerContext.top.browserId);
} else if (tab.openerTab) { } else if (tab.openerTab) {
// Noopener popups from the same window have opener tab instead. // Noopener popups from the same window have opener tab instead.
openerTarget = this._browserToTarget.get(tab.openerTab.linkedBrowser); openerTarget = this._browserToTarget.get(tab.openerTab.linkedBrowser);
@ -169,13 +168,7 @@ class TargetRegistry {
if (!browserContext) if (!browserContext)
throw new Error(`Internal error: cannot find context for userContextId=${userContextId}`); throw new Error(`Internal error: cannot find context for userContextId=${userContextId}`);
const target = new PageTarget(this, window, tab, browserContext, openerTarget); const target = new PageTarget(this, window, tab, browserContext, openerTarget);
target.updateUserAgent(); target.updateOverridesForBrowsingContext(tab.linkedBrowser.browsingContext);
target.updatePlatform();
target.updateJavaScriptDisabled();
target.updateTouchOverride();
target.updateColorSchemeOverride();
target.updateReducedMotionOverride();
target.updateForcedColorsOverride();
if (!hasExplicitSize) if (!hasExplicitSize)
target.updateViewportSize(); target.updateViewportSize();
if (browserContext.videoRecordingOptions) if (browserContext.videoRecordingOptions)
@ -329,7 +322,7 @@ class TargetRegistry {
target = this._browserToTarget.get(browser); target = this._browserToTarget.get(browser);
} }
browser.focus(); browser.focus();
if (browserContext.settings.timezoneId) { if (browserContext.crossProcessCookie.settings.timezoneId) {
if (await target.hasFailedToOverrideTimezone()) if (await target.hasFailedToOverrideTimezone())
throw new Error('Failed to override timezone'); throw new Error('Failed to override timezone');
} }
@ -343,11 +336,15 @@ class TargetRegistry {
targetForBrowser(browser) { targetForBrowser(browser) {
return this._browserToTarget.get(browser); return this._browserToTarget.get(browser);
} }
targetForBrowserId(browserId) {
return this._browserIdToTarget.get(browserId);
}
} }
class PageTarget { class PageTarget {
constructor(registry, win, tab, browserContext, opener) { constructor(registry, win, tab, browserContext, opener) {
EventEmitter.decorate(this); helper.decorateAsEventEmitter(this);
this._targetId = helper.generateId(); this._targetId = helper.generateId();
this._registry = registry; this._registry = registry;
@ -360,12 +357,19 @@ class PageTarget {
this._initialDPPX = this._linkedBrowser.browsingContext.overrideDPPX; this._initialDPPX = this._linkedBrowser.browsingContext.overrideDPPX;
this._url = 'about:blank'; this._url = 'about:blank';
this._openerId = opener ? opener.id() : undefined; this._openerId = opener ? opener.id() : undefined;
this._channel = SimpleChannel.createForMessageManager(`browser::page[${this._targetId}]`, this._linkedBrowser.messageManager); this._actor = undefined;
this._actorSequenceNumber = 0;
this._channel = new SimpleChannel(`browser::page[${this._targetId}]`);
this._videoRecordingInfo = undefined; this._videoRecordingInfo = undefined;
this._screencastRecordingInfo = undefined; this._screencastRecordingInfo = undefined;
this._dialogs = new Map(); this._dialogs = new Map();
this.forcedColors = 'no-override'; this.forcedColors = 'no-override';
this._pageInitScripts = []; this.mediumOverride = '';
this.crossProcessCookie = {
initScripts: [],
bindings: [],
interceptFileChooserDialog: false,
};
const navigationListener = { const navigationListener = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]), QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
@ -380,11 +384,38 @@ class PageTarget {
this._disposed = false; this._disposed = false;
browserContext.pages.add(this); browserContext.pages.add(this);
this._registry._browserToTarget.set(this._linkedBrowser, this); this._registry._browserToTarget.set(this._linkedBrowser, this);
this._registry._browserBrowsingContextToTarget.set(this._linkedBrowser.browsingContext, this); this._registry._browserIdToTarget.set(this._linkedBrowser.browsingContext.browserId, this);
this._registry.emit(TargetRegistry.Events.TargetCreated, this); this._registry.emit(TargetRegistry.Events.TargetCreated, this);
} }
nextActorSequenceNumber() {
return ++this._actorSequenceNumber;
}
setActor(actor) {
this._actor = actor;
this._channel.bindToActor(actor);
}
removeActor(actor) {
// Note: the order between setActor and removeActor is non-deterministic.
// Therefore we check that we are still bound to the actor that is being removed.
if (this._actor !== actor)
return;
this._actor = undefined;
this._channel.resetTransport();
}
replaceTopBrowsingContext(browsingContext) {
if (this._actor && this._actor.browsingContext !== browsingContext) {
// Disconnect early to avoid receiving protocol messages from the old actor.
this.removeActor(this._actor);
}
this.emit(PageTarget.Events.TopBrowsingContextReplaced);
this.updateOverridesForBrowsingContext(browsingContext);
}
dialog(dialogId) { dialog(dialogId) {
return this._dialogs.get(dialogId); return this._dialogs.get(dialogId);
} }
@ -405,20 +436,31 @@ class PageTarget {
return this._browserContext; return this._browserContext;
} }
updateTouchOverride() { updateOverridesForBrowsingContext(browsingContext = undefined) {
this._linkedBrowser.browsingContext.touchEventsOverride = this._browserContext.touchOverride ? 'enabled' : 'none'; this.updateTouchOverride(browsingContext);
this.updateUserAgent(browsingContext);
this.updatePlatform(browsingContext);
this.updateDPPXOverride(browsingContext);
this.updateEmulatedMedia(browsingContext);
this.updateColorSchemeOverride(browsingContext);
this.updateReducedMotionOverride(browsingContext);
this.updateForcedColorsOverride(browsingContext);
} }
updateUserAgent() { updateTouchOverride(browsingContext = undefined) {
this._linkedBrowser.browsingContext.customUserAgent = this._browserContext.defaultUserAgent; (browsingContext || this._linkedBrowser.browsingContext).touchEventsOverride = this._browserContext.touchOverride ? 'enabled' : 'none';
} }
updatePlatform() { updateUserAgent(browsingContext = undefined) {
this._linkedBrowser.browsingContext.customPlatform = this._browserContext.defaultPlatform; (browsingContext || this._linkedBrowser.browsingContext).customUserAgent = this._browserContext.defaultUserAgent;
} }
updateJavaScriptDisabled() { updatePlatform(browsingContext = undefined) {
this._linkedBrowser.browsingContext.allowJavascript = !this._browserContext.javaScriptDisabled; (browsingContext || this._linkedBrowser.browsingContext).customPlatform = this._browserContext.defaultPlatform;
}
updateDPPXOverride(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).overrideDPPX = this._browserContext.deviceScaleFactor || this._initialDPPX;
} }
_updateModalDialogs() { _updateModalDialogs() {
@ -452,7 +494,7 @@ class PageTarget {
// default viewport. // default viewport.
const viewportSize = this._viewportSize || this._browserContext.defaultViewportSize; const viewportSize = this._viewportSize || this._browserContext.defaultViewportSize;
const actualSize = await setViewportSizeForBrowser(viewportSize, this._linkedBrowser, this._window); const actualSize = await setViewportSizeForBrowser(viewportSize, this._linkedBrowser, this._window);
this._linkedBrowser.browsingContext.overrideDPPX = this._browserContext.deviceScaleFactor || this._initialDPPX; this.updateDPPXOverride();
await this._channel.connect('').send('awaitViewportDimensions', { await this._channel.connect('').send('awaitViewportDimensions', {
width: actualSize.width, width: actualSize.width,
height: actualSize.height, height: actualSize.height,
@ -461,7 +503,12 @@ class PageTarget {
} }
setEmulatedMedia(mediumOverride) { setEmulatedMedia(mediumOverride) {
this._linkedBrowser.browsingContext.mediumOverride = mediumOverride || ''; this.mediumOverride = mediumOverride || '';
this.updateEmulatedMedia();
}
updateEmulatedMedia(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).mediumOverride = this.mediumOverride;
} }
setColorScheme(colorScheme) { setColorScheme(colorScheme) {
@ -469,8 +516,8 @@ class PageTarget {
this.updateColorSchemeOverride(); this.updateColorSchemeOverride();
} }
updateColorSchemeOverride() { updateColorSchemeOverride(browsingContext = undefined) {
this._linkedBrowser.browsingContext.prefersColorSchemeOverride = this.colorScheme || this._browserContext.colorScheme || 'none'; (browsingContext || this._linkedBrowser.browsingContext).prefersColorSchemeOverride = this.colorScheme || this._browserContext.colorScheme || 'none';
} }
setReducedMotion(reducedMotion) { setReducedMotion(reducedMotion) {
@ -478,8 +525,8 @@ class PageTarget {
this.updateReducedMotionOverride(); this.updateReducedMotionOverride();
} }
updateReducedMotionOverride() { updateReducedMotionOverride(browsingContext = undefined) {
this._linkedBrowser.browsingContext.prefersReducedMotionOverride = this.reducedMotion || this._browserContext.reducedMotion || 'none'; (browsingContext || this._linkedBrowser.browsingContext).prefersReducedMotionOverride = this.reducedMotion || this._browserContext.reducedMotion || 'none';
} }
setForcedColors(forcedColors) { setForcedColors(forcedColors) {
@ -487,8 +534,14 @@ class PageTarget {
this.updateForcedColorsOverride(); this.updateForcedColorsOverride();
} }
updateForcedColorsOverride() { updateForcedColorsOverride(browsingContext = undefined) {
this._linkedBrowser.browsingContext.forcedColorsOverride = (this.forcedColors !== 'no-override' ? this.forcedColors : this._browserContext.forcedColors) || 'no-override'; (browsingContext || this._linkedBrowser.browsingContext).forcedColorsOverride = (this.forcedColors !== 'no-override' ? this.forcedColors : this._browserContext.forcedColors) || 'no-override';
}
async setInterceptFileChooserDialog(enabled) {
this.crossProcessCookie.interceptFileChooserDialog = enabled;
this._updateCrossProcessCookie();
await this._channel.connect('').send('setInterceptFileChooserDialog', enabled).catch(e => {});
} }
async setViewportSize(viewportSize) { async setViewportSize(viewportSize) {
@ -524,20 +577,28 @@ class PageTarget {
this._browserContext.grantPermissionsToOrigin(this._url); this._browserContext.grantPermissionsToOrigin(this._url);
} }
_updateCrossProcessCookie() {
Services.ppmm.sharedData.set('juggler:page-cookie-' + this._linkedBrowser.browsingContext.browserId, this.crossProcessCookie);
Services.ppmm.sharedData.flush();
}
async ensurePermissions() { async ensurePermissions() {
await this._channel.connect('').send('ensurePermissions', {}).catch(e => void e); await this._channel.connect('').send('ensurePermissions', {}).catch(e => void e);
} }
async setInitScripts(scripts) { async setInitScripts(scripts) {
this._pageInitScripts = scripts; this.crossProcessCookie.initScripts = scripts;
this._updateCrossProcessCookie();
await this.pushInitScripts(); await this.pushInitScripts();
} }
async pushInitScripts() { async pushInitScripts() {
await this._channel.connect('').send('setInitScripts', [...this._browserContext.initScripts, ...this._pageInitScripts]).catch(e => void e); await this._channel.connect('').send('setInitScripts', [...this._browserContext.crossProcessCookie.initScripts, ...this.crossProcessCookie.initScripts]).catch(e => void e);
} }
async addBinding(worldName, name, script) { async addBinding(worldName, name, script) {
this.crossProcessCookie.bindings.push({ worldName, name, script });
this._updateCrossProcessCookie();
await this._channel.connect('').send('addBinding', { worldName, name, script }).catch(e => void e); await this._channel.connect('').send('addBinding', { worldName, name, script }).catch(e => void e);
} }
@ -641,7 +702,7 @@ class PageTarget {
this.stopScreencast(); this.stopScreencast();
this._browserContext.pages.delete(this); this._browserContext.pages.delete(this);
this._registry._browserToTarget.delete(this._linkedBrowser); this._registry._browserToTarget.delete(this._linkedBrowser);
this._registry._browserBrowsingContextToTarget.delete(this._linkedBrowser.browsingContext); this._registry._browserIdToTarget.delete(this._linkedBrowser.browsingContext.browserId);
try { try {
helper.removeListeners(this._eventListeners); helper.removeListeners(this._eventListeners);
} catch (e) { } catch (e) {
@ -660,6 +721,7 @@ PageTarget.Events = {
Crashed: Symbol('PageTarget.Crashed'), Crashed: Symbol('PageTarget.Crashed'),
DialogOpened: Symbol('PageTarget.DialogOpened'), DialogOpened: Symbol('PageTarget.DialogOpened'),
DialogClosed: Symbol('PageTarget.DialogClosed'), DialogClosed: Symbol('PageTarget.DialogClosed'),
TopBrowsingContextReplaced: Symbol('PageTarget.TopBrowsingContextReplaced'),
}; };
function fromProtocolColorScheme(colorScheme) { function fromProtocolColorScheme(colorScheme) {
@ -712,18 +774,24 @@ class BrowserContext {
this.deviceScaleFactor = undefined; this.deviceScaleFactor = undefined;
this.defaultUserAgent = null; this.defaultUserAgent = null;
this.defaultPlatform = null; this.defaultPlatform = null;
this.javaScriptDisabled = false;
this.touchOverride = false; this.touchOverride = false;
this.colorScheme = 'none'; this.colorScheme = 'none';
this.forcedColors = 'no-override'; this.forcedColors = 'no-override';
this.reducedMotion = 'none'; this.reducedMotion = 'none';
this.videoRecordingOptions = undefined; this.videoRecordingOptions = undefined;
this.initScripts = []; this.crossProcessCookie = {
this.bindings = []; initScripts: [],
this.settings = {}; bindings: [],
settings: {},
};
this.pages = new Set(); this.pages = new Set();
} }
_updateCrossProcessCookie() {
Services.ppmm.sharedData.set('juggler:context-cookie-' + this.userContextId, this.crossProcessCookie);
Services.ppmm.sharedData.flush();
}
setColorScheme(colorScheme) { setColorScheme(colorScheme) {
this.colorScheme = fromProtocolColorScheme(colorScheme); this.colorScheme = fromProtocolColorScheme(colorScheme);
for (const page of this.pages) for (const page of this.pages)
@ -796,12 +864,6 @@ class BrowserContext {
page.updatePlatform(); page.updatePlatform();
} }
setJavaScriptDisabled(javaScriptDisabled) {
this.javaScriptDisabled = javaScriptDisabled;
for (const page of this.pages)
page.updateJavaScriptDisabled();
}
setTouchOverride(touchOverride) { setTouchOverride(touchOverride) {
this.touchOverride = touchOverride; this.touchOverride = touchOverride;
for (const page of this.pages) for (const page of this.pages)
@ -815,17 +877,20 @@ class BrowserContext {
} }
async setInitScripts(scripts) { async setInitScripts(scripts) {
this.initScripts = scripts; this.crossProcessCookie.initScripts = scripts;
this._updateCrossProcessCookie();
await Promise.all(Array.from(this.pages).map(page => page.pushInitScripts())); await Promise.all(Array.from(this.pages).map(page => page.pushInitScripts()));
} }
async addBinding(worldName, name, script) { async addBinding(worldName, name, script) {
this.bindings.push({ worldName, name, script }); this.crossProcessCookie.bindings.push({ worldName, name, script });
this._updateCrossProcessCookie();
await Promise.all(Array.from(this.pages).map(page => page.addBinding(worldName, name, script))); await Promise.all(Array.from(this.pages).map(page => page.addBinding(worldName, name, script)));
} }
async applySetting(name, value) { async applySetting(name, value) {
this.settings[name] = value; this.crossProcessCookie.settings[name] = value;
this._updateCrossProcessCookie();
await Promise.all(Array.from(this.pages).map(page => page.applyContextSetting(name, value))); await Promise.all(Array.from(this.pages).map(page => page.applyContextSetting(name, value)));
} }

Просмотреть файл

@ -12,12 +12,34 @@ const {BrowserHandler} = ChromeUtils.import("chrome://juggler/content/protocol/B
const {NetworkObserver} = ChromeUtils.import("chrome://juggler/content/NetworkObserver.js"); const {NetworkObserver} = ChromeUtils.import("chrome://juggler/content/NetworkObserver.js");
const {TargetRegistry} = ChromeUtils.import("chrome://juggler/content/TargetRegistry.js"); const {TargetRegistry} = ChromeUtils.import("chrome://juggler/content/TargetRegistry.js");
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
const {ActorManagerParent} = ChromeUtils.import('resource://gre/modules/ActorManagerParent.jsm');
const helper = new Helper(); const helper = new Helper();
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const FRAME_SCRIPT = "chrome://juggler/content/content/main.js"; // Register JSWindowActors that will be instantiated for each frame.
ActorManagerParent.addJSWindowActors({
JugglerFrame: {
parent: {
moduleURI: 'chrome://juggler/content/JugglerFrameParent.jsm',
},
child: {
moduleURI: 'chrome://juggler/content/content/JugglerFrameChild.jsm',
events: {
// Normally, we instantiate an actor when a new window is created.
DOMWindowCreated: {},
// However, for same-origin iframes, the navigation from about:blank
// to the URL will share the same window, so we need to also create
// an actor for a new document via DOMDocElementInserted.
DOMDocElementInserted: {},
// Also, listening to DOMContentLoaded.
DOMContentLoaded: {},
},
},
allFrames: true,
},
});
let browserStartupFinishedCallback; let browserStartupFinishedCallback;
let browserStartupFinishedPromise = new Promise(x => browserStartupFinishedCallback = x); let browserStartupFinishedPromise = new Promise(x => browserStartupFinishedCallback = x);
@ -72,8 +94,7 @@ class Juggler {
const targetRegistry = new TargetRegistry(); const targetRegistry = new TargetRegistry();
new NetworkObserver(targetRegistry); new NetworkObserver(targetRegistry);
const loadFrameScript = () => { const loadStyleSheet = () => {
Services.mm.loadFrameScript(FRAME_SCRIPT, true /* aAllowDelayedLoad */);
if (Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless) { if (Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless) {
const styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Components.interfaces.nsIStyleSheetService); const styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Components.interfaces.nsIStyleSheetService);
const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
@ -118,7 +139,7 @@ class Juggler {
pipeStopped = true; pipeStopped = true;
}, () => browserStartupFinishedPromise); }, () => browserStartupFinishedPromise);
dispatcher.rootSession().setHandler(browserHandler); dispatcher.rootSession().setHandler(browserHandler);
loadFrameScript(); loadStyleSheet();
dump(`\nJuggler listening to the pipe\n`); dump(`\nJuggler listening to the pipe\n`);
break; break;
} }

Просмотреть файл

@ -9,14 +9,13 @@ const Cu = Components.utils;
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js'); const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
const {Runtime} = ChromeUtils.import('chrome://juggler/content/content/Runtime.js'); const {Runtime} = ChromeUtils.import('chrome://juggler/content/content/Runtime.js');
const helper = new Helper(); const helper = new Helper();
class FrameTree { class FrameTree {
constructor(rootDocShell) { constructor(rootDocShell) {
EventEmitter.decorate(this); helper.decorateAsEventEmitter(this);
this._browsingContextGroup = rootDocShell.browsingContext.group; this._browsingContextGroup = rootDocShell.browsingContext.group;
if (!this._browsingContextGroup.__jugglerFrameTrees) if (!this._browsingContextGroup.__jugglerFrameTrees)
@ -33,6 +32,7 @@ class FrameTree {
this._docShellToFrame = new Map(); this._docShellToFrame = new Map();
this._frameIdToFrame = new Map(); this._frameIdToFrame = new Map();
this._pageReady = false; this._pageReady = false;
this._javaScriptDisabled = false;
this._mainFrame = this._createFrame(rootDocShell); this._mainFrame = this._createFrame(rootDocShell);
const webProgress = rootDocShell.QueryInterface(Ci.nsIInterfaceRequestor) const webProgress = rootDocShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress); .getInterface(Ci.nsIWebProgress);
@ -128,6 +128,12 @@ class FrameTree {
this.scrollbarsHidden = hidden; this.scrollbarsHidden = hidden;
} }
setJavaScriptDisabled(javaScriptDisabled) {
this._javaScriptDisabled = javaScriptDisabled;
for (const frame of this.frames())
frame._updateJavaScriptDisabled();
}
_onWorkerCreated(workerDebugger) { _onWorkerCreated(workerDebugger) {
// Note: we do not interoperate with firefox devtools. // Note: we do not interoperate with firefox devtools.
if (workerDebugger.isInitialized) if (workerDebugger.isInitialized)
@ -214,7 +220,7 @@ class FrameTree {
const docShell = progress.DOMWindow.docShell; const docShell = progress.DOMWindow.docShell;
const frame = this._docShellToFrame.get(docShell); const frame = this._docShellToFrame.get(docShell);
if (!frame) { if (!frame) {
dump(`ERROR: got a state changed event for un-tracked docshell!\n`); dump(`WARNING: got a state changed event for un-tracked docshell!\n`);
return; return;
} }
@ -227,7 +233,6 @@ class FrameTree {
const isStart = flag & Ci.nsIWebProgressListener.STATE_START; const isStart = flag & Ci.nsIWebProgressListener.STATE_START;
const isTransferring = flag & Ci.nsIWebProgressListener.STATE_TRANSFERRING; const isTransferring = flag & Ci.nsIWebProgressListener.STATE_TRANSFERRING;
const isStop = flag & Ci.nsIWebProgressListener.STATE_STOP; const isStop = flag & Ci.nsIWebProgressListener.STATE_STOP;
const isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
if (isStart) { if (isStart) {
// Starting a new navigation. // Starting a new navigation.
@ -257,9 +262,6 @@ class FrameTree {
if (frame === this._mainFrame && status !== Cr.NS_BINDING_ABORTED) if (frame === this._mainFrame && status !== Cr.NS_BINDING_ABORTED)
this.forcePageReady(); this.forcePageReady();
} }
if (isStop && isDocument)
this.emit(FrameTree.Events.Load, frame);
} }
onLocationChange(progress, request, location, flags) { onLocationChange(progress, request, location, flags) {
@ -287,6 +289,10 @@ class FrameTree {
_createFrame(docShell) { _createFrame(docShell) {
const parentFrame = this._docShellToFrame.get(docShell.parent) || null; const parentFrame = this._docShellToFrame.get(docShell.parent) || null;
if (!parentFrame && this._mainFrame) {
dump(`WARNING: found docShell with the same root, but no parent!\n`);
return;
}
const frame = new Frame(this, this._runtime, docShell, parentFrame); const frame = new Frame(this, this._runtime, docShell, parentFrame);
this._docShellToFrame.set(docShell, frame); this._docShellToFrame.set(docShell, frame);
this._frameIdToFrame.set(frame.id(), frame); this._frameIdToFrame.set(frame.id(), frame);
@ -308,6 +314,11 @@ class FrameTree {
// Detach all children first // Detach all children first
for (const subframe of frame._children) for (const subframe of frame._children)
this._detachFrame(subframe); this._detachFrame(subframe);
if (frame === this._mainFrame) {
// Do not detach main frame (happens during cross-process navigation),
// as it confuses the client.
return;
}
this._docShellToFrame.delete(frame._docShell); this._docShellToFrame.delete(frame._docShell);
this._frameIdToFrame.delete(frame.id()); this._frameIdToFrame.delete(frame.id());
if (frame._parentFrame) if (frame._parentFrame)
@ -333,7 +344,6 @@ FrameTree.Events = {
NavigationAborted: 'navigationaborted', NavigationAborted: 'navigationaborted',
SameDocumentNavigation: 'samedocumentnavigation', SameDocumentNavigation: 'samedocumentnavigation',
PageReady: 'pageready', PageReady: 'pageready',
Load: 'load',
}; };
class IsolatedWorld { class IsolatedWorld {
@ -518,6 +528,20 @@ class Frame {
for (const script of world._scriptsToEvaluateOnNewDocument) for (const script of world._scriptsToEvaluateOnNewDocument)
executionContext.evaluateScriptSafely(script); executionContext.evaluateScriptSafely(script);
} }
const url = this.domWindow().location?.href;
if (url === 'about:blank' && !this._url) {
// Sometimes FrameTree is created too early, before the location has been set.
this._url = url;
this._frameTree.emit(FrameTree.Events.NavigationCommitted, this);
}
this._updateJavaScriptDisabled();
}
_updateJavaScriptDisabled() {
if (this._docShell.browsingContext.currentWindowContext)
this._docShell.browsingContext.currentWindowContext.allowJavascript = !this._frameTree._javaScriptDisabled;
} }
mainExecutionContext() { mainExecutionContext() {
@ -592,7 +616,7 @@ class Worker {
onMessage: msg => void this._channel._onMessage(JSON.parse(msg)), onMessage: msg => void this._channel._onMessage(JSON.parse(msg)),
onClose: () => void this._channel.dispose(), onClose: () => void this._channel.dispose(),
onError: (filename, lineno, message) => { onError: (filename, lineno, message) => {
dump(`Error in worker: ${message} @${filename}:${lineno}\n`); dump(`WARNING: Error in worker: ${message} @${filename}:${lineno}\n`);
}, },
}; };
workerDebugger.addListener(this._workerDebuggerListener); workerDebugger.addListener(this._workerDebuggerListener);

Просмотреть файл

@ -0,0 +1,55 @@
"use strict";
const { Helper } = ChromeUtils.import('chrome://juggler/content/Helper.js');
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { initialize } = ChromeUtils.import('chrome://juggler/content/content/main.js');
const Ci = Components.interfaces;
const helper = new Helper();
let sameProcessInstanceNumber = 0;
class JugglerFrameChild extends JSWindowActorChild {
constructor() {
super();
this._eventListeners = [];
}
handleEvent(aEvent) {
if (this._agents && aEvent.target === this.document)
this._agents.pageAgent.onWindowEvent(aEvent);
}
actorCreated() {
this.actorName = `content::${this.browsingContext.browserId}/${this.browsingContext.id}/${++sameProcessInstanceNumber}`;
this._eventListeners.push(helper.addEventListener(this.contentWindow, 'load', event => {
this._agents?.pageAgent.onWindowEvent(event);
}));
if (this.document.documentURI.startsWith('moz-extension://'))
return;
this._agents = initialize(this.browsingContext, this.docShell, this);
}
_dispose() {
helper.removeListeners(this._eventListeners);
// We do not cleanup since agents are shared for all frames in the process.
// TODO: restore the cleanup.
// Reset transport so that all messages will be pending and will not throw any errors.
// this._channel.resetTransport();
// this._agents.pageAgent.dispose();
// this._agents.frameTree.dispose();
// this._agents = undefined;
}
didDestroy() {
this._dispose();
}
receiveMessage() { }
}
var EXPORTED_SYMBOLS = ['JugglerFrameChild'];

Просмотреть файл

@ -50,8 +50,7 @@ class WorkerData {
} }
class PageAgent { class PageAgent {
constructor(messageManager, browserChannel, frameTree) { constructor(browserChannel, frameTree) {
this._messageManager = messageManager;
this._browserChannel = browserChannel; this._browserChannel = browserChannel;
this._browserPage = browserChannel.connect('page'); this._browserPage = browserChannel.connect('page');
this._frameTree = frameTree; this._frameTree = frameTree;
@ -78,6 +77,7 @@ class PageAgent {
this._onWorkerCreated(worker); this._onWorkerCreated(worker);
// Report execution contexts. // Report execution contexts.
this._browserPage.emit('runtimeExecutionContextsCleared', {});
for (const context of this._runtime.executionContexts()) for (const context of this._runtime.executionContexts())
this._onExecutionContextCreated(context); this._onExecutionContextCreated(context);
@ -99,9 +99,7 @@ class PageAgent {
helper.addObserver(this._linkClicked.bind(this, true), 'juggler-link-click-sync'), helper.addObserver(this._linkClicked.bind(this, true), 'juggler-link-click-sync'),
helper.addObserver(this._onWindowOpenInNewContext.bind(this), 'juggler-window-open-in-new-context'), helper.addObserver(this._onWindowOpenInNewContext.bind(this), 'juggler-window-open-in-new-context'),
helper.addObserver(this._filePickerShown.bind(this), 'juggler-file-picker-shown'), helper.addObserver(this._filePickerShown.bind(this), 'juggler-file-picker-shown'),
helper.addEventListener(this._messageManager, 'DOMContentLoaded', this._onDOMContentLoaded.bind(this)),
helper.addObserver(this._onDocumentOpenLoad.bind(this), 'juggler-document-open-loaded'), helper.addObserver(this._onDocumentOpenLoad.bind(this), 'juggler-document-open-loaded'),
helper.on(this._frameTree, 'load', this._onLoad.bind(this)),
helper.on(this._frameTree, 'frameattached', this._onFrameAttached.bind(this)), helper.on(this._frameTree, 'frameattached', this._onFrameAttached.bind(this)),
helper.on(this._frameTree, 'framedetached', this._onFrameDetached.bind(this)), helper.on(this._frameTree, 'framedetached', this._onFrameDetached.bind(this)),
helper.on(this._frameTree, 'navigationstarted', this._onNavigationStarted.bind(this)), helper.on(this._frameTree, 'navigationstarted', this._onNavigationStarted.bind(this)),
@ -133,7 +131,6 @@ class PageAgent {
this._runtime.events.onExecutionContextDestroyed(this._onExecutionContextDestroyed.bind(this)), this._runtime.events.onExecutionContextDestroyed(this._onExecutionContextDestroyed.bind(this)),
this._runtime.events.onBindingCalled(this._onBindingCalled.bind(this)), this._runtime.events.onBindingCalled(this._onBindingCalled.bind(this)),
browserChannel.register('page', { browserChannel.register('page', {
addBinding: ({ worldName, name, script }) => this._frameTree.addBinding(worldName, name, script),
adoptNode: this._adoptNode.bind(this), adoptNode: this._adoptNode.bind(this),
crash: this._crash.bind(this), crash: this._crash.bind(this),
describeNode: this._describeNode.bind(this), describeNode: this._describeNode.bind(this),
@ -143,15 +140,11 @@ class PageAgent {
dispatchTapEvent: this._dispatchTapEvent.bind(this), dispatchTapEvent: this._dispatchTapEvent.bind(this),
getContentQuads: this._getContentQuads.bind(this), getContentQuads: this._getContentQuads.bind(this),
getFullAXTree: this._getFullAXTree.bind(this), getFullAXTree: this._getFullAXTree.bind(this),
goBack: this._goBack.bind(this),
goForward: this._goForward.bind(this),
insertText: this._insertText.bind(this), insertText: this._insertText.bind(this),
navigate: this._navigate.bind(this), navigate: this._navigate.bind(this),
reload: this._reload.bind(this),
scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this), scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this),
setCacheDisabled: this._setCacheDisabled.bind(this), setCacheDisabled: this._setCacheDisabled.bind(this),
setFileInputFiles: this._setFileInputFiles.bind(this), setFileInputFiles: this._setFileInputFiles.bind(this),
setInterceptFileChooserDialog: this._setInterceptFileChooserDialog.bind(this),
evaluate: this._runtime.evaluate.bind(this._runtime), evaluate: this._runtime.evaluate.bind(this._runtime),
callFunction: this._runtime.callFunction.bind(this._runtime), callFunction: this._runtime.callFunction.bind(this._runtime),
getObjectProperties: this._runtime.getObjectProperties.bind(this._runtime), getObjectProperties: this._runtime.getObjectProperties.bind(this._runtime),
@ -224,10 +217,6 @@ class PageAgent {
this._emitAllEvents(this._frameTree.mainFrame()); this._emitAllEvents(this._frameTree.mainFrame());
} }
_setInterceptFileChooserDialog({enabled}) {
this._docShell.fileInputInterceptionEnabled = !!enabled;
}
_linkClicked(sync, anchorElement) { _linkClicked(sync, anchorElement) {
if (anchorElement.ownerGlobal.docShell !== this._docShell) if (anchorElement.ownerGlobal.docShell !== this._docShell)
return; return;
@ -259,7 +248,9 @@ class PageAgent {
}); });
} }
_onDOMContentLoaded(event) { onWindowEvent(event) {
if (event.type !== 'DOMContentLoaded' && event.type !== 'load')
return;
if (!event.target.ownerGlobal) if (!event.target.ownerGlobal)
return; return;
const docShell = event.target.ownerGlobal.docShell; const docShell = event.target.ownerGlobal.docShell;
@ -268,7 +259,7 @@ class PageAgent {
return; return;
this._browserPage.emit('pageEventFired', { this._browserPage.emit('pageEventFired', {
frameId: frame.id(), frameId: frame.id(),
name: 'DOMContentLoaded', name: event.type,
}); });
} }
@ -291,13 +282,6 @@ class PageAgent {
}); });
} }
_onLoad(frame) {
this._browserPage.emit('pageEventFired', {
frameId: frame.id(),
name: 'load'
});
}
_onNavigationStarted(frame) { _onNavigationStarted(frame) {
this._browserPage.emit('pageNavigationStarted', { this._browserPage.emit('pageNavigationStarted', {
frameId: frame.id(), frameId: frame.id(),
@ -395,35 +379,16 @@ class PageAgent {
return {navigationId: frame.pendingNavigationId(), navigationURL: frame.pendingNavigationURL()}; return {navigationId: frame.pendingNavigationId(), navigationURL: frame.pendingNavigationURL()};
} }
async _reload({frameId, url}) {
const frame = this._frameTree.frame(frameId);
const docShell = frame.docShell().QueryInterface(Ci.nsIWebNavigation);
docShell.reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
}
async _goBack({frameId, url}) {
const frame = this._frameTree.frame(frameId);
const docShell = frame.docShell();
if (!docShell.canGoBack)
return {success: false};
docShell.goBack();
return {success: true};
}
async _goForward({frameId, url}) {
const frame = this._frameTree.frame(frameId);
const docShell = frame.docShell();
if (!docShell.canGoForward)
return {success: false};
docShell.goForward();
return {success: true};
}
async _adoptNode({frameId, objectId, executionContextId}) { async _adoptNode({frameId, objectId, executionContextId}) {
const frame = this._frameTree.frame(frameId); const frame = this._frameTree.frame(frameId);
if (!frame) if (!frame)
throw new Error('Failed to find frame with id = ' + frameId); throw new Error('Failed to find frame with id = ' + frameId);
const unsafeObject = frame.unsafeObject(objectId); let unsafeObject;
if (!objectId) {
unsafeObject = frame.domWindow().frameElement;
} else {
unsafeObject = frame.unsafeObject(objectId);
}
const context = this._runtime.findExecutionContext(executionContextId); const context = this._runtime.findExecutionContext(executionContextId);
const fromPrincipal = unsafeObject.nodePrincipal; const fromPrincipal = unsafeObject.nodePrincipal;
const toFrame = this._frameTree.frame(context.auxData().frameId); const toFrame = this._frameTree.frame(context.auxData().frameId);
@ -655,30 +620,23 @@ class PageAgent {
} }
_simulateDragEvent(type, x, y, modifiers) { _simulateDragEvent(type, x, y, modifiers) {
const window = this._frameTree.mainFrame().domWindow(); if (type !== 'drop' || dragService.dragAction) {
const element = window.windowUtils.elementFromPoint(x, y, false, false); const window = this._frameTree.mainFrame().domWindow();
const event = window.document.createEvent('DragEvent'); window.windowUtils.sendMouseEvent(
type,
event.initDragEvent( x,
type, y,
true /* bubble */, 0, /*button*/
true /* cancelable */, 0, /*clickCount*/
window, modifiers,
0 /* clickCount */, false /*aIgnoreRootScrollFrame*/,
window.mozInnerScreenX + x, undefined /*pressure*/,
window.mozInnerScreenY + y, undefined /*inputSource*/,
x, undefined /*isDOMEventSynthesized*/,
y, undefined /*isWidgetEventSynthesized*/,
modifiers & 2 /* ctrlkey */, 0, /*buttons*/
modifiers & 1 /* altKey */, );
modifiers & 4 /* shiftKey */, }
modifiers & 8 /* metaKey */,
0 /* button */, // firefox always has the button as 0 on drops, regardless of which was pressed
null /* relatedTarget */,
null,
);
if (type !== 'drop' || dragService.dragAction)
window.windowUtils.dispatchDOMEventViaPresShellForTesting(element, event);
if (type === 'drop') if (type === 'drop')
this._cancelDragIfNeeded(); this._cancelDragIfNeeded();
} }

Просмотреть файл

@ -367,7 +367,7 @@ class ExecutionContext {
try { try {
this._debuggee.executeInGlobal(script); this._debuggee.executeInGlobal(script);
} catch (e) { } catch (e) {
dump(`ERROR: ${e.message}\n${e.stack}\n`); dump(`WARNING: ${e.message}\n${e.stack}\n`);
} }
} }
@ -450,7 +450,7 @@ class ExecutionContext {
subtype = 'array'; subtype = 'array';
else if (Object.is(rawObj, null)) else if (Object.is(rawObj, null))
subtype = 'null'; subtype = 'null';
else if (this._instanceOf(debuggerObj, rawObj, 'Node')) else if (typeof Node !== 'undefined' && Node.isInstance(rawObj))
subtype = 'node'; subtype = 'node';
else if (this._instanceOf(debuggerObj, rawObj, 'RegExp')) else if (this._instanceOf(debuggerObj, rawObj, 'RegExp'))
subtype = 'regexp'; subtype = 'regexp';

Просмотреть файл

@ -8,119 +8,118 @@ const {FrameTree} = ChromeUtils.import('chrome://juggler/content/content/FrameTr
const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js'); const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js'); const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js');
let frameTree; const browsingContextToAgents = new Map();
const helper = new Helper(); const helper = new Helper();
const messageManager = this;
let pageAgent; function initialize(browsingContext, docShell, actor) {
if (browsingContext.parent) {
// For child frames, return agents from the main frame.
return browsingContextToAgents.get(browsingContext.top);
}
let failedToOverrideTimezone = false; let data = browsingContextToAgents.get(browsingContext);
if (data) {
// Rebind from one main frame actor to another one.
data.channel.bindToActor(actor);
return data;
}
const applySetting = { data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false };
geolocation: (geolocation) => { browsingContextToAgents.set(browsingContext, data);
if (geolocation) {
docShell.setGeolocationOverride({
coords: {
latitude: geolocation.latitude,
longitude: geolocation.longitude,
accuracy: geolocation.accuracy,
altitude: NaN,
altitudeAccuracy: NaN,
heading: NaN,
speed: NaN,
},
address: null,
timestamp: Date.now()
});
} else {
docShell.setGeolocationOverride(null);
}
},
onlineOverride: (onlineOverride) => { const applySetting = {
if (!onlineOverride) { geolocation: (geolocation) => {
docShell.onlineOverride = Ci.nsIDocShell.ONLINE_OVERRIDE_NONE; if (geolocation) {
return; docShell.setGeolocationOverride({
} coords: {
docShell.onlineOverride = onlineOverride === 'online' ? latitude: geolocation.latitude,
Ci.nsIDocShell.ONLINE_OVERRIDE_ONLINE : Ci.nsIDocShell.ONLINE_OVERRIDE_OFFLINE; longitude: geolocation.longitude,
}, accuracy: geolocation.accuracy,
altitude: NaN,
altitudeAccuracy: NaN,
heading: NaN,
speed: NaN,
},
address: null,
timestamp: Date.now()
});
} else {
docShell.setGeolocationOverride(null);
}
},
bypassCSP: (bypassCSP) => { onlineOverride: (onlineOverride) => {
docShell.bypassCSPEnabled = bypassCSP; if (!onlineOverride) {
}, docShell.onlineOverride = Ci.nsIDocShell.ONLINE_OVERRIDE_NONE;
return;
}
docShell.onlineOverride = onlineOverride === 'online' ?
Ci.nsIDocShell.ONLINE_OVERRIDE_ONLINE : Ci.nsIDocShell.ONLINE_OVERRIDE_OFFLINE;
},
timezoneId: (timezoneId) => { bypassCSP: (bypassCSP) => {
failedToOverrideTimezone = !docShell.overrideTimezone(timezoneId); docShell.bypassCSPEnabled = bypassCSP;
}, },
locale: (locale) => { timezoneId: (timezoneId) => {
docShell.languageOverride = locale; data.failedToOverrideTimezone = !docShell.overrideTimezone(timezoneId);
}, },
scrollbarsHidden: (hidden) => { locale: (locale) => {
frameTree.setScrollbarsHidden(hidden); docShell.languageOverride = locale;
}, },
colorScheme: (colorScheme) => { scrollbarsHidden: (hidden) => {
frameTree.setColorScheme(colorScheme); data.frameTree.setScrollbarsHidden(hidden);
}, },
reducedMotion: (reducedMotion) => { javaScriptDisabled: (javaScriptDisabled) => {
frameTree.setReducedMotion(reducedMotion); data.frameTree.setJavaScriptDisabled(javaScriptDisabled);
}, },
};
forcedColors: (forcedColors) => { const contextCrossProcessCookie = Services.cpmm.sharedData.get('juggler:context-cookie-' + browsingContext.originAttributes.userContextId) || { initScripts: [], bindings: [], settings: {} };
frameTree.setForcedColors(forcedColors); const pageCrossProcessCookie = Services.cpmm.sharedData.get('juggler:page-cookie-' + browsingContext.browserId) || { initScripts: [], bindings: [], interceptFileChooserDialog: false };
},
};
const channel = SimpleChannel.createForMessageManager('content::page', messageManager);
function initialize() {
const response = sendSyncMessage('juggler:content-ready')[0];
// If we didn't get a response, then we don't want to do anything
// as a part of this frame script.
if (!response)
return;
const {
initScripts = [],
bindings = [],
settings = {}
} = response || {};
// Enforce focused state for all top level documents. // Enforce focused state for all top level documents.
docShell.overrideHasFocus = true; docShell.overrideHasFocus = true;
docShell.forceActiveState = true; docShell.forceActiveState = true;
frameTree = new FrameTree(docShell); docShell.disallowBFCache = true;
for (const [name, value] of Object.entries(settings)) { data.frameTree = new FrameTree(docShell);
for (const [name, value] of Object.entries(contextCrossProcessCookie.settings)) {
if (value !== undefined) if (value !== undefined)
applySetting[name](value); applySetting[name](value);
} }
for (const { worldName, name, script } of bindings) for (const { worldName, name, script } of [...contextCrossProcessCookie.bindings, ...pageCrossProcessCookie.bindings])
frameTree.addBinding(worldName, name, script); data.frameTree.addBinding(worldName, name, script);
frameTree.setInitScripts(initScripts); data.frameTree.setInitScripts([...contextCrossProcessCookie.initScripts, ...pageCrossProcessCookie.initScripts]);
data.channel = SimpleChannel.createForActor(actor);
data.pageAgent = new PageAgent(data.channel, data.frameTree);
docShell.fileInputInterceptionEnabled = !!pageCrossProcessCookie.interceptFileChooserDialog;
pageAgent = new PageAgent(messageManager, channel, frameTree); data.channel.register('', {
channel.register('', {
setInitScripts(scripts) { setInitScripts(scripts) {
frameTree.setInitScripts(scripts); data.frameTree.setInitScripts(scripts);
}, },
addBinding({worldName, name, script}) { addBinding({worldName, name, script}) {
frameTree.addBinding(worldName, name, script); data.frameTree.addBinding(worldName, name, script);
}, },
applyContextSetting({name, value}) { applyContextSetting({name, value}) {
applySetting[name](value); applySetting[name](value);
}, },
setInterceptFileChooserDialog(enabled) {
docShell.fileInputInterceptionEnabled = !!enabled;
},
ensurePermissions() { ensurePermissions() {
// noop, just a rountrip. // noop, just a rountrip.
}, },
hasFailedToOverrideTimezone() { hasFailedToOverrideTimezone() {
return failedToOverrideTimezone; return data.failedToOverrideTimezone;
}, },
async awaitViewportDimensions({width, height, deviceSizeIsPageSize}) { async awaitViewportDimensions({width, height, deviceSizeIsPageSize}) {
@ -142,14 +141,8 @@ function initialize() {
}, },
}); });
const gListeners = [ return data;
helper.addEventListener(messageManager, 'unload', msg => {
helper.removeListeners(gListeners);
pageAgent.dispose();
frameTree.dispose();
channel.dispose();
}),
];
} }
initialize(); var EXPORTED_SYMBOLS = ['initialize'];
this.initialize = initialize;

Просмотреть файл

@ -11,11 +11,13 @@ juggler.jar:
content/NetworkObserver.js (NetworkObserver.js) content/NetworkObserver.js (NetworkObserver.js)
content/TargetRegistry.js (TargetRegistry.js) content/TargetRegistry.js (TargetRegistry.js)
content/SimpleChannel.js (SimpleChannel.js) content/SimpleChannel.js (SimpleChannel.js)
content/JugglerFrameParent.jsm (JugglerFrameParent.jsm)
content/protocol/PrimitiveTypes.js (protocol/PrimitiveTypes.js) content/protocol/PrimitiveTypes.js (protocol/PrimitiveTypes.js)
content/protocol/Protocol.js (protocol/Protocol.js) content/protocol/Protocol.js (protocol/Protocol.js)
content/protocol/Dispatcher.js (protocol/Dispatcher.js) content/protocol/Dispatcher.js (protocol/Dispatcher.js)
content/protocol/PageHandler.js (protocol/PageHandler.js) content/protocol/PageHandler.js (protocol/PageHandler.js)
content/protocol/BrowserHandler.js (protocol/BrowserHandler.js) content/protocol/BrowserHandler.js (protocol/BrowserHandler.js)
content/content/JugglerFrameChild.jsm (content/JugglerFrameChild.jsm)
content/content/main.js (content/main.js) content/content/main.js (content/main.js)
content/content/FrameTree.js (content/FrameTree.js) content/content/FrameTree.js (content/FrameTree.js)
content/content/PageAgent.js (content/PageAgent.js) content/content/PageAgent.js (content/PageAgent.js)

Просмотреть файл

@ -214,7 +214,7 @@ class BrowserHandler {
} }
async ['Browser.setJavaScriptDisabled']({browserContextId, javaScriptDisabled}) { async ['Browser.setJavaScriptDisabled']({browserContextId, javaScriptDisabled}) {
await this._targetRegistry.browserContextForId(browserContextId).setJavaScriptDisabled(javaScriptDisabled); await this._targetRegistry.browserContextForId(browserContextId).applySetting('javaScriptDisabled', nullToUndefined(javaScriptDisabled));
} }
async ['Browser.setLocaleOverride']({browserContextId, locale}) { async ['Browser.setLocaleOverride']({browserContextId, locale}) {

Просмотреть файл

@ -89,6 +89,11 @@ class PageHandler {
// to be ignored by the protocol clients. // to be ignored by the protocol clients.
this._isPageReady = false; this._isPageReady = false;
// Whether the page is about to go cross-process after navigation.
this._isTransferringCrossProcessNavigation = false;
this._mainFrameId = undefined;
this._lastMainFrameNavigationId = undefined;
if (this._pageTarget.videoRecordingInfo()) if (this._pageTarget.videoRecordingInfo())
this._onVideoRecordingStarted(); this._onVideoRecordingStarted();
@ -100,6 +105,7 @@ class PageHandler {
}), }),
helper.on(this._pageTarget, PageTarget.Events.ScreencastStarted, this._onVideoRecordingStarted.bind(this)), helper.on(this._pageTarget, PageTarget.Events.ScreencastStarted, this._onVideoRecordingStarted.bind(this)),
helper.on(this._pageTarget, PageTarget.Events.ScreencastFrame, this._onScreencastFrame.bind(this)), helper.on(this._pageTarget, PageTarget.Events.ScreencastFrame, this._onScreencastFrame.bind(this)),
helper.on(this._pageTarget, PageTarget.Events.TopBrowsingContextReplaced, this._onTopBrowsingContextReplaced.bind(this)),
helper.on(this._pageNetwork, PageNetwork.Events.Request, this._handleNetworkEvent.bind(this, 'Network.requestWillBeSent')), helper.on(this._pageNetwork, PageNetwork.Events.Request, this._handleNetworkEvent.bind(this, 'Network.requestWillBeSent')),
helper.on(this._pageNetwork, PageNetwork.Events.Response, this._handleNetworkEvent.bind(this, 'Network.responseReceived')), helper.on(this._pageNetwork, PageNetwork.Events.Response, this._handleNetworkEvent.bind(this, 'Network.responseReceived')),
helper.on(this._pageNetwork, PageNetwork.Events.RequestFinished, this._handleNetworkEvent.bind(this, 'Network.requestFinished')), helper.on(this._pageNetwork, PageNetwork.Events.RequestFinished, this._handleNetworkEvent.bind(this, 'Network.requestFinished')),
@ -113,9 +119,9 @@ class PageHandler {
pageFrameDetached: emitProtocolEvent('Page.frameDetached'), pageFrameDetached: emitProtocolEvent('Page.frameDetached'),
pageLinkClicked: emitProtocolEvent('Page.linkClicked'), pageLinkClicked: emitProtocolEvent('Page.linkClicked'),
pageWillOpenNewWindowAsynchronously: emitProtocolEvent('Page.willOpenNewWindowAsynchronously'), pageWillOpenNewWindowAsynchronously: emitProtocolEvent('Page.willOpenNewWindowAsynchronously'),
pageNavigationAborted: emitProtocolEvent('Page.navigationAborted'), pageNavigationAborted: params => this._handleNavigationEvent('Page.navigationAborted', params),
pageNavigationCommitted: emitProtocolEvent('Page.navigationCommitted'), pageNavigationCommitted: params => this._handleNavigationEvent('Page.navigationCommitted', params),
pageNavigationStarted: emitProtocolEvent('Page.navigationStarted'), pageNavigationStarted: params => this._handleNavigationEvent('Page.navigationStarted', params),
pageReady: this._onPageReady.bind(this), pageReady: this._onPageReady.bind(this),
pageSameDocumentNavigation: emitProtocolEvent('Page.sameDocumentNavigation'), pageSameDocumentNavigation: emitProtocolEvent('Page.sameDocumentNavigation'),
pageUncaughtError: emitProtocolEvent('Page.uncaughtError'), pageUncaughtError: emitProtocolEvent('Page.uncaughtError'),
@ -129,10 +135,11 @@ class PageHandler {
return; return;
} }
} }
emitProtocolEvent('Runtime.console')(params); this._session.emitEvent('Runtime.console', params);
}, },
runtimeExecutionContextCreated: emitProtocolEvent('Runtime.executionContextCreated'), runtimeExecutionContextCreated: emitProtocolEvent('Runtime.executionContextCreated'),
runtimeExecutionContextDestroyed: emitProtocolEvent('Runtime.executionContextDestroyed'), runtimeExecutionContextDestroyed: emitProtocolEvent('Runtime.executionContextDestroyed'),
runtimeExecutionContextsCleared: emitProtocolEvent('Runtime.executionContextsCleared'),
webSocketCreated: emitProtocolEvent('Page.webSocketCreated'), webSocketCreated: emitProtocolEvent('Page.webSocketCreated'),
webSocketOpened: emitProtocolEvent('Page.webSocketOpened'), webSocketOpened: emitProtocolEvent('Page.webSocketOpened'),
@ -157,6 +164,28 @@ class PageHandler {
this._session.emitEvent('Page.screencastFrame', params); this._session.emitEvent('Page.screencastFrame', params);
} }
_onTopBrowsingContextReplaced() {
this._isTransferringCrossProcessNavigation = true;
}
_handleNavigationEvent(event, params) {
if (this._isTransferringCrossProcessNavigation && params.frameId === this._mainFrameId) {
// During a cross-process navigation, http channel in the new process might not be
// the same as the original one in the old process, for example after a redirect/interception.
// Therefore, the new proces has a new navigationId.
//
// To preserve protocol consistency, we replace the new navigationId with
// the old navigationId.
params.navigationId = this._lastMainFrameNavigationId || params.navigationId;
if (event === 'Page.navigationCommitted' || event === 'Page.navigationAborted')
this._isTransferringCrossProcessNavigation = false;
}
if (event === 'Page.navigationStarted' && params.frameId === this._mainFrameId)
this._lastMainFrameNavigationId = params.navigationId;
this._session.emitEvent(event, params);
}
_onPageReady(event) { _onPageReady(event) {
this._isPageReady = true; this._isPageReady = true;
this._session.emitEvent('Page.ready'); this._session.emitEvent('Page.ready');
@ -210,6 +239,8 @@ class PageHandler {
} }
_onFrameAttached({frameId, parentFrameId}) { _onFrameAttached({frameId, parentFrameId}) {
if (!parentFrameId)
this._mainFrameId = frameId;
this._session.emitEvent('Page.frameAttached', {frameId, parentFrameId}); this._session.emitEvent('Page.frameAttached', {frameId, parentFrameId});
this._reportedFrameIds.add(frameId); this._reportedFrameIds.add(frameId);
const events = this._networkEventsForUnreportedFrameIds.get(frameId) || []; const events = this._networkEventsForUnreportedFrameIds.get(frameId) || [];
@ -295,8 +326,8 @@ class PageHandler {
return await this._contentPage.send('setCacheDisabled', options); return await this._contentPage.send('setCacheDisabled', options);
} }
async ['Page.addBinding'](options) { async ['Page.addBinding']({ worldName, name, script }) {
return await this._contentPage.send('addBinding', options); return await this._pageTarget.addBinding(worldName, name, script);
} }
async ['Page.adoptNode'](options) { async ['Page.adoptNode'](options) {
@ -358,16 +389,25 @@ class PageHandler {
return await this._contentPage.send('navigate', options); return await this._contentPage.send('navigate', options);
} }
async ['Page.goBack'](options) { async ['Page.goBack']({}) {
return await this._contentPage.send('goBack', options); const browsingContext = this._pageTarget.linkedBrowser().browsingContext;
if (!browsingContext.embedderElement?.canGoBack)
return { success: false };
browsingContext.goBack();
return { success: true };
} }
async ['Page.goForward'](options) { async ['Page.goForward']({}) {
return await this._contentPage.send('goForward', options); const browsingContext = this._pageTarget.linkedBrowser().browsingContext;
if (!browsingContext.embedderElement?.canGoForward)
return { success: false };
browsingContext.goForward();
return { success: true };
} }
async ['Page.reload'](options) { async ['Page.reload']({}) {
return await this._contentPage.send('reload', options); const browsingContext = this._pageTarget.linkedBrowser().browsingContext;
browsingContext.reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
} }
async ['Page.describeNode'](options) { async ['Page.describeNode'](options) {
@ -438,8 +478,8 @@ class PageHandler {
dialog.dismiss(); dialog.dismiss();
} }
async ['Page.setInterceptFileChooserDialog'](options) { async ['Page.setInterceptFileChooserDialog']({ enabled }) {
return await this._contentPage.send('setInterceptFileChooserDialog', options); return await this._pageTarget.setInterceptFileChooserDialog(enabled);
} }
async ['Page.startScreencast'](options) { async ['Page.startScreencast'](options) {

Просмотреть файл

@ -227,6 +227,7 @@ const Browser = {
uuid: t.String, uuid: t.String,
browserContextId: t.Optional(t.String), browserContextId: t.Optional(t.String),
pageTargetId: t.String, pageTargetId: t.String,
frameId: t.String,
url: t.String, url: t.String,
suggestedFileName: t.String, suggestedFileName: t.String,
}, },
@ -573,6 +574,8 @@ const Runtime = {
'executionContextDestroyed': { 'executionContextDestroyed': {
executionContextId: t.String, executionContextId: t.String,
}, },
'executionContextsCleared': {
},
'console': { 'console': {
executionContextId: t.String, executionContextId: t.String,
args: t.Array(runtimeTypes.RemoteObject), args: t.Array(runtimeTypes.RemoteObject),
@ -847,7 +850,8 @@ const Page = {
'adoptNode': { 'adoptNode': {
params: { params: {
frameId: t.String, frameId: t.String,
objectId: t.String, // Missing objectId adopts frame owner.
objectId: t.Optional(t.String),
executionContextId: t.String, executionContextId: t.String,
}, },
returns: { returns: {

Просмотреть файл

@ -19,7 +19,9 @@ using namespace webrtc;
namespace mozilla { namespace mozilla {
rtc::scoped_refptr<webrtc::VideoCaptureModuleEx> HeadlessWindowCapturer::Create(HeadlessWidget* headlessWindow) { rtc::scoped_refptr<webrtc::VideoCaptureModuleEx> HeadlessWindowCapturer::Create(HeadlessWidget* headlessWindow) {
return new rtc::RefCountedObject<HeadlessWindowCapturer>(headlessWindow); return rtc::scoped_refptr<webrtc::VideoCaptureModuleEx>(
new rtc::RefCountedObject<HeadlessWindowCapturer>(headlessWindow)
);
} }
HeadlessWindowCapturer::HeadlessWindowCapturer(mozilla::widget::HeadlessWidget* window) HeadlessWindowCapturer::HeadlessWindowCapturer(mozilla::widget::HeadlessWidget* window)

Просмотреть файл

@ -55,7 +55,7 @@ rtc::scoped_refptr<webrtc::VideoCaptureModuleEx> CreateWindowCapturer(nsIWidget*
windowId.AppendPrintf("%" PRIuPTR, rawWindowId); windowId.AppendPrintf("%" PRIuPTR, rawWindowId);
bool captureCursor = false; bool captureCursor = false;
static int moduleId = 0; static int moduleId = 0;
return webrtc::DesktopCaptureImpl::Create(++moduleId, windowId.get(), CaptureDeviceType::Window, captureCursor); return rtc::scoped_refptr<webrtc::VideoCaptureModuleEx>(webrtc::DesktopCaptureImpl::Create(++moduleId, windowId.get(), CaptureDeviceType::Window, captureCursor));
} }
nsresult generateUid(nsString& uid) { nsresult generateUid(nsString& uid) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -8,24 +8,88 @@ pref("datareporting.policy.dataSubmissionEnabled", false);
pref("datareporting.policy.dataSubmissionPolicyAccepted", false); pref("datareporting.policy.dataSubmissionPolicyAccepted", false);
pref("datareporting.policy.dataSubmissionPolicyBypassNotification", true); pref("datareporting.policy.dataSubmissionPolicyBypassNotification", true);
// @see https://github.com/microsoft/playwright/issues/4297 // Force pdfs into downloads.
pref("browser.tabs.remote.useCrossOriginEmbedderPolicy", false);
pref("browser.tabs.remote.useCrossOriginOpenerPolicy", false);
pref("browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", false);
pref("pdfjs.disabled", true); pref("pdfjs.disabled", true);
// Disable all kinds of cross-process navigations until we are ready. // Disable cross-process iframes, but not cross-process navigations.
pref("fission.autostart", false);
pref("fission.webContentIsolationStrategy", 0); pref("fission.webContentIsolationStrategy", 0);
// Disable BFCache in parent process.
// We also separately disable BFCache in content via docSchell property.
pref("fission.bfcacheInParent", false); pref("fission.bfcacheInParent", false);
// Avoid about:blank loading cross-process until we are ready.
pref("browser.tabs.remote.systemTriggeredAboutBlankAnywhere", true); // File url navigations behave differently from http, we are not ready.
pref("browser.tabs.remote.separateFileUriProcess", false);
// Disable first-party-based cookie partitioning.
// When it is enabled, we have to retain "thirdPartyCookie^" permissions
// in the storageState.
pref("network.cookie.cookieBehavior", 4);
// Increase max number of child web processes so that new pages
// get a new process by default and we have a process isolation
// between pages from different contexts. If this becomes a performance
// issue we can povide custom '@mozilla.org/ipc/processselector;1'
pref("dom.ipc.processCount", 60000);
// Never reuse processes as they may keep previously overridden values
// (locale, timezone etc.).
pref("dom.ipc.processPrelaunch.enabled", false);
// Isolate permissions by user context.
pref("permissions.isolateBy.userContext", true);
// We need this to issue Page.navigate from inside the renderer
// to cross-process domains, for example file urls.
pref("security.sandbox.content.level", 2);
// Allow creating files in content process - required for
// |Page.setFileInputFiles| protocol method.
pref("dom.file.createInChild", true);
// Do not warn when closing all open tabs
pref("browser.tabs.warnOnClose", false);
// Do not warn when closing all other open tabs
pref("browser.tabs.warnOnCloseOtherTabs", false);
// Do not warn when multiple tabs will be opened
pref("browser.tabs.warnOnOpen", false);
// Do not warn on quitting Firefox
pref("browser.warnOnQuit", false);
// Disable popup-blocker
pref("dom.disable_open_during_load", false);
// Disable the ProcessHangMonitor
pref("dom.ipc.reportProcessHangs", false);
pref("hangmonitor.timeout", 0);
// Allow the application to have focus even it runs in the background
pref("focusmanager.testmode", true);
// No ICC color correction. We need this for reproducible screenshots.
// See https://developer.mozilla.org/en/docs/Mozilla/Firefox/Releases/3.5/ICC_color_correction_in_Firefox.
pref("gfx.color_management.mode", 0);
pref("gfx.color_management.rendering_intent", 3);
// Always use network provider for geolocation tests so we bypass the
// macOS dialog raised by the corelocation provider
pref("geo.provider.testing", true);
// ================================================================= // =================================================================
// THESE ARE NICHE PROPERTIES THAT ARE NICE TO HAVE
// ================================================================= // =================================================================
// Avoid stalling on shutdown, after "xpcom-will-shutdown" phase.
// This at least happens when shutting down soon after launching.
// See AppShutdown.cpp for more details on shutdown phases.
pref("toolkit.shutdown.fastShutdownStage", 3);
// @see https://github.com/microsoft/playwright/issues/8178 // @see https://github.com/microsoft/playwright/issues/8178
pref("dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", true); pref("dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", true);
@ -36,23 +100,9 @@ pref("ui.systemUsesDarkTheme", 0);
// support for the new modal UI (see Bug 1686743). // support for the new modal UI (see Bug 1686743).
pref("prompts.contentPromptSubDialog", false); pref("prompts.contentPromptSubDialog", false);
// Increase max number of child web processes so that new pages
// get a new process by default and we have a process isolation
// between pages from different contexts. If this becomes a performance
// issue we can povide custom '@mozilla.org/ipc/processselector;1'
//
pref("dom.ipc.processCount", 60000);
// Never reuse processes as they may keep previously overridden values
// (locale, timezone etc.).
pref("dom.ipc.processPrelaunch.enabled", false);
// Do not use system colors - they are affected by themes. // Do not use system colors - they are affected by themes.
pref("ui.use_standins_for_native_colors", true); pref("ui.use_standins_for_native_colors", true);
// Isolate permissions by user context.
pref("permissions.isolateBy.userContext", true);
pref("dom.push.serverURL", ""); pref("dom.push.serverURL", "");
// This setting breaks settings loading. // This setting breaks settings loading.
pref("services.settings.server", ""); pref("services.settings.server", "");
@ -87,14 +137,10 @@ pref("browser.newtabpage.enabled", false);
// Do not redirect user when a milstone upgrade of Firefox is detected // Do not redirect user when a milstone upgrade of Firefox is detected
pref("browser.startup.homepage_override.mstone", "ignore"); pref("browser.startup.homepage_override.mstone", "ignore");
pref("browser.tabs.remote.separateFileUriProcess", false);
pref("security.sandbox.content.level", 2);
// Disable topstories // Disable topstories
pref("browser.newtabpage.activity-stream.feeds.section.topstories", false); pref("browser.newtabpage.activity-stream.feeds.section.topstories", false);
// DevTools JSONViewer sometimes fails to load dependencies with its require.js. // DevTools JSONViewer sometimes fails to load dependencies with its require.js.
// This doesn't affect Puppeteer operations, but spams console with a lot of // This spams console with a lot of unpleasant errors.
// unpleasant errors.
// (bug 1424372) // (bug 1424372)
pref("devtools.jsonview.enabled", false); pref("devtools.jsonview.enabled", false);
@ -107,10 +153,6 @@ pref("devtools.jsonview.enabled", false);
// (bug 1176798, bug 1177018, bug 1210465) // (bug 1176798, bug 1177018, bug 1210465)
pref("apz.content_response_timeout", 60000); pref("apz.content_response_timeout", 60000);
// Allow creating files in content process - required for
// |Page.setFileInputFiles| protocol method.
pref("dom.file.createInChild", true);
// Indicate that the download panel has been shown once so that // Indicate that the download panel has been shown once so that
// whichever download test runs first doesn't show the popup // whichever download test runs first doesn't show the popup
// inconsistently. // inconsistently.
@ -142,15 +184,6 @@ pref("browser.tabs.closeWindowWithLastTab", true);
// unloaded // unloaded
pref("browser.tabs.disableBackgroundZombification", false); pref("browser.tabs.disableBackgroundZombification", false);
// Do not warn when closing all open tabs
pref("browser.tabs.warnOnClose", false);
// Do not warn when closing all other open tabs
pref("browser.tabs.warnOnCloseOtherTabs", false);
// Do not warn when multiple tabs will be opened
pref("browser.tabs.warnOnOpen", false);
// Disable first run splash page on Windows 10 // Disable first run splash page on Windows 10
pref("browser.usedOnWindows10.introURL", ""); pref("browser.usedOnWindows10.introURL", "");
@ -163,9 +196,6 @@ pref("browser.uitour.enabled", false);
// network connections. // network connections.
pref("browser.urlbar.suggest.searches", false); pref("browser.urlbar.suggest.searches", false);
// Do not warn on quitting Firefox
pref("browser.warnOnQuit", false);
// Do not show datareporting policy notifications which can // Do not show datareporting policy notifications which can
// interfere with tests // interfere with tests
pref("datareporting.healthreport.documentServerURI", ""); pref("datareporting.healthreport.documentServerURI", "");
@ -178,13 +208,6 @@ pref("datareporting.healthreport.uploadEnabled", false);
// Automatically unload beforeunload alerts // Automatically unload beforeunload alerts
pref("dom.disable_beforeunload", false); pref("dom.disable_beforeunload", false);
// Disable popup-blocker
pref("dom.disable_open_during_load", false);
// Disable the ProcessHangMonitor
pref("dom.ipc.reportProcessHangs", false);
pref("hangmonitor.timeout", 0);
// Disable slow script dialogues // Disable slow script dialogues
pref("dom.max_chrome_script_run_time", 0); pref("dom.max_chrome_script_run_time", 0);
pref("dom.max_script_run_time", 0); pref("dom.max_script_run_time", 0);
@ -210,21 +233,9 @@ pref("extensions.webservice.discoverURL", "");
pref("extensions.screenshots.disabled", true); pref("extensions.screenshots.disabled", true);
pref("extensions.screenshots.upload-disabled", true); pref("extensions.screenshots.upload-disabled", true);
// Allow the application to have focus even it runs in the background
pref("focusmanager.testmode", true);
// Disable useragent updates // Disable useragent updates
pref("general.useragent.updates.enabled", false); pref("general.useragent.updates.enabled", false);
// No ICC color correction.
// See https://developer.mozilla.org/en/docs/Mozilla/Firefox/Releases/3.5/ICC_color_correction_in_Firefox.
pref("gfx.color_management.mode", 0);
pref("gfx.color_management.rendering_intent", 3);
// Always use network provider for geolocation tests so we bypass the
// macOS dialog raised by the corelocation provider
pref("geo.provider.testing", true);
// Do not scan Wifi // Do not scan Wifi
pref("geo.wifi.scan", false); pref("geo.wifi.scan", false);

Просмотреть файл

@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/WebKit/WebKit.git" REMOTE_URL="https://github.com/WebKit/WebKit.git"
BASE_BRANCH="main" BASE_BRANCH="main"
BASE_REVISION="c888c485b787e204057b56d69536aae567ab8b3a" BASE_REVISION="675d141bdcf7fa6df9bdf505d46e46fdac638452"

Просмотреть файл

@ -229,6 +229,7 @@ const NSActivityOptions ActivityOptions =
if (!configuration) { if (!configuration) {
configuration = [[WKWebViewConfiguration alloc] init]; configuration = [[WKWebViewConfiguration alloc] init];
configuration.websiteDataStore = [self persistentDataStore]; configuration.websiteDataStore = [self persistentDataStore];
configuration._controlledByAutomation = true;
configuration.preferences._fullScreenEnabled = YES; configuration.preferences._fullScreenEnabled = YES;
configuration.preferences._developerExtrasEnabled = YES; configuration.preferences._developerExtrasEnabled = YES;
configuration.preferences._mediaDevicesEnabled = YES; configuration.preferences._mediaDevicesEnabled = YES;
@ -496,6 +497,12 @@ const NSActivityOptions ActivityOptions =
download.delegate = self; download.delegate = self;
} }
// Always automatically accept requestStorageAccess dialog.
- (void)_webView:(WKWebView *)webView requestStorageAccessPanelForDomain:(NSString *)requestingDomain underCurrentDomain:(NSString *)currentDomain completionHandler:(void (^)(BOOL result))completionHandler
{
completionHandler(true);
}
#pragma mark WKDownloadDelegate #pragma mark WKDownloadDelegate
- (void)download:(WKDownload *)download decideDestinationUsingResponse:(NSURLResponse *)response suggestedFilename:(NSString *)suggestedFilename completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler - (void)download:(WKDownload *)download decideDestinationUsingResponse:(NSURLResponse *)response suggestedFilename:(NSString *)suggestedFilename completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler

Просмотреть файл

@ -67,10 +67,22 @@ static void* keyValueObservingContext = &keyValueObservingContext;
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
{ {
// Retain the frame size, but make sure that float kWindowControlBarHeight = 35;
// the top of the window is always visible.
CGFloat yPos = NSHeight(self.screen.frame) - 100 - NSHeight(self.frame); CGFloat screenHeight = screen.frame.size.height; // e.g. 1080
return NSMakeRect(frameRect.origin.x, yPos, frameRect.size.width, frameRect.size.height); CGFloat windowHeight = self.frame.size.height; // e.g. 5000
CGFloat screenYOffset = screen.frame.origin.y; // screen arrangement offset
bool exceedsAtTheTop = (NSMaxY(frameRect) - screenYOffset) > screenHeight;
bool exceedsAtTheBottom = (frameRect.origin.y + windowHeight + -screenYOffset - kWindowControlBarHeight) < 0;
CGFloat newOriginY = frameRect.origin.y;
// if it exceeds the height, then we move it to the top of the screen
if (screenHeight > 0 && exceedsAtTheTop)
newOriginY = screenHeight - windowHeight - kWindowControlBarHeight + screenYOffset;
// if it exceeds the bottom, then we move it to the bottom of the screen but make sure that the control bar is still visible
else if (screenHeight > 0 && exceedsAtTheBottom)
newOriginY = -windowHeight + screenYOffset + kWindowControlBarHeight;
return NSMakeRect(frameRect.origin.x, newOriginY, frameRect.size.width, frameRect.size.height);
} }
@end @end
@ -670,6 +682,12 @@ static BOOL areEssentiallyEqual(double a, double b)
}]; }];
} }
// Always automatically accept requestStorageAccess dialog.
- (void)_webView:(WKWebView *)webView requestStorageAccessPanelForDomain:(NSString *)requestingDomain underCurrentDomain:(NSString *)currentDomain completionHandler:(void (^)(BOOL result))completionHandler
{
completionHandler(true);
}
- (WKDragDestinationAction)_webView:(WKWebView *)webView dragDestinationActionMaskForDraggingInfo:(id)draggingInfo - (WKDragDestinationAction)_webView:(WKWebView *)webView dragDestinationActionMaskForDraggingInfo:(id)draggingInfo
{ {
return WKDragDestinationActionAny; return WKDragDestinationActionAny;

Просмотреть файл

@ -1,76 +1,76 @@
// Microsoft Visual C++ generated resource script. // Microsoft Visual C++ generated resource script.
// //
#include "PlaywrightResource.h" #include "PlaywrightResource.h"
#define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#define APSTUDIO_HIDDEN_SYMBOLS #define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h" #include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS #undef APSTUDIO_HIDDEN_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources // English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32 #ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252) #pragma code_page(1252)
#endif //_WIN32 #endif //_WIN32
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Icon // Icon
// //
// Icon with lowest ID value placed first to ensure application icon // Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems. // remains consistent on all systems.
IDI_PLAYWRIGHT ICON "Playwright.ico" IDI_PLAYWRIGHT ICON "Playwright.ico"
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// TEXTINCLUDE // TEXTINCLUDE
// //
1 TEXTINCLUDE 1 TEXTINCLUDE
BEGIN BEGIN
"PlaywrightResource.\0" "PlaywrightResource.\0"
END END
2 TEXTINCLUDE 2 TEXTINCLUDE
BEGIN BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n" "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n" "#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0" "\0"
END END
3 TEXTINCLUDE 3 TEXTINCLUDE
BEGIN BEGIN
"\r\n" "\r\n"
"\0" "\0"
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources #endif // English (U.S.) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED #ifndef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Generated from the TEXTINCLUDE 3 resource. // Generated from the TEXTINCLUDE 3 resource.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED #endif // not APSTUDIO_INVOKED

Просмотреть файл

@ -1,354 +1,354 @@
// Microsoft Visual C++ generated resource script. // Microsoft Visual C++ generated resource script.
// //
#include "PlaywrightLibResource.h" #include "PlaywrightLibResource.h"
#define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#define APSTUDIO_HIDDEN_SYMBOLS #define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h" #include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS #undef APSTUDIO_HIDDEN_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// English (United States) resources // English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252) #pragma code_page(1252)
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Icon // Icon
// //
// Icon with lowest ID value placed first to ensure application icon // Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems. // remains consistent on all systems.
IDI_PLAYWRIGHT ICON "Playwright.ico" IDI_PLAYWRIGHT ICON "Playwright.ico"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Menu // Menu
// //
IDC_PLAYWRIGHT MENU IDC_PLAYWRIGHT MENU
BEGIN BEGIN
POPUP "&File" POPUP "&File"
BEGIN BEGIN
MENUITEM "New Window\tCtrl-N" IDM_NEW_WINDOW MENUITEM "New Window\tCtrl-N" IDM_NEW_WINDOW
MENUITEM "Close\tCtrl-W", IDM_CLOSE_WINDOW MENUITEM "Close\tCtrl-W", IDM_CLOSE_WINDOW
END END
POPUP "&View" POPUP "&View"
BEGIN BEGIN
MENUITEM "Actual Size\tCtrl+0", IDM_ACTUAL_SIZE MENUITEM "Actual Size\tCtrl+0", IDM_ACTUAL_SIZE
MENUITEM "Zoom In\tCtrl++", IDM_ZOOM_IN MENUITEM "Zoom In\tCtrl++", IDM_ZOOM_IN
MENUITEM "Zoom Out\tCtrl+-", IDM_ZOOM_OUT MENUITEM "Zoom Out\tCtrl+-", IDM_ZOOM_OUT
MENUITEM "Invert Colors", IDM_INVERT_COLORS MENUITEM "Invert Colors", IDM_INVERT_COLORS
END END
POPUP "&History" POPUP "&History"
BEGIN BEGIN
MENUITEM "Reload\tCtrl-R", IDM_RELOAD MENUITEM "Reload\tCtrl-R", IDM_RELOAD
MENUITEM "Back", IDM_HISTORY_BACKWARD MENUITEM "Back", IDM_HISTORY_BACKWARD
MENUITEM "Forward", IDM_HISTORY_FORWARD MENUITEM "Forward", IDM_HISTORY_FORWARD
END END
POPUP "D&evelop" POPUP "D&evelop"
BEGIN BEGIN
MENUITEM "Show Web Inspector", IDM_WEB_INSPECTOR MENUITEM "Show Web Inspector", IDM_WEB_INSPECTOR
END END
POPUP "&Help" POPUP "&Help"
BEGIN BEGIN
MENUITEM "&About ...", IDM_ABOUT MENUITEM "&About ...", IDM_ABOUT
END END
END END
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Accelerator // Accelerator
// //
IDC_PLAYWRIGHT ACCELERATORS IDC_PLAYWRIGHT ACCELERATORS
BEGIN BEGIN
"/", IDM_ABOUT, ASCII, ALT, NOINVERT "/", IDM_ABOUT, ASCII, ALT, NOINVERT
"0", IDM_ACTUAL_SIZE, VIRTKEY, CONTROL, NOINVERT "0", IDM_ACTUAL_SIZE, VIRTKEY, CONTROL, NOINVERT
"?", IDM_ABOUT, ASCII, ALT, NOINVERT "?", IDM_ABOUT, ASCII, ALT, NOINVERT
"R", IDM_RELOAD, VIRTKEY, CONTROL, NOINVERT "R", IDM_RELOAD, VIRTKEY, CONTROL, NOINVERT
"N", IDM_NEW_WINDOW, VIRTKEY, CONTROL, NOINVERT "N", IDM_NEW_WINDOW, VIRTKEY, CONTROL, NOINVERT
VK_ADD, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT VK_ADD, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT
VK_OEM_MINUS, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT VK_OEM_MINUS, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT
VK_OEM_PLUS, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT VK_OEM_PLUS, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT
VK_SUBTRACT, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT VK_SUBTRACT, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT
END END
IDR_ACCELERATORS_PRE ACCELERATORS IDR_ACCELERATORS_PRE ACCELERATORS
BEGIN BEGIN
"W", IDM_CLOSE_WINDOW, VIRTKEY, CONTROL, NOINVERT "W", IDM_CLOSE_WINDOW, VIRTKEY, CONTROL, NOINVERT
END END
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Dialog // Dialog
// //
IDD_ABOUTBOX DIALOGEX 22, 17, 230, 41 IDD_ABOUTBOX DIALOGEX 22, 17, 230, 41
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "About" CAPTION "About"
FONT 8, "MS Shell Dlg", 0, 0, 0x0 FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN BEGIN
ICON IDI_PLAYWRIGHT,IDC_MYICON,14,9,20,20 ICON IDI_PLAYWRIGHT,IDC_MYICON,14,9,20,20
LTEXT "Playwright Version 1.1",IDC_STATIC,49,10,119,8 LTEXT "Playwright Version 1.1",IDC_STATIC,49,10,119,8
LTEXT "Copyright (C) 2015-2019",IDC_STATIC,49,20,119,8 LTEXT "Copyright (C) 2015-2019",IDC_STATIC,49,20,119,8
DEFPUSHBUTTON "OK",IDOK,186,10,30,11,WS_GROUP DEFPUSHBUTTON "OK",IDOK,186,10,30,11,WS_GROUP
END END
IDD_CACHES DIALOGEX 0, 0, 401, 456 IDD_CACHES DIALOGEX 0, 0, 401, 456
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog" CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "OK",IDOK,287,435,50,14 DEFPUSHBUTTON "OK",IDOK,287,435,50,14
PUSHBUTTON "Cancel",IDCANCEL,344,435,50,14 PUSHBUTTON "Cancel",IDCANCEL,344,435,50,14
GROUPBOX "FastMalloc",IDC_STATIC,208,14,186,67 GROUPBOX "FastMalloc",IDC_STATIC,208,14,186,67
GROUPBOX "WebCore Cache",IDC_STATIC,17,83,376,105 GROUPBOX "WebCore Cache",IDC_STATIC,17,83,376,105
GROUPBOX "JavaScript Heap",IDC_STATIC,18,193,376,168 GROUPBOX "JavaScript Heap",IDC_STATIC,18,193,376,168
GROUPBOX "Site Icon Database",IDC_STATIC,18,366,142,65 GROUPBOX "Site Icon Database",IDC_STATIC,18,366,142,65
GROUPBOX "Font and Glyph Caches",IDC_STATIC,168,366,226,66 GROUPBOX "Font and Glyph Caches",IDC_STATIC,168,366,226,66
GROUPBOX "CFURLCache",IDC_STATIC,7,14,197,67 GROUPBOX "CFURLCache",IDC_STATIC,7,14,197,67
PUSHBUTTON "Empty URLCache",IDC_EMPTY_URL_CACHE,131,63,69,14,WS_DISABLED PUSHBUTTON "Empty URLCache",IDC_EMPTY_URL_CACHE,131,63,69,14,WS_DISABLED
PUSHBUTTON "Return Free Memory",IDC_RETURN_FREE_MEMORY,308,63,76,14,WS_DISABLED PUSHBUTTON "Return Free Memory",IDC_RETURN_FREE_MEMORY,308,63,76,14,WS_DISABLED
PUSHBUTTON "Empty WebCore Cache",IDC_EMPTY_WEBCORE_CACHE,21,170,83,14,WS_DISABLED PUSHBUTTON "Empty WebCore Cache",IDC_EMPTY_WEBCORE_CACHE,21,170,83,14,WS_DISABLED
CONTROL "Disable WebCore Cache",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,119,172,93,10 CONTROL "Disable WebCore Cache",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,119,172,93,10
PUSHBUTTON "Garbage Collect JavaScript Objects",IDC_GC_JSC,253,343,135,14,WS_DISABLED PUSHBUTTON "Garbage Collect JavaScript Objects",IDC_GC_JSC,253,343,135,14,WS_DISABLED
RTEXT "Reserved VM",IDC_STATIC,212,26,67,9 RTEXT "Reserved VM",IDC_STATIC,212,26,67,9
RTEXT "0",IDC_RESERVED_VM,290,26,94,8 RTEXT "0",IDC_RESERVED_VM,290,26,94,8
RTEXT "Committed VM",IDC_STATIC,211,39,67,8 RTEXT "Committed VM",IDC_STATIC,211,39,67,8
RTEXT "0",IDC_COMMITTED_VM,290,39,94,8 RTEXT "0",IDC_COMMITTED_VM,290,39,94,8
RTEXT "Free List Bytes",IDC_STATIC,211,52,67,8 RTEXT "Free List Bytes",IDC_STATIC,211,52,67,8
RTEXT "0",IDC_FREE_LIST_BYTES,290,52,94,8 RTEXT "0",IDC_FREE_LIST_BYTES,290,52,94,8
RTEXT "Images",IDC_STATIC,37,106,24,8 RTEXT "Images",IDC_STATIC,37,106,24,8
RTEXT "CSS",IDC_STATIC,47,116,14,8 RTEXT "CSS",IDC_STATIC,47,116,14,8
RTEXT "XSL",IDC_STATIC,49,126,12,8 RTEXT "XSL",IDC_STATIC,49,126,12,8
RTEXT "JavaScript",IDC_STATIC,27,135,34,8 RTEXT "JavaScript",IDC_STATIC,27,135,34,8
RTEXT "Total",IDC_STATIC,43,146,17,8 RTEXT "Total",IDC_STATIC,43,146,17,8
LTEXT "Objects",IDC_STATIC,111,96,26,8 LTEXT "Objects",IDC_STATIC,111,96,26,8
LTEXT "Bytes",IDC_STATIC,175,96,19,8 LTEXT "Bytes",IDC_STATIC,175,96,19,8
LTEXT "Live",IDC_STATIC,232,96,14,8 LTEXT "Live",IDC_STATIC,232,96,14,8
LTEXT "Decoded",IDC_STATIC,284,96,29,8 LTEXT "Decoded",IDC_STATIC,284,96,29,8
LTEXT "Purgeable",IDC_STATIC,351,96,33,8 LTEXT "Purgeable",IDC_STATIC,351,96,33,8
RTEXT "0",IDC_IMAGES_OBJECT_COUNT,100,106,32,8 RTEXT "0",IDC_IMAGES_OBJECT_COUNT,100,106,32,8
RTEXT "0",IDC_CSS_OBJECT_COUNT,100,116,32,8 RTEXT "0",IDC_CSS_OBJECT_COUNT,100,116,32,8
RTEXT "0",IDC_XSL_OBJECT_COUNT,100,126,32,8 RTEXT "0",IDC_XSL_OBJECT_COUNT,100,126,32,8
RTEXT "0",IDC_JSC_OBJECT_COUNT,100,135,32,8 RTEXT "0",IDC_JSC_OBJECT_COUNT,100,135,32,8
RTEXT "0",IDC_TOTAL_OBJECT_COUNT,100,146,32,8 RTEXT "0",IDC_TOTAL_OBJECT_COUNT,100,146,32,8
RTEXT "0",IDC_IMAGES_BYTES,162,106,32,8 RTEXT "0",IDC_IMAGES_BYTES,162,106,32,8
RTEXT "0",IDC_CSS_BYTES,162,116,32,8 RTEXT "0",IDC_CSS_BYTES,162,116,32,8
RTEXT "0",IDC_XSL_BYTES,162,126,32,8 RTEXT "0",IDC_XSL_BYTES,162,126,32,8
RTEXT "0",IDC_JSC_BYTES,162,135,32,8 RTEXT "0",IDC_JSC_BYTES,162,135,32,8
RTEXT "0",IDC_TOTAL_BYTES,162,146,32,8 RTEXT "0",IDC_TOTAL_BYTES,162,146,32,8
RTEXT "0",IDC_IMAGES_LIVE_COUNT,221,106,32,8 RTEXT "0",IDC_IMAGES_LIVE_COUNT,221,106,32,8
RTEXT "0",IDC_CSS_LIVE_COUNT,221,116,32,8 RTEXT "0",IDC_CSS_LIVE_COUNT,221,116,32,8
RTEXT "0",IDC_XSL_LIVE_COUNT,221,126,32,8 RTEXT "0",IDC_XSL_LIVE_COUNT,221,126,32,8
RTEXT "0",IDC_JSC_LIVE_COUNT,221,135,32,8 RTEXT "0",IDC_JSC_LIVE_COUNT,221,135,32,8
RTEXT "0",IDC_TOTAL_LIVE_COUNT,221,146,32,8 RTEXT "0",IDC_TOTAL_LIVE_COUNT,221,146,32,8
RTEXT "0",IDC_IMAGES_DECODED_COUNT,284,106,32,8 RTEXT "0",IDC_IMAGES_DECODED_COUNT,284,106,32,8
RTEXT "0",IDC_CSS_DECODED_COUNT,284,116,32,8 RTEXT "0",IDC_CSS_DECODED_COUNT,284,116,32,8
RTEXT "0",IDC_XSL_DECODED_COUNT,284,126,32,8 RTEXT "0",IDC_XSL_DECODED_COUNT,284,126,32,8
RTEXT "0",IDC_JSC_DECODED_COUNT,284,135,32,8 RTEXT "0",IDC_JSC_DECODED_COUNT,284,135,32,8
RTEXT "0",IDC_TOTAL_DECODED,284,146,32,8 RTEXT "0",IDC_TOTAL_DECODED,284,146,32,8
RTEXT "0",IDC_IMAGES_PURGEABLE_COUNT,354,106,32,8 RTEXT "0",IDC_IMAGES_PURGEABLE_COUNT,354,106,32,8
RTEXT "0",IDC_CSS_PURGEABLE_COUNT,354,116,32,8 RTEXT "0",IDC_CSS_PURGEABLE_COUNT,354,116,32,8
RTEXT "0",IDC_XSL_PURGEABLE_COUNT,354,126,32,8 RTEXT "0",IDC_XSL_PURGEABLE_COUNT,354,126,32,8
RTEXT "0",IDC_JSC_PURGEABLE_COUNT,354,135,32,8 RTEXT "0",IDC_JSC_PURGEABLE_COUNT,354,135,32,8
RTEXT "0",IDC_TOTAL_PURGEABLE,354,146,32,8 RTEXT "0",IDC_TOTAL_PURGEABLE,354,146,32,8
RTEXT "Total Objects",IDC_STATIC,63,207,44,8 RTEXT "Total Objects",IDC_STATIC,63,207,44,8
RTEXT "Global Objects",IDC_STATIC,56,217,51,8 RTEXT "Global Objects",IDC_STATIC,56,217,51,8
RTEXT "Protected Objects",IDC_STATIC,48,227,59,8 RTEXT "Protected Objects",IDC_STATIC,48,227,59,8
RTEXT "0",IDC_TOTAL_JSC_HEAP_OBJECTS,127,207,56,8 RTEXT "0",IDC_TOTAL_JSC_HEAP_OBJECTS,127,207,56,8
RTEXT "0",IDC_GLOBAL_JSC_HEAP_OBJECTS,127,217,56,8 RTEXT "0",IDC_GLOBAL_JSC_HEAP_OBJECTS,127,217,56,8
RTEXT "0",IDC_PROTECTED_JSC_HEAP_OBJECTS,127,227,56,8 RTEXT "0",IDC_PROTECTED_JSC_HEAP_OBJECTS,127,227,56,8
RTEXT "Size",IDC_STATIC56,223,207,14,8 RTEXT "Size",IDC_STATIC56,223,207,14,8
RTEXT "Free",IDC_STATIC57,222,217,16,8 RTEXT "Free",IDC_STATIC57,222,217,16,8
RTEXT "0",IDC_JSC_HEAP_SIZE,270,207,56,8 RTEXT "0",IDC_JSC_HEAP_SIZE,270,207,56,8
RTEXT "0",IDC_JSC_HEAP_FREE,270,217,56,8 RTEXT "0",IDC_JSC_HEAP_FREE,270,217,56,8
PUSHBUTTON "Purge Inactive Font Data",IDC_BUTTON5,293,415,95,14,WS_DISABLED PUSHBUTTON "Purge Inactive Font Data",IDC_BUTTON5,293,415,95,14,WS_DISABLED
LTEXT "Total Font Data Objects",IDC_STATIC,208,379,78,8 LTEXT "Total Font Data Objects",IDC_STATIC,208,379,78,8
LTEXT "Inactive Font Data Objects",IDC_STATIC,198,390,88,8 LTEXT "Inactive Font Data Objects",IDC_STATIC,198,390,88,8
LTEXT "Glyph Pages",IDC_STATIC,246,402,40,8 LTEXT "Glyph Pages",IDC_STATIC,246,402,40,8
RTEXT "0",IDC_TOTAL_FONT_OBJECTS,329,379,56,8 RTEXT "0",IDC_TOTAL_FONT_OBJECTS,329,379,56,8
RTEXT "0",IDC_INACTIVE_FONT_OBJECTS,329,390,56,8 RTEXT "0",IDC_INACTIVE_FONT_OBJECTS,329,390,56,8
RTEXT "0",IDC_GLYPH_PAGES,329,402,56,8 RTEXT "0",IDC_GLYPH_PAGES,329,402,56,8
LTEXT "Page URL Mappings",IDC_STATIC,33,380,64,8 LTEXT "Page URL Mappings",IDC_STATIC,33,380,64,8
LTEXT "Retained Page URLs",IDC_STATIC,31,390,66,8 LTEXT "Retained Page URLs",IDC_STATIC,31,390,66,8
LTEXT "Site Icon Records",IDC_STATIC,40,400,57,8 LTEXT "Site Icon Records",IDC_STATIC,40,400,57,8
LTEXT "Site Icons with Data",IDC_STATIC,32,410,65,8 LTEXT "Site Icons with Data",IDC_STATIC,32,410,65,8
RTEXT "0",IDC_PAGE_URL_MAPPINGS,101,380,52,8 RTEXT "0",IDC_PAGE_URL_MAPPINGS,101,380,52,8
RTEXT "0",IDC_RETAINED_PAGE_URLS,101,390,52,8 RTEXT "0",IDC_RETAINED_PAGE_URLS,101,390,52,8
RTEXT "0",IDC_SITE_ICON_RECORDS,101,400,52,8 RTEXT "0",IDC_SITE_ICON_RECORDS,101,400,52,8
RTEXT "0",IDC_SITE_ICONS_WITH_DATA,101,410,52,8 RTEXT "0",IDC_SITE_ICONS_WITH_DATA,101,410,52,8
END END
IDD_AUTH DIALOGEX 0, 0, 231, 119 IDD_AUTH DIALOGEX 0, 0, 231, 119
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Authentication Required" CAPTION "Authentication Required"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Sign In",IDOK,116,98,50,14 DEFPUSHBUTTON "Sign In",IDOK,116,98,50,14
PUSHBUTTON "Cancel",IDCANCEL,174,98,50,14 PUSHBUTTON "Cancel",IDCANCEL,174,98,50,14
LTEXT "Realm",IDC_REALM_TEXT,67,21,157,8 LTEXT "Realm",IDC_REALM_TEXT,67,21,157,8
RTEXT "User Name:",IDC_STATIC,7,41,57,8 RTEXT "User Name:",IDC_STATIC,7,41,57,8
EDITTEXT IDC_AUTH_USER,67,39,157,14,ES_AUTOHSCROLL EDITTEXT IDC_AUTH_USER,67,39,157,14,ES_AUTOHSCROLL
RTEXT "Password:",IDC_STATIC,7,66,57,8 RTEXT "Password:",IDC_STATIC,7,66,57,8
EDITTEXT IDC_AUTH_PASSWORD,67,64,157,14,ES_PASSWORD | ES_AUTOHSCROLL EDITTEXT IDC_AUTH_PASSWORD,67,64,157,14,ES_PASSWORD | ES_AUTOHSCROLL
END END
IDD_PROXY DIALOGEX 0, 0, 310, 176 IDD_PROXY DIALOGEX 0, 0, 310, 176
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Proxy Configuration" CAPTION "Proxy Configuration"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "OK",IDOK,199,155,50,14 DEFPUSHBUTTON "OK",IDOK,199,155,50,14
PUSHBUTTON "Cancel",IDCANCEL,253,155,50,14 PUSHBUTTON "Cancel",IDCANCEL,253,155,50,14
CONTROL "Use system default proxy configuration.",IDC_PROXY_DEFAULT, CONTROL "Use system default proxy configuration.",IDC_PROXY_DEFAULT,
"Button",BS_AUTORADIOBUTTON | WS_GROUP,22,15,226,10 "Button",BS_AUTORADIOBUTTON | WS_GROUP,22,15,226,10
CONTROL "Use custom proxy configuration:",IDC_PROXY_CUSTOM, CONTROL "Use custom proxy configuration:",IDC_PROXY_CUSTOM,
"Button",BS_AUTORADIOBUTTON,22,33,226,10 "Button",BS_AUTORADIOBUTTON,22,33,226,10
CONTROL "Don't use proxy.",IDC_PROXY_DISABLE,"Button",BS_AUTORADIOBUTTON,22,117,226,10 CONTROL "Don't use proxy.",IDC_PROXY_DISABLE,"Button",BS_AUTORADIOBUTTON,22,117,226,10
EDITTEXT IDC_PROXY_URL,76,52,193,14,ES_AUTOHSCROLL EDITTEXT IDC_PROXY_URL,76,52,193,14,ES_AUTOHSCROLL
EDITTEXT IDC_PROXY_EXCLUDE,76,85,193,14,ES_AUTOHSCROLL EDITTEXT IDC_PROXY_EXCLUDE,76,85,193,14,ES_AUTOHSCROLL
LTEXT "URL:",IDC_STATIC,30,55,43,8,0,WS_EX_RIGHT LTEXT "URL:",IDC_STATIC,30,55,43,8,0,WS_EX_RIGHT
LTEXT "Excude list:",IDC_STATIC,30,88,43,8,0,WS_EX_RIGHT LTEXT "Excude list:",IDC_STATIC,30,88,43,8,0,WS_EX_RIGHT
LTEXT "Example: http://192.168.0.2:8000",IDC_STATIC,80,68,194,8 LTEXT "Example: http://192.168.0.2:8000",IDC_STATIC,80,68,194,8
LTEXT "Comma separated hostnames.",IDC_STATIC,80,101,194,8 LTEXT "Comma separated hostnames.",IDC_STATIC,80,101,194,8
END END
IDD_SERVER_TRUST DIALOGEX 0, 0, 319, 184 IDD_SERVER_TRUST DIALOGEX 0, 0, 319, 184
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Server Trust Evaluation Request" CAPTION "Server Trust Evaluation Request"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Yes",IDOK,197,163,50,14 DEFPUSHBUTTON "Yes",IDOK,197,163,50,14
PUSHBUTTON "No",IDCANCEL,262,163,50,14 PUSHBUTTON "No",IDCANCEL,262,163,50,14
LTEXT "Certificate information",IDC_STATIC,7,7,294,17 LTEXT "Certificate information",IDC_STATIC,7,7,294,17
EDITTEXT IDC_SERVER_TRUST_TEXT,7,24,305,130,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP EDITTEXT IDC_SERVER_TRUST_TEXT,7,24,305,130,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
END END
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// TEXTINCLUDE // TEXTINCLUDE
// //
1 TEXTINCLUDE 1 TEXTINCLUDE
BEGIN BEGIN
"PlaywrightLibResource.h\0" "PlaywrightLibResource.h\0"
END END
2 TEXTINCLUDE 2 TEXTINCLUDE
BEGIN BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n" "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n" "#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0" "\0"
END END
3 TEXTINCLUDE 3 TEXTINCLUDE
BEGIN BEGIN
"\r\n" "\r\n"
"\0" "\0"
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// DESIGNINFO // DESIGNINFO
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO GUIDELINES DESIGNINFO
BEGIN BEGIN
IDD_ABOUTBOX, DIALOG IDD_ABOUTBOX, DIALOG
BEGIN BEGIN
END END
IDD_CACHES, DIALOG IDD_CACHES, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 394 RIGHTMARGIN, 394
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 449 BOTTOMMARGIN, 449
END END
IDD_AUTH, DIALOG IDD_AUTH, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 224 RIGHTMARGIN, 224
VERTGUIDE, 64 VERTGUIDE, 64
VERTGUIDE, 67 VERTGUIDE, 67
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 92 BOTTOMMARGIN, 92
HORZGUIDE, 25 HORZGUIDE, 25
HORZGUIDE, 50 HORZGUIDE, 50
END END
IDD_PROXY, DIALOG IDD_PROXY, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 303 RIGHTMARGIN, 303
VERTGUIDE, 22 VERTGUIDE, 22
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 169 BOTTOMMARGIN, 169
END END
IDD_SERVER_TRUST, DIALOG IDD_SERVER_TRUST, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 312 RIGHTMARGIN, 312
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 177 BOTTOMMARGIN, 177
END END
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Bitmap // Bitmap
// //
IDB_TOOLBAR BITMAP "toolbar.bmp" IDB_TOOLBAR BITMAP "toolbar.bmp"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// String Table // String Table
// //
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_APP_TITLE "Playwright" IDS_APP_TITLE "Playwright"
IDC_PLAYWRIGHT "Playwright" IDC_PLAYWRIGHT "Playwright"
END END
#endif // English (United States) resources #endif // English (United States) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED #ifndef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Generated from the TEXTINCLUDE 3 resource. // Generated from the TEXTINCLUDE 3 resource.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED #endif // not APSTUDIO_INVOKED

Просмотреть файл

@ -34,6 +34,7 @@
#include <WebKit/WKCredential.h> #include <WebKit/WKCredential.h>
#include <WebKit/WKFramePolicyListener.h> #include <WebKit/WKFramePolicyListener.h>
#include <WebKit/WKInspector.h> #include <WebKit/WKInspector.h>
#include <WebKit/WKPagePrivate.h>
#include <WebKit/WKProtectionSpace.h> #include <WebKit/WKProtectionSpace.h>
#include <WebKit/WKProtectionSpaceCurl.h> #include <WebKit/WKProtectionSpaceCurl.h>
#include <WebKit/WKWebsiteDataStoreRef.h> #include <WebKit/WKWebsiteDataStoreRef.h>
@ -102,6 +103,8 @@ WebKitBrowserWindow::WebKitBrowserWindow(BrowserWindowClient& client, HWND mainW
policyClient.decidePolicyForResponse_deprecatedForUseWithV0 = decidePolicyForResponse; policyClient.decidePolicyForResponse_deprecatedForUseWithV0 = decidePolicyForResponse;
policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction; policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction;
WKPageSetPagePolicyClient(page, &policyClient.base); WKPageSetPagePolicyClient(page, &policyClient.base);
WKPageSetControlledByAutomation(page, true);
resetZoom(); resetZoom();
} }

Разница между файлами не показана из-за своего большого размера Загрузить разницу