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
--- 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);
+});