Skip to content

Commit

Permalink
browser(firefox): misc fixes (#983)
Browse files Browse the repository at this point in the history
- crash support;
- keydown supports text by committing composition;
- cross-page frame handling;
- security check for node adoption.
  • Loading branch information
dgozman authored Feb 13, 2020
1 parent d367a2e commit c2ab1e3
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 31 deletions.
2 changes: 1 addition & 1 deletion browser_patches/firefox/BUILD_NUMBER
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1028
1029
139 changes: 109 additions & 30 deletions browser_patches/firefox/patches/bootstrap.diff
Original file line number Diff line number Diff line change
Expand Up @@ -1450,10 +1450,10 @@ index 0000000000000000000000000000000000000000..66f61d432f9ad2f50931b780ec5ea0e3
+this.NetworkObserver = NetworkObserver;
diff --git a/testing/juggler/TargetRegistry.js b/testing/juggler/TargetRegistry.js
new file mode 100644
index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f86483177a4e0
index 0000000000000000000000000000000000000000..6a128959f9128a87cd3d46a5d906028ff500f9e0
--- /dev/null
+++ b/testing/juggler/TargetRegistry.js
@@ -0,0 +1,214 @@
@@ -0,0 +1,232 @@
+const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
+const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Expand Down Expand Up @@ -1506,6 +1506,7 @@ index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f8648
+ target.dispose();
+ this.emit(TargetRegistry.Events.TargetDestroyed, target.info());
+ });
+ Services.obs.addObserver(this, 'oop-frameloader-crashed');
+ }
+
+ async newPage({browserContextId}) {
Expand Down Expand Up @@ -1563,6 +1564,22 @@ index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f8648
+ this.emit(TargetRegistry.Events.TargetCreated, target.info());
+ return target;
+ }
+
+ observe(subject, topic, data) {
+ if (topic === 'oop-frameloader-crashed') {
+ const browser = subject.ownerElement;
+ if (!browser)
+ return;
+ const tab = this._mainWindow.gBrowser.getTabForBrowser(browser);
+ if (!tab)
+ return;
+ const target = this._tabToTarget.get(tab);
+ if (!target)
+ return;
+ this.emit(TargetRegistry.Events.TargetCrashed, target.id());
+ return;
+ }
+ }
+}
+
+class PageTarget {
Expand Down Expand Up @@ -1663,6 +1680,7 @@ index 0000000000000000000000000000000000000000..2b1a1bd0f931d82824a86ecbb46f8648
+ TargetCreated: Symbol('TargetRegistry.Events.TargetCreated'),
+ TargetDestroyed: Symbol('TargetRegistry.Events.TargetDestroyed'),
+ TargetChanged: Symbol('TargetRegistry.Events.TargetChanged'),
+ TargetCrashed: Symbol('TargetRegistry.Events.TargetCrashed'),
+ PageTargetReady: Symbol('TargetRegistry.Events.PageTargetReady'),
+};
+
Expand Down Expand Up @@ -1890,10 +1908,10 @@ index 0000000000000000000000000000000000000000..3891da101e6906ae2a3888e256aefd03
+
diff --git a/testing/juggler/content/FrameTree.js b/testing/juggler/content/FrameTree.js
new file mode 100644
index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574bee5915ea
index 0000000000000000000000000000000000000000..6735dd39c6cfb6f945d5d094cfb7902f4eb9cefd
--- /dev/null
+++ b/testing/juggler/content/FrameTree.js
@@ -0,0 +1,252 @@
@@ -0,0 +1,266 @@
+"use strict";
+const Ci = Components.interfaces;
+const Cr = Components.results;
Expand All @@ -1907,6 +1925,12 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
+class FrameTree {
+ constructor(rootDocShell, waitForInitialNavigation) {
+ EventEmitter.decorate(this);
+
+ this._browsingContextGroup = rootDocShell.browsingContext.group;
+ if (!this._browsingContextGroup.__jugglerFrameTrees)
+ this._browsingContextGroup.__jugglerFrameTrees = new Set();
+ this._browsingContextGroup.__jugglerFrameTrees.add(this);
+
+ this._docShellToFrame = new Map();
+ this._frameIdToFrame = new Map();
+ this._pageReady = !waitForInitialNavigation;
Expand All @@ -1928,6 +1952,13 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
+ ];
+ }
+
+ allFramesInBrowsingContextGroup(group) {
+ const frames = [];
+ for (const frameTree of (group.__jugglerFrameTrees || []))
+ frames.push(...frameTree.frames());
+ return frames;
+ }
+
+ isPageReady() {
+ return this._pageReady;
+ }
Expand Down Expand Up @@ -1957,6 +1988,7 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
+ }
+
+ dispose() {
+ this._browsingContextGroup.__jugglerFrameTrees.delete(this);
+ helper.removeListeners(this._eventListeners);
+ }
+
Expand Down Expand Up @@ -2148,7 +2180,7 @@ index 0000000000000000000000000000000000000000..dcebb7bbf6d0c9bb7a350443dfa2574b
+
diff --git a/testing/juggler/content/NetworkMonitor.js b/testing/juggler/content/NetworkMonitor.js
new file mode 100644
index 0000000000000000000000000000000000000000..2508cce41565023b7fee9c7b85afe8ecebd26e7d
index 0000000000000000000000000000000000000000..be70ea364f9534bb3b344f64970366c32e8c11be
--- /dev/null
+++ b/testing/juggler/content/NetworkMonitor.js
@@ -0,0 +1,62 @@
Expand Down Expand Up @@ -2179,7 +2211,7 @@ index 0000000000000000000000000000000000000000..2508cce41565023b7fee9c7b85afe8ec
+ if (!loadContext)
+ return;
+ const window = loadContext.associatedWindow;
+ const frame = this._frameTree.frameForDocShell(window.docShell)
+ const frame = this._frameTree.frameForDocShell(window.docShell);
+ if (!frame)
+ return;
+ this._requestDetails.set(httpChannel.channelId, {
Expand Down Expand Up @@ -2216,10 +2248,10 @@ index 0000000000000000000000000000000000000000..2508cce41565023b7fee9c7b85afe8ec
+
diff --git a/testing/juggler/content/PageAgent.js b/testing/juggler/content/PageAgent.js
new file mode 100644
index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631f0bd1780
index 0000000000000000000000000000000000000000..994b683a78c43f8fb072cc185f2e5f8d2badec3c
--- /dev/null
+++ b/testing/juggler/content/PageAgent.js
@@ -0,0 +1,875 @@
@@ -0,0 +1,912 @@
+"use strict";
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const Ci = Components.interfaces;
Expand Down Expand Up @@ -2734,6 +2766,11 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
+ throw new Error('Failed to find frame with id = ' + frameId);
+ const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
+ const context = this._runtime.findExecutionContext(executionContextId);
+ const fromPrincipal = unsafeObject.nodePrincipal;
+ const toFrame = this._frameTree.frame(context.auxData().frameId);
+ const toPrincipal = toFrame.domWindow().document.nodePrincipal;
+ if (!toPrincipal.subsumes(fromPrincipal))
+ return { remoteObject: null };
+ return { remoteObject: context.rawValueToRemoteObject(unsafeObject) };
+ }
+
Expand Down Expand Up @@ -2771,9 +2808,20 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
+ if (!frame)
+ throw new Error('Failed to find frame with id = ' + frameId);
+ const unsafeObject = this._frameData.get(frame).unsafeObject(objectId);
+ const browsingContextGroup = frame.docShell().browsingContext.group;
+ const frames = this._frameTree.allFramesInBrowsingContextGroup(browsingContextGroup);
+ let contentFrame;
+ let ownerFrame;
+ for (const frame of frames) {
+ if (unsafeObject.contentWindow && frame.docShell() === unsafeObject.contentWindow.docShell)
+ contentFrame = frame;
+ const document = frame.domWindow().document;
+ if (unsafeObject === document || unsafeObject.ownerDocument === document)
+ ownerFrame = frame;
+ }
+ return {
+ contentFrameId: unsafeObject.contentWindow ? this._frameTree.frameForDocShell(unsafeObject.contentWindow.docShell).id() : undefined,
+ ownerFrameId: this._findFrameForNode(unsafeObject)._frame.id(),
+ contentFrameId: contentFrame ? contentFrame.id() : undefined,
+ ownerFrameId: ownerFrame ? ownerFrame.id() : undefined,
+ };
+ }
+
Expand Down Expand Up @@ -2867,7 +2915,7 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
+ return {data};
+ }
+
+ async dispatchKeyEvent({type, keyCode, code, key, repeat, location}) {
+ async dispatchKeyEvent({type, keyCode, code, key, repeat, location, text}) {
+ const frame = this._frameTree.mainFrame();
+ const tip = frame.textInputProcessor();
+ if (key === 'Meta' && Services.appinfo.OS !== 'Darwin')
Expand All @@ -2881,13 +2929,21 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
+ repeat,
+ keyCode
+ });
+ const flags = 0;
+ if (type === 'keydown')
+ tip.keydown(keyEvent, flags);
+ else if (type === 'keyup')
+ if (type === 'keydown') {
+ if (text && text !== key) {
+ tip.commitCompositionWith(text, keyEvent);
+ } else {
+ const flags = 0;
+ tip.keydown(keyEvent, flags);
+ }
+ } else if (type === 'keyup') {
+ if (text)
+ throw new Error(`keyup does not support text option`);
+ const flags = 0;
+ tip.keyup(keyEvent, flags);
+ else
+ } else {
+ throw new Error(`Unknown type ${type}`);
+ }
+ }
+
+ async dispatchTouchEvent({type, touchPoints, modifiers}) {
Expand Down Expand Up @@ -2943,6 +2999,19 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
+ frame.textInputProcessor().commitCompositionWith(text);
+ }
+
+ async crash() {
+ dump(`Crashing intentionally\n`);
+ // This is to intentionally crash the frame.
+ // We crash by using js-ctypes and dereferencing
+ // a bad pointer. The crash should happen immediately
+ // upon loading this frame script.
+ const { ctypes } = ChromeUtils.import('resource://gre/modules/ctypes.jsm');
+ ChromeUtils.privateNoteIntentionalCrash();
+ const zero = new ctypes.intptr_t(8);
+ const badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
+ badptr.contents;
+ }
+
+ async getFullAXTree({objectId}) {
+ let unsafeObject = null;
+ if (objectId) {
Expand Down Expand Up @@ -3097,10 +3166,10 @@ index 0000000000000000000000000000000000000000..e505911e81ef014f19a3a732f3c5f631
+
diff --git a/testing/juggler/content/RuntimeAgent.js b/testing/juggler/content/RuntimeAgent.js
new file mode 100644
index 0000000000000000000000000000000000000000..5765d5c3b1de7b9383a80435b37b034d6951d981
index 0000000000000000000000000000000000000000..c6568d0e98cb3405877f711a3242ab31b55ce7c1
--- /dev/null
+++ b/testing/juggler/content/RuntimeAgent.js
@@ -0,0 +1,545 @@
@@ -0,0 +1,549 @@
+"use strict";
+// Note: this file should be loadabale with eval() into worker environment.
+// Avoid Components.*, ChromeUtils and global const variables.
Expand Down Expand Up @@ -3445,6 +3514,10 @@ index 0000000000000000000000000000000000000000..5765d5c3b1de7b9383a80435b37b034d
+ return this._id;
+ }
+
+ auxData() {
+ return this._auxData;
+ }
+
+ async evaluateScript(script, exceptionDetails = {}) {
+ const userInputHelper = this._domWindow ? this._domWindow.windowUtils.setHandlingUserInput(true) : null;
+ let {success, obj} = this._getResult(this._global.executeInGlobal(script), exceptionDetails);
Expand Down Expand Up @@ -4566,7 +4639,7 @@ index 0000000000000000000000000000000000000000..5d776ab6f28ccff44ef4663e8618ad9c
+this.NetworkHandler = NetworkHandler;
diff --git a/testing/juggler/protocol/PageHandler.js b/testing/juggler/protocol/PageHandler.js
new file mode 100644
index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09c223e59f
index 0000000000000000000000000000000000000000..8333a58253745298fa88f7ce17909699be43b3d4
--- /dev/null
+++ b/testing/juggler/protocol/PageHandler.js
@@ -0,0 +1,266 @@
Expand Down Expand Up @@ -4615,6 +4688,10 @@ index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09
+ this._updateModalDialogs();
+ }),
+ helper.addEventListener(this._browser, 'DOMModalDialogClosed', event => this._updateModalDialogs()),
+ helper.on(TargetRegistry.instance(), TargetRegistry.Events.TargetCrashed, targetId => {
+ if (targetId === this._chromeSession.targetId())
+ this._chromeSession.emitEvent('Page.crashed', {});
+ }),
+ ];
+ }
+
Expand Down Expand Up @@ -4660,18 +4737,10 @@ index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09
+ return await this._contentSession.send('Page.setFileInputFiles', options);
+ }
+
+ async setBypassCSP(options) {
+ return await this._contentSession.send('Page.setBypassCSP', options);
+ }
+
+ async setEmulatedMedia(options) {
+ return await this._contentSession.send('Page.setEmulatedMedia', options);
+ }
+
+ async setJavascriptEnabled(options) {
+ return await this._contentSession.send('Page.setJavascriptEnabled', options);
+ }
+
+ async setCacheDisabled(options) {
+ return await this._contentSession.send('Page.setCacheDisabled', options);
+ }
Expand Down Expand Up @@ -4756,6 +4825,10 @@ index 0000000000000000000000000000000000000000..efb0fc1f3f7af37e101976cf8a682e09
+ return await this._contentSession.send('Page.insertText', options);
+ }
+
+ async crash(options) {
+ return await this._contentSession.send('Page.crash', options);
+ }
+
+ async handleDialog({dialogId, accept, promptText}) {
+ const dialog = this._dialogs.get(dialogId);
+ if (!dialog)
Expand Down Expand Up @@ -4987,10 +5060,10 @@ index 0000000000000000000000000000000000000000..78b6601b91d0b7fcda61114e6846aa07
+this.EXPORTED_SYMBOLS = ['t', 'checkScheme'];
diff --git a/testing/juggler/protocol/Protocol.js b/testing/juggler/protocol/Protocol.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690fa7941f25
index 0000000000000000000000000000000000000000..6751bfaa84655952f4a51e3dd4353eb84f517fcb
--- /dev/null
+++ b/testing/juggler/protocol/Protocol.js
@@ -0,0 +1,746 @@
@@ -0,0 +1,752 @@
+const {t, checkScheme} = ChromeUtils.import('chrome://juggler/content/protocol/PrimitiveTypes.js');
+
+// Protocol-specific types.
Expand Down Expand Up @@ -5446,6 +5519,8 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
+ events: {
+ 'ready': {
+ },
+ 'crashed': {
+ },
+ 'eventFired': {
+ frameId: t.String,
+ name: t.Enum(['load', 'DOMContentLoaded']),
Expand Down Expand Up @@ -5635,7 +5710,7 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
+ executionContextId: t.String,
+ },
+ returns: {
+ remoteObject: runtimeTypes.RemoteObject,
+ remoteObject: t.Nullable(runtimeTypes.RemoteObject),
+ },
+ },
+ 'screenshot': {
Expand Down Expand Up @@ -5665,6 +5740,7 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
+ location: t.Number,
+ code: t.String,
+ repeat: t.Boolean,
+ text: t.Optional(t.String),
+ }
+ },
+ 'dispatchTouchEvent': {
Expand Down Expand Up @@ -5693,6 +5769,9 @@ index 0000000000000000000000000000000000000000..a0a96a87ff4a422deccae1045962690f
+ text: t.String,
+ }
+ },
+ 'crash': {
+ params: {}
+ },
+ 'handleDialog': {
+ params: {
+ dialogId: t.String,
Expand Down

0 comments on commit c2ab1e3

Please sign in to comment.