Backed out 4 changesets (bug 1519335) for causing a spike in bug 1641788, per whimboo's request CLOSED TREE

Backed out changeset 80a0c09b0211 (bug 1519335)
Backed out changeset 315a7ffd643b (bug 1519335)
Backed out changeset 7c82cbd6f034 (bug 1519335)
Backed out changeset f84fa4157d90 (bug 1519335)
This commit is contained in:
Bogdan Tara 2020-06-03 18:34:46 +03:00
parent 49600f0317
commit 6b3e9fd483
6 changed files with 85 additions and 129 deletions

View File

@ -287,25 +287,6 @@ assert.callable = function(obj, msg = "") {
return assert.that(o => typeof o == "function", msg)(obj);
};
/**
* Asserts that <var>obj</var> is an unsigned short number.
*
* @param {?} obj
* Value to test.
* @param {string=} msg
* Custom error message.
*
* @return {number}
* <var>obj</var> is returned unaltered.
*
* @throws {InvalidArgumentError}
* If <var>obj</var> is not an unsigned short.
*/
assert.unsignedShort = function(obj, msg = "") {
msg = msg || pprint`Expected ${obj} to be >= 0 and < 65536`;
return assert.that(n => n >= 0 && n < 65536, msg)(obj);
};
/**
* Asserts that <var>obj</var> is an integer.
*

View File

@ -567,17 +567,17 @@ browser.Context = class {
};
/**
* The window storage is used to save browsing context ids mapped to weak
* The window storage is used to save outer window IDs mapped to weak
* references of Window objects.
*
* Usage:
*
* let wins = new browser.Windows();
* wins.set(browser.browsingContext.id, window);
* wins.set(browser.outerWindowID, window);
*
* ...
*
* let win = wins.get(browser.browsingContext.id);
* let win = wins.get(browser.outerWindowID);
*
*/
browser.Windows = class extends Map {
@ -585,7 +585,7 @@ browser.Windows = class extends Map {
* Save a weak reference to the Window object.
*
* @param {string} id
* Browsing context id.
* Outer window ID.
* @param {Window} win
* Window object to save.
*
@ -602,7 +602,7 @@ browser.Windows = class extends Map {
* Get the window object stored by provided |id|.
*
* @param {string} id
* Browsing context id.
* Outer window ID.
*
* @return {Window}
* Saved window object.

View File

@ -288,7 +288,7 @@ Object.defineProperty(GeckoDriver.prototype, "chromeWindowHandles", {
let hs = [];
for (let win of this.windows) {
hs.push(getWindowId(win));
hs.push(getOuterWindowId(win));
}
return hs;
@ -474,16 +474,16 @@ GeckoDriver.prototype.addFrameCloseListener = function(action) {
* @return {string}
* Returns the unique server-assigned ID of the window.
*/
GeckoDriver.prototype.addBrowser = function(win) {
let context = new browser.Context(win, this);
let winId = getWindowId(win);
GeckoDriver.prototype.addBrowser = function(window) {
let bc = new browser.Context(window, this);
let winId = getOuterWindowId(window);
this.browsers[winId] = context;
this.browsers[winId] = bc;
this.curBrowser = this.browsers[winId];
if (!this.wins.has(winId)) {
// add this to seenItems so we can guarantee
// the user will get winId as this window's id
this.wins.set(winId, win);
this.wins.set(winId, window);
}
};
@ -579,6 +579,8 @@ GeckoDriver.prototype.getVisibleText = function(el, lines) {
* their type they are either accepted or ignored.
*/
GeckoDriver.prototype.registerBrowser = function(id, be) {
let listenerWindow = Services.wm.getOuterWindowWithId(id);
// We want to ignore frames that are XUL browsers that aren't in the "main"
// tabbrowser, but accept things on Fennec (which doesn't have a
// xul:tabbrowser), and accept HTML iframes (because tests depend on it),
@ -594,9 +596,7 @@ GeckoDriver.prototype.registerBrowser = function(id, be) {
this.curBrowser.register(id, be);
}
const context = BrowsingContext.get(id);
this.wins.set(id, context.currentWindowGlobal);
this.wins.set(id, listenerWindow);
return id;
};
@ -605,8 +605,8 @@ GeckoDriver.prototype.registerPromise = function() {
return new Promise(resolve => {
let cb = ({ json, target }) => {
let { frameId } = json;
this.registerBrowser(frameId, target);
let { outerWindowID } = json;
this.registerBrowser(outerWindowID, target);
if (this.curBrowser.frameRegsPending > 0) {
this.curBrowser.frameRegsPending--;
@ -617,7 +617,7 @@ GeckoDriver.prototype.registerPromise = function() {
resolve();
}
return { frameId };
return { outerWindowID };
};
this.mm.addMessageListener(li, cb);
});
@ -628,7 +628,7 @@ GeckoDriver.prototype.listeningPromise = function() {
return new Promise(resolve => {
let cb = msg => {
if (msg.json.frameId === this.curBrowser.curFrameId) {
if (msg.json.outerWindowID === this.curBrowser.curFrameId) {
this.mm.removeMessageListener(li, cb);
resolve();
}
@ -1390,7 +1390,7 @@ GeckoDriver.prototype.getIdForBrowser = function(browser) {
return this._browserIds.get(permKey);
}
let winId = browser.browsingContext.id;
let winId = browser.outerWindowID;
if (winId) {
this._browserIds.set(permKey, winId);
return winId;
@ -1618,13 +1618,13 @@ GeckoDriver.prototype.switchToWindow = async function(cmd) {
* associated metadata.
*/
GeckoDriver.prototype.findWindow = function(winIterable, filter) {
for (const win of winIterable) {
const bc = win.docShell.browsingContext;
const tabBrowser = browser.getTabBrowser(win);
for (let win of winIterable) {
let outerId = getOuterWindowId(win);
let tabBrowser = browser.getTabBrowser(win);
// In case the wanted window is a chrome window, we are done.
if (filter(win, bc.id)) {
return { win, id: bc.id, hasTabBrowser: !!tabBrowser };
if (filter(win, outerId)) {
return { win, outerId, hasTabBrowser: !!tabBrowser };
// Otherwise check if the chrome window has a tab browser, and that it
// contains a tab with the wanted window handle.
@ -1636,7 +1636,7 @@ GeckoDriver.prototype.findWindow = function(winIterable, filter) {
if (filter(win, contentWindowId)) {
return {
win,
id: bc.id,
outerId,
hasTabBrowser: true,
tabIndex: i,
};
@ -1665,7 +1665,7 @@ GeckoDriver.prototype.setWindowHandle = async function(
winProperties,
focus = true
) {
if (!(winProperties.id in this.browsers)) {
if (!(winProperties.outerId in this.browsers)) {
// Initialise Marionette if the current chrome window has not been seen
// before. Also register the initial tab, if one exists.
let registerBrowsers, browserListening;
@ -1683,7 +1683,7 @@ GeckoDriver.prototype.setWindowHandle = async function(
}
} else {
// Otherwise switch to the known chrome window
this.curBrowser = this.browsers[winProperties.id];
this.curBrowser = this.browsers[winProperties.outerId];
this.mainFrame = this.curBrowser.window;
this.curFrame = null;
@ -1758,10 +1758,6 @@ GeckoDriver.prototype.switchToFrame = async function(cmd) {
let { id, focus } = cmd.parameters;
if (typeof id == "number") {
assert.unsignedShort(id, `Expected id to be unsigned short, got ${id}`);
}
// TODO(ato): element can be either string (deprecated) or a web
// element JSON Object. Can be removed with Firefox 60.
let byFrame;
@ -3572,12 +3568,12 @@ GeckoDriver.prototype.receiveMessage = function(message) {
break;
case "Marionette:Register":
let { frameId } = message.json;
this.registerBrowser(frameId, message.target);
return { frameId };
let { outerWindowID } = message.json;
this.registerBrowser(outerWindowID, message.target);
return { outerWindowID };
case "Marionette:ListenersAttached":
if (message.json.frameId === this.curBrowser.curFrameId) {
if (message.json.outerWindowID === this.curBrowser.curFrameId) {
this.curBrowser.flushPendingCommands();
}
break;
@ -3899,8 +3895,8 @@ GeckoDriver.prototype.commands = {
"WebDriver:TakeScreenshot": GeckoDriver.prototype.takeScreenshot,
};
function getWindowId(win) {
return win.docShell.browsingContext.id;
function getOuterWindowId(win) {
return win.windowUtils.outerWindowID;
}
async function exitFullscreen(win) {

View File

@ -92,7 +92,7 @@ class WindowManagerMixin(object):
return self.marionette.execute_script("""
Components.utils.import("resource://gre/modules/Services.jsm");
const win = BrowsingContext.get(Number(arguments[0])).window;
let win = Services.wm.getOuterWindowWithId(Number(arguments[0]));
return win.document.readyState == "complete";
""", script_args=[handle])
@ -174,7 +174,7 @@ class WindowManagerMixin(object):
await focused;
}
resolve(win.docShell.browsingContext.id);
resolve(win.windowUtils.outerWindowID);
})();
""", script_args=(url, focus))

View File

@ -6,7 +6,6 @@ from __future__ import absolute_import
from marionette_driver.by import By
from marionette_driver.errors import (
InvalidArgumentException,
JavascriptException,
NoSuchFrameException,
)
@ -123,13 +122,11 @@ class TestSwitchFrame(MarionetteTestCase):
def test_switch_to_frame_with_out_of_bounds_index(self):
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
count = self.marionette.execute_script("return window.frames.length;")
for index in [count, 65535]:
self.assertRaises(NoSuchFrameException, self.marionette.switch_to_frame, index)
self.assertRaises(NoSuchFrameException, self.marionette.switch_to_frame, count)
def test_switch_to_frame_with_invalid_index(self):
def test_switch_to_frame_with_negative_index(self):
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
for index in [-1, 65536]:
self.assertRaises(InvalidArgumentException, self.marionette.switch_to_frame, index)
self.assertRaises(NoSuchFrameException, self.marionette.switch_to_frame, -1)
def test_switch_to_parent_frame(self):
frame_html = self.marionette.absolute_url("frameset.html")

View File

@ -58,26 +58,13 @@ const { navigate } = ChromeUtils.import(
);
const { proxy } = ChromeUtils.import("chrome://marionette/content/proxy.js");
XPCOMUtils.defineLazyGetter(this, "logger", () => Log.getWithPrefix(contentId));
XPCOMUtils.defineLazyGetter(this, "logger", () =>
Log.getWithPrefix(outerWindowID)
);
XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
const contentId = content.docShell.browsingContext.id;
const curContainer = {
_frame: null,
shadowRoot: null,
get frame() {
return this._frame;
},
set frame(frame) {
this._frame = frame;
this.id = this._frame.docShell.browsingContext.id;
this.shadowRoot = null;
},
};
let { outerWindowID } = winUtil;
let curContainer = { frame: content, shadowRoot: null };
// Listen for click event to indicate one click has happened, so actions
// code can send dblclick event
@ -386,16 +373,17 @@ const loadListener = {
},
observe(subject, topic) {
logger.trace(`Received observer notification ${topic}`);
const win = curContainer.frame;
const winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
const curWinID = win.windowUtils.outerWindowID;
const winId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
const bc = BrowsingContext.get(curContainer.id);
logger.trace(`Received observer notification ${topic}`);
switch (topic) {
// In the case when the currently selected frame is closed,
// there will be no further load events. Stop listening immediately.
case "outer-window-destroyed":
if (bc.window.windowUtils.outerWindowID == winId) {
if (curWinID === winID) {
this.stop();
sendOk(this.commandID);
}
@ -493,27 +481,25 @@ const loadListener = {
function registerSelf() {
logger.trace("Frame script loaded");
curContainer.frame = content;
sandboxes.clear();
curContainer = {
frame: content,
shadowRoot: null,
};
legacyactions.mouseEventsOnly = false;
action.inputStateMap = new Map();
action.inputsToCancel = [];
let reply = sendSyncMessage("Marionette:Register", {
frameId: contentId,
});
let reply = sendSyncMessage("Marionette:Register", { outerWindowID });
if (reply.length == 0) {
logger.error("No reply from Marionette:Register");
return;
}
if (reply[0].frameId === contentId) {
if (reply[0].outerWindowID === outerWindowID) {
logger.trace("Frame script registered");
startListeners();
sendAsyncMessage("Marionette:ListenersAttached", {
frameId: contentId,
});
sendAsyncMessage("Marionette:ListenersAttached", { outerWindowID });
}
}
@ -680,11 +666,9 @@ function deregister() {
function deleteSession() {
seenEls.clear();
// reset container frame to the top-most frame
curContainer.frame = content;
curContainer = { frame: content, shadowRoot: null };
curContainer.frame.focus();
legacyactions.touchIds = {};
if (action.inputStateMap !== undefined) {
action.inputStateMap.clear();
@ -765,7 +749,8 @@ function emitTouchEvent(type, touch) {
);
const win = curContainer.frame;
if (win.docShell.asyncPanZoomEnabled && legacyactions.scrolling) {
let docShell = win.docShell;
if (docShell.asyncPanZoomEnabled && legacyactions.scrolling) {
let ev = {
index: 0,
type,
@ -1530,9 +1515,7 @@ function switchToParentFrame(msg) {
*/
function switchToFrame(msg) {
let commandID = msg.json.commandID;
let foundFrame;
let frameWebEl;
let foundFrame = null;
// check if curContainer.frame reference is dead
let frames = [];
@ -1552,7 +1535,6 @@ function switchToFrame(msg) {
sendSyncMessage("Marionette:switchedToFrame", { frameValue: null });
curContainer.frame = content;
if (msg.json.focus) {
curContainer.frame.focus();
}
@ -1588,12 +1570,13 @@ function switchToFrame(msg) {
let wrappedItem = new XPCNativeWrapper(frameEl);
let wrappedWanted = new XPCNativeWrapper(wantedFrame);
if (wrappedItem == wrappedWanted) {
foundFrame = frameEl;
curContainer.frame = frameEl;
foundFrame = i;
}
}
}
if (!foundFrame) {
if (foundFrame === null) {
// Either the frame has been removed or we have a OOP frame
// so lets just get all the iframes and do a quick loop before
// throwing in the towel
@ -1604,47 +1587,48 @@ function switchToFrame(msg) {
let wrappedEl = new XPCNativeWrapper(frameEl);
let wrappedWanted = new XPCNativeWrapper(wantedFrame);
if (wrappedEl == wrappedWanted) {
foundFrame = iframes[i];
curContainer.frame = iframes[i];
foundFrame = i;
}
}
}
}
if (!foundFrame) {
if (foundFrame === null) {
if (typeof msg.json.id === "number") {
try {
if (msg.json.id >= 0 && msg.json.id < frames.length) {
foundFrame = frames[msg.json.id].frameElement;
if (foundFrame !== null) {
frameWebEl = seenEls.add(foundFrame.wrappedJSObject);
} else {
// If foundFrame is null at this point then we have the top
// level browsing context so should treat it accordingly.
sendSyncMessage("Marionette:switchedToFrame", { frameValue: null });
curContainer.frame = content;
foundFrame = frames[msg.json.id].frameElement;
if (foundFrame !== null) {
curContainer.frame = foundFrame;
foundFrame = seenEls.add(curContainer.frame);
} else {
// If foundFrame is null at this point then we have the top
// level browsing context so should treat it accordingly.
sendSyncMessage("Marionette:switchedToFrame", { frameValue: null });
curContainer.frame = content;
if (msg.json.focus) {
curContainer.frame.focus();
}
sendOk(commandID);
return;
if (msg.json.focus) {
curContainer.frame.focus();
}
sendOk(commandID);
return;
}
} catch (e) {
// Since window.frames does not return OOP frames it will throw
// and we land up here. Let's not give up and check if there are
// iframes and switch to the indexed frame there
let doc = foundFrame.document;
let doc = curContainer.frame.document;
let iframes = doc.getElementsByTagName("iframe");
if (msg.json.id >= 0 && msg.json.id < iframes.length) {
foundFrame = iframes[msg.json.id];
curContainer.frame = iframes[msg.json.id];
foundFrame = msg.json.id;
}
}
}
}
if (!foundFrame) {
if (foundFrame === null) {
let failedFrame = msg.json.id || msg.json.element;
let err = new NoSuchFrameError(`Unable to locate frame: ${failedFrame}`);
sendError(err, commandID);
@ -1653,14 +1637,12 @@ function switchToFrame(msg) {
// send a synchronous message to let the server update the currently active
// frame element (for getActiveFrame)
if (!frameWebEl) {
frameWebEl = seenEls.add(foundFrame.wrappedJSObject);
}
let frameWebEl = seenEls.add(curContainer.frame.wrappedJSObject);
sendSyncMessage("Marionette:switchedToFrame", {
frameValue: frameWebEl.uuid,
});
curContainer.frame = foundFrame.contentWindow;
curContainer.frame = curContainer.frame.contentWindow;
if (msg.json.focus) {
curContainer.frame.focus();
}