Bug 1430109 - Combine assert.window and assert.contentBrowser. r=maja_zf
authorAndreas Tolfsen <ato@sny.no>
Fri, 12 Jan 2018 14:25:30 +0000
changeset 453591 b67c5b1e033bdea10e4cc242099ffb986fd09357
parent 453590 b8c8fae652739ac35c35a8e44b76a0c34e70b4fa
child 453592 78776e9bdba1f3427823d364f49adf4065ea7b79
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmaja_zf
bugs1430109
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1430109 - Combine assert.window and assert.contentBrowser. r=maja_zf The forthcoming window tracking refactoring introduces the new abstractions ContentContext and ChromeContext that to a large extent share the same interface. They make it possible to interact with both types of browsing context in a uniform manner. Marionette currently has a lot of convoluted if-conditions to paper over the differences between ChromeWindow, <xul:browser>, and browser.Context. Examples of this includes the assert.window and assert.contentBrowser assertions: they essentially perform the same job, but does not share the same API because the underlying APIs they call are different. In an effort to prepare Marionette for the window tracking refactoring, this patch adds a bit of glue to combine them both into one assertion called assert.open. This checks that the browsing context has not been discarded. MozReview-Commit-ID: K5e7Sr1mq0
testing/marionette/assert.js
testing/marionette/browser.js
testing/marionette/driver.js
testing/marionette/reftest.js
testing/marionette/test_assert.js
--- a/testing/marionette/assert.js
+++ b/testing/marionette/assert.js
@@ -4,27 +4,33 @@
 
 "use strict";
 
 const {utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const {
   InvalidArgumentError,
   InvalidSessionIDError,
   JavaScriptError,
   NoSuchWindowError,
   UnexpectedAlertOpenError,
   UnsupportedOperationError,
 } = Cu.import("chrome://marionette/content/error.js", {});
 const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
 
+XPCOMUtils.defineLazyGetter(this, "browser", () => {
+  const {browser} = Cu.import("chrome://marionette/content/browser.js", {});
+  return browser;
+});
+
 this.EXPORTED_SYMBOLS = ["assert"];
 
 const isFennec = () => AppConstants.platform == "android";
 const isFirefox = () =>
     Services.appinfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 
 /**
  * Shorthands for common assertions made in Marionette.
@@ -120,55 +126,46 @@ assert.fennec = function(msg = "") {
  *     If <var>context</var> is not content.
  */
 assert.content = function(context, msg = "") {
   msg = msg || "Only supported in content context";
   assert.that(c => c.toString() == "content", msg, UnsupportedOperationError)(context);
 };
 
 /**
- * Asserts that |win| is open.
- *
- * @param {ChromeWindow} win
- *     Chrome window to test.
- * @param {string=} msg
- *     Custom error message.
- *
- * @return {ChromeWindow}
- *     <var>win</var> is returned unaltered.
+ * Asserts that the {@link ChromeWindow} is open or that the {@link
+ * browser.Context} has a content browser attached.
  *
- * @throws {NoSuchWindowError}
- *     If <var>win</var> has been closed.
- */
-assert.window = function(win, msg = "") {
-  msg = msg || "Unable to locate window";
-  return assert.that(w => w && !w.closed,
-      msg,
-      NoSuchWindowError)(win);
-};
-
-/**
- * Asserts that |context| is a valid browsing context.
+ * When passed in a {@link ChromeContext} this is equivalent to
+ * testing that the associated <code>window</code> global is open,
+ * and when given {@link browser.Context} it will test that the content
+ * frame, represented by <code>&lt;xul:browser&gt;</code>, is
+ * connected.
  *
- * @param {browser.Context} context
+ * @param {(ChromeWindow|browser.Context)} context
  *     Browsing context to test.
  * @param {string=} msg
  *     Custom error message.
  *
+ * @return {(ChromeWindow|browser.Context)}
+ *     <var>context</var> is returned unaltered.
+ *
  * @throws {NoSuchWindowError}
- *     If |context| is invalid.
+ *     If <var>context</var>'s <code>window</code> has been closed.
  */
-assert.contentBrowser = function(context, msg = "") {
+assert.open = function(context, msg = "") {
   // TODO: The contentBrowser uses a cached tab, which is only updated when
   // switchToTab is called. Because of that an additional check is needed to
   // make sure that the chrome window has not already been closed.
-  assert.window(context && context.window);
+  if (context instanceof browser.Context) {
+    assert.open(context.window);
+  }
 
-  msg = msg || "Current window does not have a content browser";
-  assert.that(c => c.contentBrowser,
+  msg = msg || "Browsing context has been discarded";
+  return assert.that(ctx => ctx && !ctx.closed,
       msg,
       NoSuchWindowError)(context);
 };
 
 /**
  * Asserts that there is no current user prompt.
  *
  * @param {modal.Dialog} dialog
--- a/testing/marionette/browser.js
+++ b/testing/marionette/browser.js
@@ -170,16 +170,30 @@ browser.Context = class {
     return null;
   }
 
   get messageManager() {
     return this.contentBrowser.messageManager;
   }
 
   /**
+   * Checks if the browsing context has been discarded.
+   *
+   * The browsing context will have been discarded if the content
+   * browser, represented by the <code>&lt;xul:browser&gt;</code>,
+   * has been detached.
+   *
+   * @return {boolean}
+   *     True if browsing context has been discarded, false otherwise.
+   */
+  get closed() {
+    return this.contentBrowser === null;
+  }
+
+  /**
    * The current frame ID is managed per browser element on desktop in
    * case the ID needs to be refreshed. The currently selected window is
    * identified by a tab.
    */
   get curFrameId() {
     let rv = null;
     if (this.tab || this.driver.isReftestBrowser(this.contentBrowser)) {
       rv = this.getIdForBrowser(this.contentBrowser);
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -867,17 +867,17 @@ GeckoDriver.prototype.getContext = funct
  *
  * @throws {ScriptTimeoutError}
  *     If the script was interrupted due to reaching the
  *     <var>scriptTimeout</var> or default timeout.
  * @throws {JavaScriptError}
  *     If an {@link Error} was thrown whilst evaluating the script.
  */
 GeckoDriver.prototype.executeScript = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
 
   let {script, args, scriptTimeout} = cmd.parameters;
   scriptTimeout = scriptTimeout || this.timeouts.script;
 
   let opts = {
     sandboxName: cmd.parameters.sandbox,
     newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||
         cmd.parameters.newSandbox,
@@ -944,17 +944,17 @@ GeckoDriver.prototype.executeScript = as
  *
  * @throws {ScriptTimeoutError}
  *     If the script was interrupted due to reaching the
  *     <var>scriptTimeout</var> or default timeout.
  * @throws {JavaScriptError}
  *     If an Error was thrown whilst evaluating the script.
  */
 GeckoDriver.prototype.executeAsyncScript = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
 
   let {script, args, scriptTimeout} = cmd.parameters;
   scriptTimeout = scriptTimeout || this.timeouts.script;
 
   let opts = {
     sandboxName: cmd.parameters.sandbox,
     newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||
         cmd.parameters.newSandbox,
@@ -1027,17 +1027,17 @@ GeckoDriver.prototype.execute_ = async f
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.get = async function(cmd) {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let url = cmd.parameters.url;
 
   let get = this.listener.get({url, pageTimeout: this.timeouts.pageLoad});
 
   // If a reload of the frame script interrupts our page load, this will
   // never return. We need to re-issue this request to correctly poll for
@@ -1069,17 +1069,17 @@ GeckoDriver.prototype.get = async functi
  * of the current resource.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getCurrentUrl = function() {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   return this.currentURL.toString();
 };
 
 /**
  * Gets the current title of the window.
  *
@@ -1087,25 +1087,25 @@ GeckoDriver.prototype.getCurrentUrl = fu
  *     Document title of the top-level browsing context.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getTitle = function() {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   return this.title;
 };
 
 /** Gets the current type of the window. */
 GeckoDriver.prototype.getWindowType = function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
 
   resp.body.value = this.windowType;
 };
 
 /**
  * Gets the page source of the content document.
  *
  * @return {string}
@@ -1113,17 +1113,17 @@ GeckoDriver.prototype.getWindowType = fu
  *     active document.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getPageSource = async function(cmd, resp) {
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   switch (this.context) {
     case Context.Chrome:
       let s = new win.XMLSerializer();
       resp.body.value = s.serializeToString(win.document);
       break;
 
@@ -1141,17 +1141,17 @@ GeckoDriver.prototype.getPageSource = as
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.goBack = async function() {
   assert.content(this.context);
-  assert.contentBrowser(this.curBrowser);
+  assert.open(this.curBrowser);
   this._assertAndDismissModal();
 
   // If there is no history, just return
   if (!this.curBrowser.contentBrowser.webNavigation.canGoBack) {
     return;
   }
 
   let lastURL = this.currentURL;
@@ -1183,17 +1183,17 @@ GeckoDriver.prototype.goBack = async fun
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.goForward = async function() {
   assert.content(this.context);
-  assert.contentBrowser(this.curBrowser);
+  assert.open(this.curBrowser);
   this._assertAndDismissModal();
 
   // If there is no history, just return
   if (!this.curBrowser.contentBrowser.webNavigation.canGoForward) {
     return;
   }
 
   let lastURL = this.currentURL;
@@ -1226,17 +1226,17 @@ GeckoDriver.prototype.goForward = async 
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.refresh = async function() {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let refresh = this.listener.refresh(
       {pageTimeout: this.timeouts.pageLoad});
 
   // If a reload of the frame script interrupts our page load, this will
   // never return. We need to re-issue this request to correctly poll for
   // readyState and send errors.
@@ -1293,17 +1293,17 @@ GeckoDriver.prototype.getIdForBrowser = 
  *
  * @return {string}
  *     Unique window handle.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  */
 GeckoDriver.prototype.getWindowHandle = function() {
-  assert.contentBrowser(this.curBrowser);
+  assert.open(this.curBrowser);
 
   return this.curBrowser.curFrameId.toString();
 };
 
 /**
  * Get a list of top-level browsing contexts. On desktop this typically
  * corresponds to the set of open tabs for browser windows, or the window
  * itself for non-browser chrome windows.
@@ -1328,17 +1328,17 @@ GeckoDriver.prototype.getWindowHandles =
  *
  * @return {string}
  *     Unique window handle.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  */
 GeckoDriver.prototype.getChromeWindowHandle = function(cmd, resp) {
-  assert.window(this.getCurrentWindow(Context.Chrome));
+  assert.open(this.getCurrentWindow(Context.Chrome));
 
   for (let i in this.browsers) {
     if (this.curBrowser == this.browsers[i]) {
       resp.body.value = i;
       return;
     }
   }
 };
@@ -1366,17 +1366,17 @@ GeckoDriver.prototype.getChromeWindowHan
  *     of browser window.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getWindowRect = function() {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
   return this.curBrowser.rect;
 };
 
 /**
  * Set the window position and size of the browser on the operating
  * system window manager.
  *
@@ -1403,17 +1403,17 @@ GeckoDriver.prototype.getWindowRect = fu
  *     Not applicable to application.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.setWindowRect = async function(cmd) {
   assert.firefox();
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {x, y, width, height} = cmd.parameters;
   let origRect = this.curBrowser.rect;
 
   // Synchronous resize to |width| and |height| dimensions.
   async function resizeWindow(width, height) {
     return new Promise(resolve => {
@@ -1602,17 +1602,17 @@ GeckoDriver.prototype.setWindowHandle = 
     if ("tabIndex" in winProperties) {
       this.curBrowser.switchToTab(
           winProperties.tabIndex, winProperties.win, focus);
     }
   }
 };
 
 GeckoDriver.prototype.getActiveFrame = function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
 
   switch (this.context) {
     case Context.Chrome:
       // no frame means top-level
       resp.body.value = null;
       if (this.curFrame) {
         resp.body.value = this.curBrowser.seenEls.add(
             this.curFrame.frameElement);
@@ -1633,17 +1633,17 @@ GeckoDriver.prototype.getActiveFrame = f
  * of the current browsing context.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.switchToParentFrame = async function() {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   await this.listener.switchToParentFrame();
 };
 
 /**
  * Switch to a given frame within the current window.
  *
@@ -1654,17 +1654,17 @@ GeckoDriver.prototype.switchToParentFram
  *     or index of the frame to switch to.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.switchToFrame = async function(cmd) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {id, focus} = cmd.parameters;
 
   // TODO(ato): element can be either string (deprecated) or a web
   // element JSON Object.  Can be removed with Firefox 60.
   let byFrame;
   if (typeof cmd.parameters.element == "string") {
@@ -1837,17 +1837,17 @@ GeckoDriver.prototype.getTimeouts = func
 GeckoDriver.prototype.setTimeouts = function(cmd) {
   // merge with existing timeouts
   let merged = Object.assign(this.timeouts.toJSON(), cmd.parameters);
   this.timeouts = session.Timeouts.fromJSON(merged);
 };
 
 /** Single tap. */
 GeckoDriver.prototype.singleTap = async function(cmd) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
 
   let {id, x, y} = cmd.parameters;
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       throw new UnsupportedOperationError(
           "Command 'singleTap' is not yet available in chrome context");
@@ -1869,17 +1869,17 @@ GeckoDriver.prototype.singleTap = async 
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.performActions = async function(cmd) {
   assert.content(this.context,
       "Command 'performActions' is not yet available in chrome context");
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let actions = cmd.parameters.actions;
   await this.listener.performActions({"actions": actions});
 };
 
 /**
  * Release all the keys and pointer buttons that are currently depressed.
@@ -1888,17 +1888,17 @@ GeckoDriver.prototype.performActions = a
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.releaseActions = async function() {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   await this.listener.releaseActions();
 };
 
 /**
  * An action chain.
  *
@@ -1912,17 +1912,17 @@ GeckoDriver.prototype.releaseActions = a
  * @throws {UnsupportedOperationError}
  *     Not applicable to application.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.actionChain = async function(cmd, resp) {
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {chain, nextId} = cmd.parameters;
 
   switch (this.context) {
     case Context.Chrome:
       // be conservative until this has a use case and is established
       // to work as expected in Fennec
@@ -1950,17 +1950,17 @@ GeckoDriver.prototype.actionChain = asyn
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.multiAction = async function(cmd) {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {value, max_length} = cmd.parameters; // eslint-disable-line camelcase
   await this.listener.multiAction(value, max_length);
 };
 
 /**
  * Find an element using the indicated search strategy.
@@ -1971,17 +1971,17 @@ GeckoDriver.prototype.multiAction = asyn
  *     Value the client is looking for.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.findElement = async function(cmd, resp) {
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {using, value} = cmd.parameters;
   let startNode;
   if (typeof cmd.parameters.element != "undefined") {
     startNode = WebElement.fromUUID(cmd.parameters.element, this.context);
   }
 
@@ -2017,17 +2017,17 @@ GeckoDriver.prototype.findElement = asyn
  * Find elements using the indicated search strategy.
  *
  * @param {string} using
  *     Indicates which search method to use.
  * @param {string} value
  *     Value the client is looking for.
  */
 GeckoDriver.prototype.findElements = async function(cmd, resp) {
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
 
   let {using, value} = cmd.parameters;
   let startNode;
   if (typeof cmd.parameters.element != "undefined") {
     startNode = WebElement.fromUUID(cmd.parameters.element, this.context);
   }
 
   let opts = {
@@ -2071,17 +2071,17 @@ GeckoDriver.prototype.findElements = asy
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  * @throws {NoSuchElementError}
  *     If the document does not have an active element, i.e. if
  *     its document element has been deleted.
  */
 GeckoDriver.prototype.getActiveElement = async function() {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   return this.listener.getActiveElement();
 };
 
 /**
  * Send click event to element.
  *
@@ -2093,17 +2093,17 @@ GeckoDriver.prototype.getActiveElement =
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.clickElement = async function(cmd) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2149,17 +2149,17 @@ GeckoDriver.prototype.clickElement = asy
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementAttribute = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let name = assert.string(cmd.parameters.name);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
@@ -2189,17 +2189,17 @@ GeckoDriver.prototype.getElementAttribut
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementProperty = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let name = assert.string(cmd.parameters.name);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
@@ -2228,17 +2228,17 @@ GeckoDriver.prototype.getElementProperty
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementText = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // for chrome, we look at text nodes, and any node with a "label" field
@@ -2268,17 +2268,17 @@ GeckoDriver.prototype.getElementText = a
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementTagName = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2305,17 +2305,17 @@ GeckoDriver.prototype.getElementTagName 
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.isElementDisplayed = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2346,17 +2346,17 @@ GeckoDriver.prototype.isElementDisplayed
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementValueOfCssProperty = async function(
     cmd, resp) {
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let prop = assert.string(cmd.parameters.propertyName);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
@@ -2386,17 +2386,17 @@ GeckoDriver.prototype.getElementValueOfC
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.isElementEnabled = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // Selenium atom doesn't quite work here
@@ -2425,17 +2425,17 @@ GeckoDriver.prototype.isElementEnabled =
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.isElementSelected = async function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // Selenium atom doesn't quite work here
@@ -2456,17 +2456,17 @@ GeckoDriver.prototype.isElementSelected 
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementRect = async function(cmd, resp) {
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2498,17 +2498,17 @@ GeckoDriver.prototype.getElementRect = a
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.sendKeysToElement = async function(cmd) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let text = assert.string(cmd.parameters.text);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
@@ -2533,17 +2533,17 @@ GeckoDriver.prototype.sendKeysToElement 
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.clearElement = async function(cmd) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // the selenium atom doesn't work here
@@ -2569,17 +2569,17 @@ GeckoDriver.prototype.clearElement = asy
  *
  * @throws {InvalidArgumentError}
  *     If <var>id</var> is not a string.
  * @throws {NoSuchElementError}
  *     If element represented by reference <var>id</var> is unknown.
  */
 GeckoDriver.prototype.switchToShadowRoot = async function(cmd) {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
   await this.listener.switchToShadowRoot(webEl);
 };
 
 /**
  * Add a single cookie to the cookie store associated with the active
@@ -2595,17 +2595,17 @@ GeckoDriver.prototype.switchToShadowRoot
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  * @throws {InvalidCookieDomainError}
  *     If <var>cookie</var> is for a different domain than the active
  *     document's host.
  */
 GeckoDriver.prototype.addCookie = function(cmd) {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {protocol, hostname} = this.currentURL;
 
   const networkSchemes = ["ftp:", "http:", "https:"];
   if (!networkSchemes.includes(protocol)) {
     throw new InvalidCookieDomainError("Document is cookie-averse");
   }
@@ -2625,17 +2625,17 @@ GeckoDriver.prototype.addCookie = functi
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getCookies = function(cmd, resp) {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {hostname, pathname} = this.currentURL;
   resp.body = [...cookie.iter(hostname, pathname)];
 };
 
 /**
  * Delete all cookies that are visible to a document.
@@ -2644,17 +2644,17 @@ GeckoDriver.prototype.getCookies = funct
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.deleteAllCookies = function() {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {hostname, pathname} = this.currentURL;
   for (let toDelete of cookie.iter(hostname, pathname)) {
     cookie.remove(toDelete);
   }
 };
 
@@ -2665,17 +2665,17 @@ GeckoDriver.prototype.deleteAllCookies =
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.deleteCookie = function(cmd) {
   assert.content(this.context);
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   let {hostname, pathname} = this.currentURL;
   let name = assert.string(cmd.parameters.name);
   for (let c of cookie.iter(hostname, pathname)) {
     if (c.name === name) {
       cookie.remove(c);
     }
@@ -2695,17 +2695,17 @@ GeckoDriver.prototype.deleteCookie = fun
  *     Unique window handles of remaining windows.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.close = async function() {
-  assert.window(this.getCurrentWindow(Context.Content));
+  assert.open(this.getCurrentWindow(Context.Content));
   this._assertAndDismissModal();
 
   let nwins = 0;
 
   for (let win of this.windows) {
     // For browser windows count the tabs. Otherwise take the window itself.
     let tabbrowser = browser.getTabBrowser(win);
     if (tabbrowser && tabbrowser.tabs) {
@@ -2733,17 +2733,17 @@ GeckoDriver.prototype.close = async func
  * closed to prevent a shutdown of the application. Instead the returned
  * list of chrome window handles is empty.
  *
  * @return {Array.<string>}
  *     Unique chrome window handles of remaining chrome windows.
  */
 GeckoDriver.prototype.closeChromeWindow = async function() {
   assert.firefox();
-  assert.window(this.getCurrentWindow(Context.Chrome));
+  assert.open(this.getCurrentWindow(Context.Chrome));
 
   let nwins = 0;
 
   // eslint-disable-next-line
   for (let _ of this.windows) {
     nwins++;
   }
 
@@ -2840,17 +2840,17 @@ GeckoDriver.prototype.deleteSession = fu
  *     scroll to the element.
  *
  * @return {string}
  *     If <var>hash</var> is false, PNG image encoded as Base64 encoded
  *     string.  If <var>hash</var> is true, hex digest of the SHA-256
  *     hash of the Base64 encoded string.
  */
 GeckoDriver.prototype.takeScreenshot = function(cmd) {
-  let win = assert.window(this.getCurrentWindow());
+  let win = assert.open(this.getCurrentWindow());
 
   let {id, highlights, full, hash} = cmd.parameters;
   highlights = highlights || [];
   let format = hash ? capture.Format.Hash : capture.Format.Base64;
 
   switch (this.context) {
     case Context.Chrome:
       let highlightEls = highlights
@@ -2895,17 +2895,17 @@ GeckoDriver.prototype.takeScreenshot = f
  * Get the current browser orientation.
  *
  * Will return one of the valid primary orientation values
  * portrait-primary, landscape-primary, portrait-secondary, or
  * landscape-secondary.
  */
 GeckoDriver.prototype.getScreenOrientation = function(cmd, resp) {
   assert.fennec();
-  let win = assert.window(this.getCurrentWindow());
+  let win = assert.open(this.getCurrentWindow());
 
   resp.body.value = win.screen.mozOrientation;
 };
 
 /**
  * Set the current browser orientation.
  *
  * The supplied orientation should be given as one of the valid
@@ -2913,17 +2913,17 @@ GeckoDriver.prototype.getScreenOrientati
  * be raised.
  *
  * Valid orientations are "portrait" and "landscape", which fall
  * back to "portrait-primary" and "landscape-primary" respectively,
  * and "portrait-secondary" as well as "landscape-secondary".
  */
 GeckoDriver.prototype.setScreenOrientation = function(cmd) {
   assert.fennec();
-  let win = assert.window(this.getCurrentWindow());
+  let win = assert.open(this.getCurrentWindow());
 
   const ors = [
     "portrait", "landscape",
     "portrait-primary", "landscape-primary",
     "portrait-secondary", "landscape-secondary",
   ];
 
   let or = String(cmd.parameters.orientation);
@@ -2953,17 +2953,17 @@ GeckoDriver.prototype.setScreenOrientati
  *     Not available for current application.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.minimizeWindow = async function() {
   assert.firefox();
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   if (WindowState.from(win.windowState) == WindowState.Fullscreen) {
     await exitFullscreen(win);
   }
 
   if (WindowState.from(win.windowState) != WindowState.Minimized) {
     await new Promise(resolve => {
@@ -2990,17 +2990,17 @@ GeckoDriver.prototype.minimizeWindow = a
  *     Not available for current application.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.maximizeWindow = async function() {
   assert.firefox();
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   switch (WindowState.from(win.windowState)) {
     case WindowState.Fullscreen:
       await exitFullscreen(win);
       break;
 
     case WindowState.Minimized:
@@ -3076,17 +3076,17 @@ GeckoDriver.prototype.maximizeWindow = a
  *     Not available for current application.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.fullscreenWindow = async function() {
   assert.firefox();
-  const win = assert.window(this.getCurrentWindow());
+  const win = assert.open(this.getCurrentWindow());
   this._assertAndDismissModal();
 
   if (WindowState.from(win.windowState) == WindowState.Minimized) {
     await restoreWindow(win, this.curBrowser.eventObserver);
   }
 
   if (WindowState.from(win.windowState) != WindowState.Fullscreen) {
     await new Promise(resolve => {
@@ -3098,43 +3098,43 @@ GeckoDriver.prototype.fullscreenWindow =
   return this.curBrowser.rect;
 };
 
 /**
  * Dismisses a currently displayed tab modal, or returns no such alert if
  * no modal is displayed.
  */
 GeckoDriver.prototype.dismissDialog = function() {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._checkIfAlertIsPresent();
 
   let {button0, button1} = this.dialog.ui;
   (button1 ? button1 : button0).click();
   this.dialog = null;
 };
 
 /**
  * Accepts a currently displayed tab modal, or returns no such alert if
  * no modal is displayed.
  */
 GeckoDriver.prototype.acceptDialog = function() {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._checkIfAlertIsPresent();
 
   let {button0} = this.dialog.ui;
   button0.click();
   this.dialog = null;
 };
 
 /**
  * Returns the message shown in a currently displayed modal, or returns
  * a no such alert error if no modal is currently displayed.
  */
 GeckoDriver.prototype.getTextFromDialog = function(cmd, resp) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._checkIfAlertIsPresent();
 
   let {infoBody} = this.dialog.ui;
   resp.body.value = infoBody.textContent;
 };
 
 /**
  * Set the user prompt's value field.
@@ -3151,17 +3151,17 @@ GeckoDriver.prototype.getTextFromDialog 
  *     If the current user prompt is an alert or confirm.
  * @throws {NoSuchAlertError}
  *     If there is no current user prompt.
  * @throws {UnsupportedOperationError}
  *     If the current user prompt is something other than an alert,
  *     confirm, or a prompt.
  */
 GeckoDriver.prototype.sendKeysToDialog = async function(cmd) {
-  assert.window(this.getCurrentWindow());
+  assert.open(this.getCurrentWindow());
   this._checkIfAlertIsPresent();
 
   // see toolkit/components/prompts/content/commonDialog.js
   let {loginTextbox} = this.dialog.ui;
   await interaction.sendKeysToElement(
       loginTextbox, cmd.parameters.text, this.a11yChecks);
 };
 
--- a/testing/marionette/reftest.js
+++ b/testing/marionette/reftest.js
@@ -64,17 +64,17 @@ reftest.Runner = class {
    * @param {Object.<Number>} urlCount
    *     Object holding a map of URL: number of times the URL
    *     will be opened during the reftest run, where that's
    *     greater than 1.
    * @param {string} screenshotMode
    *     String enum representing when screenshots should be taken
    */
   async setup(urlCount, screenshotMode) {
-    this.parentWindow =  assert.window(this.driver.getCurrentWindow());
+    this.parentWindow =  assert.open(this.driver.getCurrentWindow());
 
     this.screenshotMode = SCREENSHOT_MODE[screenshotMode] ||
         SCREENSHOT_MODE.unexpected;
 
     this.urlCount = Object.keys(urlCount || {})
         .reduce((map, key) => map.set(key, urlCount[key]), new Map());
 
     await this.ensureWindow();
--- a/testing/marionette/test_assert.js
+++ b/testing/marionette/test_assert.js
@@ -164,37 +164,24 @@ add_test(function test_string() {
   assert.string(`bar`);
   Assert.throws(() => assert.string(42), InvalidArgumentError);
 
   Assert.throws(() => assert.string(42, "custom"), /custom/);
 
   run_next_test();
 });
 
-add_test(function test_window() {
-  assert.window({closed: false});
+add_test(function test_open() {
+  assert.open({closed: false});
 
   for (let typ of [null, undefined, {closed: true}]) {
-    Assert.throws(() => assert.window(typ), NoSuchWindowError);
+    Assert.throws(() => assert.open(typ), NoSuchWindowError);
   }
 
-  Assert.throws(() => assert.window(null, "custom"), /custom/);
-
-  run_next_test();
-});
-
-add_test(function test_contentBrowser() {
-  assert.contentBrowser({contentBrowser: 42, window: {closed: false}});
-
-  let closedWindow = {contentBrowser: 42, window: {closed: true}};
-  let noContentBrowser = {contentBrowser: null, window: {closed: false}};
-
-  for (let typ of [null, undefined, closedWindow, noContentBrowser]) {
-    Assert.throws(() => assert.contentBrowser(typ), NoSuchWindowError);
-  }
+  Assert.throws(() => assert.open(null, "custom"), /custom/);
 
   run_next_test();
 });
 
 add_test(function test_object() {
   assert.object({});
   assert.object(new Object());
   for (let typ of [42, "foo", true, null, undefined]) {