Bug 1397383 - Add loadReplace option to tabs.update, r?mixedpuppy draft
authorBob Silverberg <bsilverberg@mozilla.com>
Fri, 08 Sep 2017 08:31:39 -0400
changeset 661695 34dd30e07eb35cbbdc782f6a7f4c3c9e58399af4
parent 660738 37b95547f0d27565452136d16b2df2857be840f6
child 730652 7018a4162af6ef7062afea74ea9f06e20baf4ec5
push id78849
push userbmo:bob.silverberg@gmail.com
push dateFri, 08 Sep 2017 21:13:11 +0000
reviewersmixedpuppy
bugs1397383
milestone57.0a1
Bug 1397383 - Add loadReplace option to tabs.update, r?mixedpuppy This adds a loadReplace option into the updateOptions object for tabs.update() which, when set to true, will cause the loading of the new URL to replace the current URL in the tab's history. MozReview-Commit-ID: KZTuEl7cgb0
browser/components/extensions/ext-tabs.js
browser/components/extensions/schemas/tabs.json
browser/components/extensions/test/browser/browser_ext_tabs_update_url.js
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -433,17 +433,20 @@ this.tabs = class extends ExtensionAPI {
 
           if (updateProperties.url !== null) {
             let url = context.uri.resolve(updateProperties.url);
 
             if (!context.checkLoadURL(url, {dontReportErrors: true})) {
               return Promise.reject({message: `Illegal URL: ${url}`});
             }
 
-            nativeTab.linkedBrowser.loadURI(url);
+            let flags = updateProperties.loadReplace
+              ? Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY
+              : Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
+            nativeTab.linkedBrowser.loadURIWithFlags(url, {flags});
           }
 
           if (updateProperties.active !== null) {
             if (updateProperties.active) {
               tabbrowser.selectedTab = nativeTab;
             } else {
               // Not sure what to do here? Which tab should we select?
             }
--- a/browser/components/extensions/schemas/tabs.json
+++ b/browser/components/extensions/schemas/tabs.json
@@ -743,16 +743,21 @@
                 "optional": true,
                 "description": "Whether the tab should be muted."
               },
               "openerTabId": {
                 "type": "integer",
                 "minimum": 0,
                 "optional": true,
                 "description": "The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as this tab."
+              },
+              "loadReplace": {
+                "type": "boolean",
+                "optional": true,
+                "description": "Whether the load should replace the current history entry for the tab."
               }
             }
           },
           {
             "type": "function",
             "name": "callback",
             "optional": true,
             "parameters": [
--- a/browser/components/extensions/test/browser/browser_ext_tabs_update_url.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_update_url.js
@@ -1,12 +1,17 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
+XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
+                                  "resource:///modules/sessionstore/SessionStore.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TabStateFlusher",
+                                  "resource:///modules/sessionstore/TabStateFlusher.jsm");
+
 async function testTabsUpdateURL(existentTabURL, tabsUpdateURL, isErrorExpected) {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
     },
 
     files: {
       "tab.html": `
@@ -103,8 +108,78 @@ add_task(async function() {
         .map((check) => Object.assign({}, check, {existentTabURL: "about:blank"}));
 
   for (let {existentTabURL, tabsUpdateURL, isErrorExpected} of testCases) {
     await testTabsUpdateURL(existentTabURL, tabsUpdateURL, isErrorExpected);
   }
 
   info("done");
 });
+
+add_task(async function test_update_reload() {
+  const URL = "https://example.com/";
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "permissions": ["tabs", "history"],
+    },
+
+    background() {
+      browser.test.onMessage.addListener(async (cmd, ...args) => {
+        const result = await browser.tabs[cmd](...args);
+        browser.test.sendMessage("result", result);
+      });
+
+      browser.history.onVisited.addListener(data => {
+        browser.test.sendMessage("historyAdded");
+      });
+    },
+  });
+
+  let win = await BrowserTestUtils.openNewBrowserWindow();
+  let tabBrowser = win.gBrowser.selectedBrowser;
+  await BrowserTestUtils.loadURI(tabBrowser, URL);
+  await BrowserTestUtils.browserLoaded(tabBrowser, false, URL);
+  let tab = win.gBrowser.selectedTab;
+
+  async function getTabHistory() {
+    await TabStateFlusher.flush(tabBrowser);
+    return JSON.parse(SessionStore.getTabState(tab));
+  }
+
+  await extension.startup();
+  extension.sendMessage("query", {url: URL});
+  let tabs = await extension.awaitMessage("result");
+  let tabId = tabs[0].id;
+
+  let history = await getTabHistory();
+  is(history.entries.length, 1,
+     "Tab history contains the expected number of entries.");
+  is(history.entries[0].url, URL,
+    `Tab history contains the expected entry: URL.`);
+
+  extension.sendMessage("update", tabId, {url: `${URL}1/`});
+  await Promise.all([
+    extension.awaitMessage("result"),
+    extension.awaitMessage("historyAdded"),
+  ]);
+
+  history = await getTabHistory();
+  is(history.entries.length, 2,
+     "Tab history contains the expected number of entries.");
+  is(history.entries[1].url, `${URL}1/`,
+    `Tab history contains the expected entry: ${URL}1/.`);
+
+  extension.sendMessage("update", tabId, {url: `${URL}2/`, loadReplace: true});
+  await Promise.all([
+    extension.awaitMessage("result"),
+    extension.awaitMessage("historyAdded"),
+  ]);
+
+  history = await getTabHistory();
+  is(history.entries.length, 2,
+     "Tab history contains the expected number of entries.");
+  is(history.entries[1].url, `${URL}2/`,
+    `Tab history contains the expected entry: ${URL}2/.`);
+
+  await extension.unload();
+  await BrowserTestUtils.closeWindow(win);
+});