Bug 1381459 - Allow closing of browserless tabs.
Closing a tab should always be allowed, even if the current content browser doesn't exist.
This can be the case when a tab gets moved to a different process.
MozReview-Commit-ID: LaU9MgEyCOx
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -236,16 +236,22 @@ Object.defineProperty(GeckoDriver.protot
});
Object.defineProperty(GeckoDriver.prototype, "windows", {
get() {
return enumeratorIterator(Services.wm.getEnumerator(null));
},
});
+Object.defineProperty(GeckoDriver.prototype, "windowType", {
+ get() {
+ return this.curBrowser.window.document.documentElement.getAttribute("windowtype");
+ },
+});
+
Object.defineProperty(GeckoDriver.prototype, "windowHandles", {
get() {
let hs = [];
for (let win of this.windows) {
let tabBrowser = browser.getTabBrowser(win);
// Only return handles for browser windows
@@ -1160,19 +1166,19 @@ GeckoDriver.prototype.getTitle = functio
assert.window(this.getCurrentWindow());
this._assertAndDismissModal();
return this.title;
};
/** Gets the current type of the window. */
GeckoDriver.prototype.getWindowType = function(cmd, resp) {
- let win = assert.window(this.getCurrentWindow());
-
- resp.body.value = win.document.documentElement.getAttribute("windowtype");
+ assert.window(this.getCurrentWindow());
+
+ resp.body.value = this.windowType;
};
/**
* Gets the page source of the content document.
*
* @return {string}
* String serialisation of the DOM of the current browsing context's
* active document.
@@ -2795,17 +2801,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.contentBrowser(this.curBrowser);
+ assert.window(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) {
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_window_close_content.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_close_content.py
@@ -75,8 +75,36 @@ class TestCloseWindow(WindowManagerMixin
def test_close_window_for_last_open_tab(self):
self.close_all_tabs()
self.assertListEqual([], self.marionette.close())
self.assertListEqual([self.start_tab], self.marionette.window_handles)
self.assertListEqual([self.start_window], self.marionette.chrome_window_handles)
self.assertIsNotNone(self.marionette.session)
+
+ @skip_if_mobile("discardBrowser is only available in Firefox")
+ def test_close_browserless_tab(self):
+ self.close_all_tabs()
+
+ test_page = self.marionette.absolute_url("windowHandles.html")
+ tab = self.open_tab()
+ self.marionette.switch_to_window(tab)
+ self.marionette.navigate(test_page)
+ self.marionette.switch_to_window(self.start_tab)
+
+ with self.marionette.using_context("chrome"):
+ self.marionette.execute_async_script("""
+ Components.utils.import("resource:///modules/RecentWindow.jsm");
+
+ let win = RecentWindow.getMostRecentBrowserWindow();
+ win.addEventListener("TabBrowserDiscarded", ev => {
+ marionetteScriptFinished(true);
+ }, { once: true});
+ win.gBrowser.discardBrowser(win.gBrowser.tabs[1].linkedBrowser);
+ """)
+
+ window_handles = self.marionette.window_handles
+ window_handles.remove(self.start_tab)
+ self.assertEqual(1, len(window_handles))
+ self.marionette.switch_to_window(window_handles[0], focus=False)
+ self.marionette.close()
+ self.assertListEqual([self.start_tab], self.marionette.window_handles)