mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Merge inbound to mozilla-central r=merge a=merge
This commit is contained in:
commit
c6a942e1bf
@ -98,7 +98,7 @@ tasks:
|
||||
TASKCLUSTER_CACHES: /builds/worker/checkouts
|
||||
- $if: 'tasks_for == "action"'
|
||||
then:
|
||||
ACTION_TASK_GROUP_ID: '${action.taskGroupId}'
|
||||
ACTION_TASK_GROUP_ID: '${ownTaskId}'
|
||||
ACTION_TASK_ID: {$json: {$eval: 'taskId'}}
|
||||
ACTION_TASK: {$json: {$eval: 'task'}}
|
||||
ACTION_INPUT: {$json: {$eval: 'input'}}
|
||||
@ -185,4 +185,7 @@ tasks:
|
||||
taskId: {$eval: 'taskId'}
|
||||
input: {$eval: 'input'}
|
||||
parameters: {$eval: 'parameters'}
|
||||
- $if: 'tasks_for == "cron"'
|
||||
then:
|
||||
cron: {$json: {$eval: 'cron'}}
|
||||
- tasks_for: '${tasks_for}'
|
||||
|
@ -602,98 +602,6 @@ addMessageListener("Browser:AppTab", function(message) {
|
||||
}
|
||||
});
|
||||
|
||||
let PrerenderContentHandler = {
|
||||
init() {
|
||||
this._pending = [];
|
||||
this._idMonotonic = 0;
|
||||
this._initialized = true;
|
||||
addMessageListener("Prerender:Canceled", this);
|
||||
addMessageListener("Prerender:Swapped", this);
|
||||
},
|
||||
|
||||
get initialized() {
|
||||
return !!this._initialized;
|
||||
},
|
||||
|
||||
receiveMessage(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "Prerender:Canceled": {
|
||||
for (let i = 0; i < this._pending.length; ++i) {
|
||||
if (this._pending[i].id === aMessage.data.id) {
|
||||
if (this._pending[i].failure) {
|
||||
this._pending[i].failure.run();
|
||||
}
|
||||
// Remove the item from the array
|
||||
this._pending.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Prerender:Swapped": {
|
||||
for (let i = 0; i < this._pending.length; ++i) {
|
||||
if (this._pending[i].id === aMessage.data.id) {
|
||||
if (this._pending[i].success) {
|
||||
this._pending[i].success.run();
|
||||
}
|
||||
// Remove the item from the array
|
||||
this._pending.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
startPrerenderingDocument(aHref, aReferrer, aTriggeringPrincipal) {
|
||||
// XXX: Make this constant a pref
|
||||
if (this._pending.length >= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
let id = ++this._idMonotonic;
|
||||
sendAsyncMessage("Prerender:Request", {
|
||||
href: aHref.spec,
|
||||
referrer: aReferrer ? aReferrer.spec : null,
|
||||
id,
|
||||
triggeringPrincipal: Utils.serializePrincipal(aTriggeringPrincipal),
|
||||
});
|
||||
|
||||
this._pending.push({
|
||||
href: aHref,
|
||||
referrer: aReferrer,
|
||||
id,
|
||||
success: null,
|
||||
failure: null,
|
||||
});
|
||||
},
|
||||
|
||||
shouldSwitchToPrerenderedDocument(aHref, aReferrer, aSuccess, aFailure) {
|
||||
// Check if we think there is a prerendering document pending for the given
|
||||
// href and referrer. If we think there is one, we will send a message to
|
||||
// the parent process asking it to do a swap, and hook up the success and
|
||||
// failure listeners.
|
||||
for (let i = 0; i < this._pending.length; ++i) {
|
||||
let p = this._pending[i];
|
||||
if (p.href.equals(aHref) && p.referrer.equals(aReferrer)) {
|
||||
p.success = aSuccess;
|
||||
p.failure = aFailure;
|
||||
sendAsyncMessage("Prerender:Swap", {id: p.id});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
// We only want to initialize the PrerenderContentHandler in the content
|
||||
// process. Outside of the content process, this should be unused.
|
||||
PrerenderContentHandler.init();
|
||||
}
|
||||
|
||||
var WebBrowserChrome = {
|
||||
onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
@ -717,20 +625,6 @@ var WebBrowserChrome = {
|
||||
reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags) {
|
||||
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags);
|
||||
return true;
|
||||
},
|
||||
|
||||
startPrerenderingDocument(aHref, aReferrer, aTriggeringPrincipal) {
|
||||
if (PrerenderContentHandler.initialized) {
|
||||
PrerenderContentHandler.startPrerenderingDocument(aHref, aReferrer, aTriggeringPrincipal);
|
||||
}
|
||||
},
|
||||
|
||||
shouldSwitchToPrerenderedDocument(aHref, aReferrer, aSuccess, aFailure) {
|
||||
if (PrerenderContentHandler.initialized) {
|
||||
return PrerenderContentHandler.shouldSwitchToPrerenderedDocument(
|
||||
aHref, aReferrer, aSuccess, aFailure);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1732,7 +1732,6 @@
|
||||
var aOriginPrincipal;
|
||||
var aOpener;
|
||||
var aOpenerBrowser;
|
||||
var aIsPrerendered;
|
||||
var aCreateLazyBrowser;
|
||||
var aNextTabParentId;
|
||||
var aFocusUrlBar;
|
||||
@ -1760,7 +1759,6 @@
|
||||
aOriginPrincipal = params.originPrincipal;
|
||||
aOpener = params.opener;
|
||||
aOpenerBrowser = params.openerBrowser;
|
||||
aIsPrerendered = params.isPrerendered;
|
||||
aCreateLazyBrowser = params.createLazyBrowser;
|
||||
aNextTabParentId = params.nextTabParentId;
|
||||
aFocusUrlBar = params.focusUrlBar;
|
||||
@ -1792,7 +1790,6 @@
|
||||
sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
|
||||
opener: aOpener,
|
||||
openerBrowser: aOpenerBrowser,
|
||||
isPrerendered: aIsPrerendered,
|
||||
nextTabParentId: aNextTabParentId,
|
||||
focusUrlBar: aFocusUrlBar,
|
||||
name: aName });
|
||||
@ -2201,7 +2198,7 @@
|
||||
<![CDATA[
|
||||
// Supported parameters:
|
||||
// userContextId, remote, remoteType, isPreloadBrowser,
|
||||
// uriIsAboutBlank, sameProcessAsFrameLoader, isPrerendered
|
||||
// uriIsAboutBlank, sameProcessAsFrameLoader
|
||||
|
||||
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
@ -2213,10 +2210,6 @@
|
||||
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
|
||||
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
|
||||
|
||||
if (aParams.isPrerendered) {
|
||||
b.setAttribute("prerendered", "true");
|
||||
}
|
||||
|
||||
if (aParams.userContextId) {
|
||||
b.setAttribute("usercontextid", aParams.userContextId);
|
||||
}
|
||||
@ -2605,7 +2598,6 @@
|
||||
var aDisallowInheritPrincipal;
|
||||
var aOpener;
|
||||
var aOpenerBrowser;
|
||||
var aIsPrerendered;
|
||||
var aCreateLazyBrowser;
|
||||
var aSkipBackgroundNotify;
|
||||
var aNextTabParentId;
|
||||
@ -2637,7 +2629,6 @@
|
||||
aDisallowInheritPrincipal = params.disallowInheritPrincipal;
|
||||
aOpener = params.opener;
|
||||
aOpenerBrowser = params.openerBrowser;
|
||||
aIsPrerendered = params.isPrerendered;
|
||||
aCreateLazyBrowser = params.createLazyBrowser;
|
||||
aSkipBackgroundNotify = params.skipBackgroundNotify;
|
||||
aNextTabParentId = params.nextTabParentId;
|
||||
@ -2695,10 +2686,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (aIsPrerendered) {
|
||||
t.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
// Related tab inherits current tab's user context unless a different
|
||||
// usercontextid is specified
|
||||
if (aUserContextId == null && openerTab) {
|
||||
@ -2795,7 +2782,6 @@
|
||||
userContextId: aUserContextId,
|
||||
sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
|
||||
openerWindow: aOpener,
|
||||
isPrerendered: aIsPrerendered,
|
||||
nextTabParentId: aNextTabParentId,
|
||||
name: aName });
|
||||
}
|
||||
@ -5824,76 +5810,6 @@
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "Prerender:Request": {
|
||||
let sendCancelPrerendering = () => {
|
||||
browser.frameloader.messageManager.
|
||||
sendAsyncMessage("Prerender:Canceled", { id: data.id });
|
||||
};
|
||||
|
||||
let tab = this.getTabForBrowser(browser);
|
||||
if (!tab) {
|
||||
// No tab?
|
||||
sendCancelPrerendering();
|
||||
break;
|
||||
}
|
||||
|
||||
if (tab.hidden) {
|
||||
// Skip prerender on hidden tab.
|
||||
sendCancelPrerendering();
|
||||
break;
|
||||
}
|
||||
|
||||
if (browser.canGoForward) {
|
||||
// Skip prerender on history navigation as we don't support it
|
||||
// yet. Remove this check once bug 1323650 is implemented.
|
||||
sendCancelPrerendering();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!data.href) {
|
||||
// If we don't have data.href, loadOneTab will load about:blank
|
||||
// which is meaningless for prerendering.
|
||||
sendCancelPrerendering();
|
||||
break;
|
||||
}
|
||||
|
||||
let groupedSHistory = browser.frameLoader.ensureGroupedSHistory();
|
||||
|
||||
let newTab = this.loadOneTab(data.href, {
|
||||
referrerURI: (data.referrer ? makeURI(data.referrer) : null),
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
postData: null,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Utils.deserializePrincipal(data.triggeringPrincipal),
|
||||
});
|
||||
let partialSHistory = newTab.linkedBrowser.frameLoader.partialSHistory;
|
||||
groupedSHistory.addPrerenderingPartialSHistory(partialSHistory, data.id);
|
||||
break;
|
||||
}
|
||||
|
||||
case "Prerender:Cancel": {
|
||||
let groupedSHistory = browser.frameLoader.groupedSHistory;
|
||||
if (groupedSHistory) {
|
||||
groupedSHistory.cancelPrerendering(data.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "Prerender:Swap": {
|
||||
let frameloader = browser.frameLoader;
|
||||
let groupedSHistory = browser.frameLoader.groupedSHistory;
|
||||
if (groupedSHistory) {
|
||||
groupedSHistory.activatePrerendering(data.id).then(
|
||||
() => frameloader.messageManager.sendAsyncMessage("Prerender:Swapped", data),
|
||||
() => frameloader.messageManager.sendAsyncMessage("Prerender:Canceled", data),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return undefined;
|
||||
]]></body>
|
||||
@ -6060,11 +5976,6 @@
|
||||
Services.prefs.addObserver("accessibility.typeaheadfind", this);
|
||||
messageManager.addMessageListener("Findbar:Keypress", this);
|
||||
|
||||
// Add listeners for prerender messages
|
||||
messageManager.addMessageListener("Prerender:Request", this);
|
||||
messageManager.addMessageListener("Prerender:Cancel", this);
|
||||
messageManager.addMessageListener("Prerender:Swap", this);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "animationsEnabled",
|
||||
"toolkit.cosmeticAnimations.enabled", true);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "schedulePressureDefaultCount",
|
||||
|
@ -588,6 +588,3 @@ skip-if = (os == "linux" && !e10s) # Bug 1263254 - Perma fails on Linux without
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_bug1299667.js]
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_close_dependent_tabs.js]
|
||||
skip-if = !e10s # GroupedSHistory is e10s-only
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
|
@ -1,78 +0,0 @@
|
||||
add_task(async function() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true],
|
||||
["dom.linkPrerender.enabled", true]]
|
||||
});
|
||||
|
||||
// Wait for a process change and then fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("BrowserChangedProcess", function(e) {
|
||||
ok(true, "The browser changed process!");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for given number tabs being closed.
|
||||
function awaitTabClose(number) {
|
||||
return new Promise(resolve => {
|
||||
let seen = 0;
|
||||
gBrowser.tabContainer.addEventListener("TabClose", function f() {
|
||||
if (++seen == number) {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", f);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test 1: Create prerendered browser, and don't switch to it, then close the tab
|
||||
let closed1 = awaitTabClose(2);
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, async function(browser1) {
|
||||
// Set up the grouped SHEntry setup
|
||||
|
||||
let requestMade = new Promise(resolve => {
|
||||
browser1.messageManager.addMessageListener("Prerender:Request", function f() {
|
||||
browser1.messageManager.removeMessageListener("Prerender:Request", f);
|
||||
ok(true, "Successfully received the prerender request");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
is(gBrowser.tabs.length, 2);
|
||||
await ContentTask.spawn(browser1, null, function() {
|
||||
let link = content.document.createElement("link");
|
||||
link.setAttribute("rel", "prerender");
|
||||
link.setAttribute("href", "data:text/html,b");
|
||||
content.document.body.appendChild(link);
|
||||
});
|
||||
await requestMade;
|
||||
|
||||
is(gBrowser.tabs.length, 3);
|
||||
});
|
||||
await closed1;
|
||||
|
||||
// At this point prerendered tab should be closed
|
||||
is(gBrowser.tabs.length, 1, "The new tab and the prerendered 'tab' should be closed");
|
||||
|
||||
// Test 2: Create prerendered browser, switch to it, then close the tab
|
||||
let closed2 = awaitTabClose(2);
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, async function(browser1) {
|
||||
// Set up the grouped SHEntry setup
|
||||
let tab2 = gBrowser.loadOneTab("data:text/html,b", {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
|
||||
await awaitProcessChange(browser1);
|
||||
});
|
||||
await closed2;
|
||||
|
||||
// At this point prerendered tab should be closed
|
||||
is(gBrowser.tabs.length, 1, "The new tab and the prerendered 'tab' should be closed");
|
||||
});
|
@ -3898,11 +3898,7 @@ var SessionStoreInternal = {
|
||||
|
||||
this.markTabAsRestoring(aTab);
|
||||
|
||||
// We need a new frameloader if we are reloading into a browser with a
|
||||
// grouped session history (as we don't support restoring into browsers
|
||||
// with grouped session histories directly).
|
||||
let newFrameloader =
|
||||
aOptions.newFrameloader || !!browser.frameLoader.groupedSHistory;
|
||||
let newFrameloader = aOptions.newFrameloader;
|
||||
|
||||
let isRemotenessUpdate;
|
||||
if (aOptions.remoteType !== undefined) {
|
||||
|
@ -233,16 +233,7 @@ var MessageListener = {
|
||||
this.flush(data);
|
||||
break;
|
||||
case "SessionStore:becomeActiveProcess":
|
||||
let shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
|
||||
// Check if we are at the end of the current session history, if we are,
|
||||
// it is safe for us to collect and transmit our session history, so
|
||||
// transmit all of it. Otherwise, we only want to transmit our index changes,
|
||||
// so collect from kLastIndex.
|
||||
if (shistory.globalCount - shistory.globalIndexOffset == shistory.count) {
|
||||
SessionHistoryListener.collect();
|
||||
} else {
|
||||
SessionHistoryListener.collectFrom(kLastIndex);
|
||||
}
|
||||
SessionHistoryListener.collect();
|
||||
break;
|
||||
default:
|
||||
debug("received unknown message '" + name + "'");
|
||||
|
@ -258,8 +258,6 @@ run-if = e10s && crashreporter
|
||||
[browser_undoCloseById.js]
|
||||
skip-if = debug
|
||||
[browser_docshell_uuid_consistency.js]
|
||||
[browser_grouped_session_store.js]
|
||||
skip-if = !e10s # GroupedSHistory is e10s-only
|
||||
|
||||
[browser_closed_objects_changed_notifications_tabs.js]
|
||||
[browser_closed_objects_changed_notifications_windows.js]
|
||||
|
@ -1,143 +0,0 @@
|
||||
add_task(async function() {
|
||||
const URIs = [
|
||||
"data:text/html,1",
|
||||
"data:text/html,2",
|
||||
"data:text/html,3",
|
||||
"data:text/html,4",
|
||||
"data:text/html,5",
|
||||
];
|
||||
|
||||
const {TabStateCache} = Cu.import("resource:///modules/sessionstore/TabStateCache.jsm", {});
|
||||
const {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true]]
|
||||
});
|
||||
|
||||
// Check that the data stored in the TabStateCache is correct for the current state.
|
||||
async function validate(browser, length, index) {
|
||||
await TabStateFlusher.flush(browser);
|
||||
let {history} = TabStateCache.get(browser);
|
||||
is(history.entries.length, length, "Lengths match");
|
||||
for (let i = 0; i < length; ++i) {
|
||||
is(history.entries[i].url, URIs[i], "URI at index " + i + " matches");
|
||||
}
|
||||
is(history.index, index, "Index matches");
|
||||
await ContentTask.spawn(browser, [index, length], async function([expectedIndex, expectedLength]) {
|
||||
let webNav = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
is(webNav.sessionHistory.globalIndexOffset + webNav.sessionHistory.index,
|
||||
expectedIndex - 1, "In content index matches");
|
||||
is(webNav.canGoForward, expectedIndex < expectedLength, "canGoForward is correct");
|
||||
is(webNav.canGoBack, expectedIndex > 1, "canGoBack is correct");
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for a process change, followed by a locationchange event, and then
|
||||
// fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
let locChangeListener = {
|
||||
onLocationChange: () => {
|
||||
gBrowser.removeProgressListener(locChangeListener);
|
||||
resolve();
|
||||
},
|
||||
};
|
||||
|
||||
browser.addEventListener("BrowserChangedProcess", function(e) {
|
||||
gBrowser.addProgressListener(locChangeListener);
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
// Order of events:
|
||||
// Load [0], load [1], prerender [2], load [2], load [3]
|
||||
// Back [2], Back [1], Forward [2], Back [0], Forward [3]
|
||||
// Prerender [4], Back [0], Forward [2], Load [3'], Back [0].
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: URIs[0] }, async function(browser1) {
|
||||
await validate(browser1, 1, 1);
|
||||
|
||||
browser1.loadURI(URIs[1], null, null);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
await validate(browser1, 2, 2);
|
||||
|
||||
// Create a new hidden prerendered tab to swap to.
|
||||
let tab2 = gBrowser.loadOneTab(URIs[2], {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 3, 3);
|
||||
|
||||
browser1.loadURI(URIs[3], null, null);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
await validate(browser1, 4, 4);
|
||||
|
||||
// In process navigate back.
|
||||
let p = BrowserTestUtils.waitForContentEvent(browser1, "pageshow");
|
||||
browser1.goBack();
|
||||
await p;
|
||||
await validate(browser1, 4, 3);
|
||||
|
||||
// Cross process navigate back.
|
||||
browser1.goBack();
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 4, 2);
|
||||
|
||||
// Cross process navigate forward.
|
||||
browser1.goForward();
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 4, 3);
|
||||
|
||||
// Navigate across process to a page which was not recently loaded.
|
||||
browser1.gotoIndex(0);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 4, 1);
|
||||
|
||||
// Navigate across process to a page which was not recently loaded in the other direction.
|
||||
browser1.gotoIndex(3);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 4, 4);
|
||||
|
||||
// Create a new hidden prerendered tab to swap to
|
||||
let tab3 = gBrowser.loadOneTab(URIs[4], {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab3.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSHistoryAndSwap(tab3.linkedBrowser.frameLoader);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 5, 5);
|
||||
|
||||
browser1.gotoIndex(0);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 5, 1);
|
||||
|
||||
browser1.gotoIndex(2);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 5, 3);
|
||||
|
||||
// Load a new page and make sure it throws out all of the following entries.
|
||||
URIs[3] = "data:text/html,NEW";
|
||||
browser1.loadURI(URIs[3]);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
await validate(browser1, 4, 4);
|
||||
|
||||
browser1.gotoIndex(0);
|
||||
await awaitProcessChange(browser1);
|
||||
await validate(browser1, 4, 1);
|
||||
|
||||
// XXX: This will be removed automatically by the owning tab closing in the
|
||||
// future, but this is not supported yet.
|
||||
gBrowser.removeTab(tab2);
|
||||
gBrowser.removeTab(tab3);
|
||||
});
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.0.250
|
||||
Current extension version is: 2.0.258
|
||||
|
||||
Taken from upstream commit: 6b2ed504
|
||||
Taken from upstream commit: 5a52ee0a
|
||||
|
@ -1936,7 +1936,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
||||
if (worker.destroyed) {
|
||||
return Promise.reject(new Error('Worker was destroyed'));
|
||||
}
|
||||
let apiVersion = '2.0.250';
|
||||
let apiVersion = '2.0.258';
|
||||
source.disableRange = (0, _dom_utils.getDefaultSetting)('disableRange');
|
||||
source.disableAutoFetch = (0, _dom_utils.getDefaultSetting)('disableAutoFetch');
|
||||
source.disableStream = (0, _dom_utils.getDefaultSetting)('disableStream');
|
||||
@ -2144,11 +2144,8 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
get view() {
|
||||
return this.pageInfo.view;
|
||||
},
|
||||
getViewport: function PDFPageProxy_getViewport(scale, rotate) {
|
||||
if (arguments.length < 2) {
|
||||
rotate = this.rotate;
|
||||
}
|
||||
return new _util.PageViewport(this.view, scale, rotate, 0, 0);
|
||||
getViewport(scale, rotate = this.rotate, dontFlip = false) {
|
||||
return new _util.PageViewport(this.view, scale, rotate, 0, 0, dontFlip);
|
||||
},
|
||||
getAnnotations: function PDFPageProxy_getAnnotations(params) {
|
||||
var intent = params && params.intent || null;
|
||||
@ -3233,8 +3230,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
|
||||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '2.0.250';
|
||||
exports.build = build = '6b2ed504';
|
||||
exports.version = version = '2.0.258';
|
||||
exports.build = build = '5a52ee0a';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
@ -4621,8 +4618,8 @@ exports.SVGGraphics = SVGGraphics;
|
||||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.250';
|
||||
var pdfjsBuild = '6b2ed504';
|
||||
var pdfjsVersion = '2.0.258';
|
||||
var pdfjsBuild = '5a52ee0a';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(0);
|
||||
var pdfjsDisplayGlobal = __w_pdfjs_require__(12);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(3);
|
||||
@ -7744,8 +7741,8 @@ if (!_global_scope2.default.PDFJS) {
|
||||
}
|
||||
var PDFJS = _global_scope2.default.PDFJS;
|
||||
{
|
||||
PDFJS.version = '2.0.250';
|
||||
PDFJS.build = '6b2ed504';
|
||||
PDFJS.version = '2.0.258';
|
||||
PDFJS.build = '5a52ee0a';
|
||||
}
|
||||
PDFJS.pdfBug = false;
|
||||
if (PDFJS.verbosity !== undefined) {
|
||||
|
123
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
123
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
@ -20784,8 +20784,8 @@ exports.PostScriptCompiler = PostScriptCompiler;
|
||||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.250';
|
||||
var pdfjsBuild = '6b2ed504';
|
||||
var pdfjsVersion = '2.0.258';
|
||||
var pdfjsBuild = '5a52ee0a';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(19);
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
||||
@ -20980,7 +20980,7 @@ var WorkerMessageHandler = {
|
||||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.0.250';
|
||||
let workerVersion = '2.0.258';
|
||||
if (apiVersion !== null && apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
@ -32533,6 +32533,10 @@ var Font = function FontClosure() {
|
||||
var header = file.peekBytes(4);
|
||||
return (0, _util.readUint32)(header, 0) === 0x00010000;
|
||||
}
|
||||
function isTrueTypeCollectionFile(file) {
|
||||
let header = file.peekBytes(4);
|
||||
return (0, _util.bytesToString)(header) === 'ttcf';
|
||||
}
|
||||
function isOpenTypeFile(file) {
|
||||
var header = file.peekBytes(4);
|
||||
return (0, _util.bytesToString)(header) === 'OTTO';
|
||||
@ -32941,6 +32945,29 @@ var Font = function FontClosure() {
|
||||
this.fontType = getFontType(type, subtype);
|
||||
},
|
||||
checkAndRepair: function Font_checkAndRepair(name, font, properties) {
|
||||
const VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
|
||||
function readTables(file, numTables) {
|
||||
let tables = Object.create(null);
|
||||
tables['OS/2'] = null;
|
||||
tables['cmap'] = null;
|
||||
tables['head'] = null;
|
||||
tables['hhea'] = null;
|
||||
tables['hmtx'] = null;
|
||||
tables['maxp'] = null;
|
||||
tables['name'] = null;
|
||||
tables['post'] = null;
|
||||
for (let i = 0; i < numTables; i++) {
|
||||
let table = readTableEntry(font);
|
||||
if (VALID_TABLES.indexOf(table.tag) < 0) {
|
||||
continue;
|
||||
}
|
||||
if (table.length === 0) {
|
||||
continue;
|
||||
}
|
||||
tables[table.tag] = table;
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
function readTableEntry(file) {
|
||||
var tag = (0, _util.bytesToString)(file.getBytes(4));
|
||||
var checksum = file.getInt32() >>> 0;
|
||||
@ -32972,6 +32999,58 @@ var Font = function FontClosure() {
|
||||
rangeShift: ttf.getUint16()
|
||||
};
|
||||
}
|
||||
function readTrueTypeCollectionHeader(ttc) {
|
||||
let ttcTag = (0, _util.bytesToString)(ttc.getBytes(4));
|
||||
(0, _util.assert)(ttcTag === 'ttcf', 'Must be a TrueType Collection font.');
|
||||
let majorVersion = ttc.getUint16();
|
||||
let minorVersion = ttc.getUint16();
|
||||
let numFonts = ttc.getInt32() >>> 0;
|
||||
let offsetTable = [];
|
||||
for (let i = 0; i < numFonts; i++) {
|
||||
offsetTable.push(ttc.getInt32() >>> 0);
|
||||
}
|
||||
let header = {
|
||||
ttcTag,
|
||||
majorVersion,
|
||||
minorVersion,
|
||||
numFonts,
|
||||
offsetTable
|
||||
};
|
||||
switch (majorVersion) {
|
||||
case 1:
|
||||
return header;
|
||||
case 2:
|
||||
header.dsigTag = ttc.getInt32() >>> 0;
|
||||
header.dsigLength = ttc.getInt32() >>> 0;
|
||||
header.dsigOffset = ttc.getInt32() >>> 0;
|
||||
return header;
|
||||
}
|
||||
throw new _util.FormatError(`Invalid TrueType Collection majorVersion: ${majorVersion}.`);
|
||||
}
|
||||
function readTrueTypeCollectionData(ttc, fontName) {
|
||||
let { numFonts, offsetTable } = readTrueTypeCollectionHeader(ttc);
|
||||
for (let i = 0; i < numFonts; i++) {
|
||||
ttc.pos = (ttc.start || 0) + offsetTable[i];
|
||||
let potentialHeader = readOpenTypeHeader(ttc);
|
||||
let potentialTables = readTables(ttc, potentialHeader.numTables);
|
||||
if (!potentialTables['name']) {
|
||||
throw new _util.FormatError('TrueType Collection font must contain a "name" table.');
|
||||
}
|
||||
let nameTable = readNameTable(potentialTables['name']);
|
||||
for (let j = 0, jj = nameTable.length; j < jj; j++) {
|
||||
for (let k = 0, kk = nameTable[j].length; k < kk; k++) {
|
||||
let nameEntry = nameTable[j][k];
|
||||
if (nameEntry && nameEntry.replace(/\s/g, '') === fontName) {
|
||||
return {
|
||||
header: potentialHeader,
|
||||
tables: potentialTables
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new _util.FormatError(`TrueType Collection does not contain "${fontName}" font.`);
|
||||
}
|
||||
function readCmapTable(cmap, font, isSymbolicFont, hasEncoding) {
|
||||
if (!cmap) {
|
||||
(0, _util.warn)('No cmap table available.');
|
||||
@ -33687,30 +33766,16 @@ var Font = function FontClosure() {
|
||||
return ttContext.hintsValid;
|
||||
}
|
||||
font = new _stream.Stream(new Uint8Array(font.getBytes()));
|
||||
var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
|
||||
var header = readOpenTypeHeader(font);
|
||||
var numTables = header.numTables;
|
||||
var cff, cffFile;
|
||||
var tables = Object.create(null);
|
||||
tables['OS/2'] = null;
|
||||
tables['cmap'] = null;
|
||||
tables['head'] = null;
|
||||
tables['hhea'] = null;
|
||||
tables['hmtx'] = null;
|
||||
tables['maxp'] = null;
|
||||
tables['name'] = null;
|
||||
tables['post'] = null;
|
||||
var table;
|
||||
for (var i = 0; i < numTables; i++) {
|
||||
table = readTableEntry(font);
|
||||
if (VALID_TABLES.indexOf(table.tag) < 0) {
|
||||
continue;
|
||||
}
|
||||
if (table.length === 0) {
|
||||
continue;
|
||||
}
|
||||
tables[table.tag] = table;
|
||||
let header, tables;
|
||||
if (isTrueTypeCollectionFile(font)) {
|
||||
let ttcData = readTrueTypeCollectionData(font, this.name);
|
||||
header = ttcData.header;
|
||||
tables = ttcData.tables;
|
||||
} else {
|
||||
header = readOpenTypeHeader(font);
|
||||
tables = readTables(font, header.numTables);
|
||||
}
|
||||
let cff, cffFile;
|
||||
var isTrueType = !tables['CFF '];
|
||||
if (!isTrueType) {
|
||||
if (header.version === 'OTTO' && !(properties.composite && properties.cidToGidMap) || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) {
|
||||
@ -33865,7 +33930,7 @@ var Font = function FontClosure() {
|
||||
unicodeOrCharCode = _encodings.MacRomanEncoding.indexOf(standardGlyphName);
|
||||
}
|
||||
var found = false;
|
||||
for (i = 0; i < cmapMappingsLength; ++i) {
|
||||
for (let i = 0; i < cmapMappingsLength; ++i) {
|
||||
if (cmapMappings[i].charCode !== unicodeOrCharCode) {
|
||||
continue;
|
||||
}
|
||||
@ -33884,11 +33949,11 @@ var Font = function FontClosure() {
|
||||
}
|
||||
}
|
||||
} else if (cmapPlatformId === 0 && cmapEncodingId === 0) {
|
||||
for (i = 0; i < cmapMappingsLength; ++i) {
|
||||
for (let i = 0; i < cmapMappingsLength; ++i) {
|
||||
charCodeToGlyphId[cmapMappings[i].charCode] = cmapMappings[i].glyphId;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < cmapMappingsLength; ++i) {
|
||||
for (let i = 0; i < cmapMappingsLength; ++i) {
|
||||
charCode = cmapMappings[i].charCode;
|
||||
if (cmapPlatformId === 3 && charCode >= 0xF000 && charCode <= 0xF0FF) {
|
||||
charCode &= 0xFF;
|
||||
|
@ -2305,6 +2305,7 @@ function webViewerKeyDown(evt) {
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
case 40:
|
||||
case 34:
|
||||
case 32:
|
||||
@ -2349,6 +2350,7 @@ function webViewerKeyDown(evt) {
|
||||
}
|
||||
if (cmd === 4) {
|
||||
switch (evt.keyCode) {
|
||||
case 13:
|
||||
case 32:
|
||||
if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== 'page-fit') {
|
||||
break;
|
||||
|
@ -1,81 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/PendingGlobalHistoryEntry.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
void
|
||||
PendingGlobalHistoryEntry::VisitURI(nsIURI* aURI,
|
||||
nsIURI* aLastVisitedURI,
|
||||
nsIURI* aReferrerURI,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
URIVisit visit;
|
||||
visit.mURI = aURI;
|
||||
visit.mLastVisitedURI = aLastVisitedURI;
|
||||
visit.mReferrerURI = aReferrerURI;
|
||||
visit.mFlags = aFlags;
|
||||
mVisits.AppendElement(Move(visit));
|
||||
}
|
||||
|
||||
void
|
||||
PendingGlobalHistoryEntry::SetURITitle(nsIURI* aURI,
|
||||
const nsAString& aTitle)
|
||||
{
|
||||
URITitle title;
|
||||
title.mURI = aURI;
|
||||
title.mTitle.Assign(aTitle);
|
||||
mTitles.AppendElement(title);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PendingGlobalHistoryEntry::ApplyChanges(IHistory* aHistory)
|
||||
{
|
||||
nsresult rv;
|
||||
for (const URIVisit& visit : mVisits) {
|
||||
rv = aHistory->VisitURI(visit.mURI, visit.mLastVisitedURI, visit.mFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mVisits.Clear();
|
||||
|
||||
for (const URITitle& title : mTitles) {
|
||||
rv = aHistory->SetURITitle(title.mURI, title.mTitle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mTitles.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PendingGlobalHistoryEntry::ApplyChanges(nsIGlobalHistory2* aHistory)
|
||||
{
|
||||
nsresult rv;
|
||||
for (const URIVisit& visit : mVisits) {
|
||||
bool redirect = (visit.mFlags & IHistory::REDIRECT_TEMPORARY) ||
|
||||
(visit.mFlags & IHistory::REDIRECT_PERMANENT);
|
||||
bool toplevel = (visit.mFlags & IHistory::TOP_LEVEL);
|
||||
|
||||
rv = aHistory->AddURI(visit.mURI, redirect, toplevel, visit.mReferrerURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mVisits.Clear();
|
||||
|
||||
for (const URITitle& title : mTitles) {
|
||||
rv = aHistory->SetPageTitle(title.mURI, title.mTitle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mTitles.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
@ -1,65 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PendingGlobalHistoryEntry_h_
|
||||
#define mozilla_dom_PendingGlobalHistoryEntry_h_
|
||||
|
||||
#include "mozilla/IHistory.h"
|
||||
#include "nsIGlobalHistory2.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
// This class acts as a wrapper around a IHistory, in that it can be used to
|
||||
// record a series of operations on the IHistory, and then play them back at a
|
||||
// later time. This is used in Prerendering in order to record the Global
|
||||
// History changes being made by the prerendering docshell and then play them
|
||||
// back when the docshell is finished rendering.
|
||||
//
|
||||
// This class also handles applying the changes to nsIGlobalHistory2.
|
||||
class PendingGlobalHistoryEntry
|
||||
{
|
||||
public:
|
||||
void VisitURI(nsIURI* aURI,
|
||||
nsIURI* aLastVisitedURI,
|
||||
nsIURI* aReferrerURI,
|
||||
uint32_t aFlags);
|
||||
|
||||
void SetURITitle(nsIURI* aURI,
|
||||
const nsAString& aTitle);
|
||||
|
||||
nsresult ApplyChanges(IHistory* aHistory);
|
||||
|
||||
nsresult ApplyChanges(nsIGlobalHistory2* aHistory);
|
||||
|
||||
private:
|
||||
struct URIVisit
|
||||
{
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mLastVisitedURI;
|
||||
nsCOMPtr<nsIURI> mReferrerURI;
|
||||
uint32_t mFlags = 0;
|
||||
};
|
||||
struct URITitle
|
||||
{
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsString mTitle;
|
||||
};
|
||||
nsTArray<URIVisit> mVisits;
|
||||
nsTArray<URITitle> mTitles;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PendingGlobalHistoryEntry_h_
|
||||
|
@ -80,10 +80,6 @@ EXPORTS.mozilla += [
|
||||
'LoadContext.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'PendingGlobalHistoryEntry.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'LoadContext.cpp',
|
||||
'nsAboutRedirector.cpp',
|
||||
@ -98,7 +94,6 @@ UNIFIED_SOURCES += [
|
||||
'nsPingListener.cpp',
|
||||
'nsRefreshTimer.cpp',
|
||||
'nsWebNavigationInfo.cpp',
|
||||
'PendingGlobalHistoryEntry.cpp',
|
||||
'SerializedLoadContext.cpp',
|
||||
]
|
||||
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||
#include "mozilla/dom/PendingGlobalHistoryEntry.h"
|
||||
#include "mozilla/dom/PerformanceNavigation.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
@ -367,7 +366,6 @@ nsDocShell::nsDocShell()
|
||||
, mIsOffScreenBrowser(false)
|
||||
, mIsActive(true)
|
||||
, mDisableMetaRefreshWhenInactive(false)
|
||||
, mIsPrerendered(false)
|
||||
, mIsAppTab(false)
|
||||
, mUseGlobalHistory(false)
|
||||
, mUseRemoteTabs(false)
|
||||
@ -1026,7 +1024,6 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
||||
srcdoc,
|
||||
sourceDocShell,
|
||||
baseURI,
|
||||
false,
|
||||
nullptr, // No nsIDocShell
|
||||
nullptr); // No nsIRequest
|
||||
}
|
||||
@ -2991,12 +2988,8 @@ nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
|
||||
}
|
||||
SetAllowContentRetargeting(mAllowContentRetargeting &&
|
||||
parentAsDocShell->GetAllowContentRetargetingOnChildren());
|
||||
if (parentAsDocShell->GetIsPrerendered()) {
|
||||
SetIsPrerendered();
|
||||
}
|
||||
if (NS_SUCCEEDED(parentAsDocShell->GetIsActive(&value))) {
|
||||
// a prerendered docshell is not active yet
|
||||
SetIsActive(value && !mIsPrerendered);
|
||||
SetIsActive(value);
|
||||
}
|
||||
if (NS_SUCCEEDED(parentAsDocShell->GetCustomUserAgent(customUserAgent)) &&
|
||||
!customUserAgent.IsEmpty()) {
|
||||
@ -5024,7 +5017,7 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
|
||||
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
|
||||
nullptr, VoidString(), nullptr, -1, nullptr,
|
||||
LOAD_ERROR_PAGE, nullptr, true, VoidString(), this,
|
||||
nullptr, false, nullptr, nullptr);
|
||||
nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5133,7 +5126,6 @@ nsDocShell::Reload(uint32_t aReloadFlags)
|
||||
srcdoc, // srcdoc argument for iframe
|
||||
this, // For reloads we are the source
|
||||
baseURI,
|
||||
false,
|
||||
nullptr, // No nsIDocShell
|
||||
nullptr); // No nsIRequest
|
||||
}
|
||||
@ -5846,21 +5838,6 @@ nsDocShell::SetIsActive(bool aIsActive)
|
||||
// Keep track ourselves.
|
||||
mIsActive = aIsActive;
|
||||
|
||||
// Clear prerender flag if necessary.
|
||||
if (mIsPrerendered && aIsActive) {
|
||||
MOZ_ASSERT(mPrerenderGlobalHistory.get());
|
||||
mIsPrerendered = false;
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
nsresult rv = NS_OK;
|
||||
if (history) {
|
||||
rv = mPrerenderGlobalHistory->ApplyChanges(history);
|
||||
} else if (mGlobalHistory) {
|
||||
rv = mPrerenderGlobalHistory->ApplyChanges(mGlobalHistory);
|
||||
}
|
||||
mPrerenderGlobalHistory = nullptr;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Tell the PresShell about it.
|
||||
nsCOMPtr<nsIPresShell> pshell = GetPresShell();
|
||||
if (pshell) {
|
||||
@ -5933,24 +5910,6 @@ nsDocShell::GetIsActive(bool* aIsActive)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetIsPrerendered()
|
||||
{
|
||||
MOZ_ASSERT(!mIsPrerendered,
|
||||
"SetIsPrerendered() called on already prerendered docshell");
|
||||
SetIsActive(false);
|
||||
mIsPrerendered = true;
|
||||
mPrerenderGlobalHistory = mozilla::MakeUnique<PendingGlobalHistoryEntry>();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetIsPrerendered(bool* aIsPrerendered)
|
||||
{
|
||||
*aIsPrerendered = mIsPrerendered;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetIsAppTab(bool aIsAppTab)
|
||||
{
|
||||
@ -8573,8 +8532,7 @@ nsDocShell::RestoreFromHistory()
|
||||
|
||||
// this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
|
||||
// the child inherits our state. Among other things, this means that the
|
||||
// child inherits our mIsActive, mIsPrerendered and mPrivateBrowsingId,
|
||||
// which is what we want.
|
||||
// child inherits our mIsActive mPrivateBrowsingId, which is what we want.
|
||||
AddChild(childItem);
|
||||
|
||||
childShell->SetAllowPlugins(allowPlugins);
|
||||
@ -9264,8 +9222,7 @@ public:
|
||||
bool aFirstParty,
|
||||
const nsAString& aSrcdoc,
|
||||
nsIDocShell* aSourceDocShell,
|
||||
nsIURI* aBaseURI,
|
||||
bool aCheckForPrerender)
|
||||
nsIURI* aBaseURI)
|
||||
: mozilla::Runnable("InternalLoadEvent")
|
||||
, mSrcdoc(aSrcdoc)
|
||||
, mDocShell(aDocShell)
|
||||
@ -9286,7 +9243,6 @@ public:
|
||||
, mFirstParty(aFirstParty)
|
||||
, mSourceDocShell(aSourceDocShell)
|
||||
, mBaseURI(aBaseURI)
|
||||
, mCheckForPrerender(aCheckForPrerender)
|
||||
{
|
||||
// Make sure to keep null things null as needed
|
||||
if (aTypeHint) {
|
||||
@ -9310,7 +9266,7 @@ public:
|
||||
VoidString(), mPostData, mPostDataLength,
|
||||
mHeadersData, mLoadType, mSHEntry,
|
||||
mFirstParty, mSrcdoc, mSourceDocShell,
|
||||
mBaseURI, mCheckForPrerender, nullptr,
|
||||
mBaseURI, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@ -9336,7 +9292,6 @@ private:
|
||||
bool mFirstParty;
|
||||
nsCOMPtr<nsIDocShell> mSourceDocShell;
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
bool mCheckForPrerender;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -9388,7 +9343,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
const nsAString& aSrcdoc,
|
||||
nsIDocShell* aSourceDocShell,
|
||||
nsIURI* aBaseURI,
|
||||
bool aCheckForPrerender,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest)
|
||||
{
|
||||
@ -9768,7 +9722,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
aSrcdoc,
|
||||
aSourceDocShell,
|
||||
aBaseURI,
|
||||
aCheckForPrerender,
|
||||
aDocShell,
|
||||
aRequest);
|
||||
if (rv == NS_ERROR_NO_CONTENT) {
|
||||
@ -9854,7 +9807,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
aTriggeringPrincipal, principalToInherit,
|
||||
aFlags, aTypeHint, aPostData, aPostDataLength,
|
||||
aHeadersData, aLoadType, aSHEntry, aFirstParty,
|
||||
aSrcdoc, aSourceDocShell, aBaseURI, false);
|
||||
aSrcdoc, aSourceDocShell, aBaseURI);
|
||||
return DispatchToTabGroup(TaskCategory::Other, ev.forget());
|
||||
}
|
||||
|
||||
@ -10233,25 +10186,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
}
|
||||
}
|
||||
|
||||
if (browserChrome3 && aCheckForPrerender) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
|
||||
aLoadReplace, aReferrer, aReferrerPolicy,
|
||||
aTriggeringPrincipal, principalToInherit,
|
||||
aFlags, aTypeHint, aPostData, aPostDataLength,
|
||||
aHeadersData, aLoadType, aSHEntry, aFirstParty,
|
||||
aSrcdoc, aSourceDocShell, aBaseURI, false);
|
||||
// We don't need any success handler since in that case
|
||||
// OnPartialSHistoryDeactive would be called, and it would ensure
|
||||
// docshell loads about:blank.
|
||||
bool shouldSwitch = false;
|
||||
rv = browserChrome3->ShouldSwitchToPrerenderedDocument(
|
||||
aURI, mCurrentURI, nullptr, ev, &shouldSwitch);
|
||||
if (NS_SUCCEEDED(rv) && shouldSwitch) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Whenever a top-level browsing context is navigated, the user agent MUST
|
||||
// lock the orientation of the document to the document's default
|
||||
// orientation. We don't explicitly check for a top-level browsing context
|
||||
@ -12478,7 +12412,6 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
|
||||
srcdoc,
|
||||
nullptr, // Source docshell, see comment above
|
||||
baseURI,
|
||||
false,
|
||||
nullptr, // No nsIDocShell
|
||||
nullptr); // No nsIRequest
|
||||
return rv;
|
||||
@ -12780,7 +12713,7 @@ nsDocShell::AddURIVisit(nsIURI* aURI,
|
||||
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
|
||||
if (mPrerenderGlobalHistory || history) {
|
||||
if (history) {
|
||||
uint32_t visitURIFlags = 0;
|
||||
|
||||
if (!IsFrame()) {
|
||||
@ -12810,14 +12743,7 @@ nsDocShell::AddURIVisit(nsIURI* aURI,
|
||||
visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
|
||||
}
|
||||
|
||||
if (mPrerenderGlobalHistory) {
|
||||
mPrerenderGlobalHistory->VisitURI(aURI,
|
||||
aPreviousURI,
|
||||
aReferrerURI,
|
||||
visitURIFlags);
|
||||
} else {
|
||||
(void)history->VisitURI(aURI, aPreviousURI, visitURIFlags);
|
||||
}
|
||||
(void)history->VisitURI(aURI, aPreviousURI, visitURIFlags);
|
||||
} else if (mGlobalHistory) {
|
||||
// Falls back to sync global history interface.
|
||||
(void)mGlobalHistory->AddURI(aURI,
|
||||
@ -13785,7 +13711,6 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||||
VoidString(), // No srcdoc
|
||||
this, // We are the source
|
||||
nullptr, // baseURI not needed
|
||||
true, // Check for prerendered doc
|
||||
aDocShell, // DocShell out-param
|
||||
aRequest); // Request out-param
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -14215,9 +14140,7 @@ nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI)
|
||||
{
|
||||
if (mUseGlobalHistory && !UsePrivateBrowsing()) {
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
if (mPrerenderGlobalHistory) {
|
||||
mPrerenderGlobalHistory->SetURITitle(aURI, mTitle);
|
||||
} else if (history) {
|
||||
if (history) {
|
||||
history->SetURITitle(aURI, mTitle);
|
||||
} else if (mGlobalHistory) {
|
||||
mGlobalHistory->SetPageTitle(aURI, nsString(mTitle));
|
||||
|
@ -71,7 +71,6 @@ namespace dom {
|
||||
class ClientInfo;
|
||||
class ClientSource;
|
||||
class EventTarget;
|
||||
class PendingGlobalHistoryEntry;
|
||||
typedef uint32_t ScreenOrientationInternal;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@ -911,7 +910,6 @@ private: // data members
|
||||
nsTObserverArray<nsWeakPtr> mReflowObservers;
|
||||
nsTObserverArray<nsWeakPtr> mScrollObservers;
|
||||
mozilla::OriginAttributes mOriginAttributes;
|
||||
mozilla::UniquePtr<mozilla::dom::PendingGlobalHistoryEntry> mPrerenderGlobalHistory;
|
||||
mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource;
|
||||
RefPtr<nsDOMNavigationTiming> mTiming;
|
||||
RefPtr<nsDSURIContentListener> mContentListener;
|
||||
@ -1113,7 +1111,6 @@ private: // data members
|
||||
bool mIsOffScreenBrowser : 1;
|
||||
bool mIsActive : 1;
|
||||
bool mDisableMetaRefreshWhenInactive : 1;
|
||||
bool mIsPrerendered : 1;
|
||||
bool mIsAppTab : 1;
|
||||
bool mUseGlobalHistory : 1;
|
||||
bool mUseRemoteTabs : 1;
|
||||
|
@ -219,7 +219,6 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
in AString aSrcdoc,
|
||||
in nsIDocShell aSourceDocShell,
|
||||
in nsIURI aBaseURI,
|
||||
in boolean aCheckForPrerender,
|
||||
out nsIDocShell aDocShell,
|
||||
out nsIRequest aRequest);
|
||||
|
||||
@ -677,17 +676,6 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
attribute boolean isActive;
|
||||
|
||||
/**
|
||||
* Puts the docshell in prerendering mode. noscript because we want only
|
||||
* native code to be able to put a docshell in prerendering.
|
||||
*/
|
||||
[noscript] void SetIsPrerendered();
|
||||
|
||||
/**
|
||||
* Whether this docshell is in prerender mode.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isPrerendered;
|
||||
|
||||
/**
|
||||
* The ID of the docshell in the session history.
|
||||
*/
|
||||
|
@ -6,9 +6,6 @@
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIBFCacheEntry.idl',
|
||||
'nsIGroupedSHistory.idl',
|
||||
'nsIPartialSHistory.idl',
|
||||
'nsIPartialSHistoryListener.idl',
|
||||
'nsISHContainer.idl',
|
||||
'nsISHEntry.idl',
|
||||
'nsISHistory.idl',
|
||||
|
@ -1,83 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFrameLoader;
|
||||
interface nsIPartialSHistory;
|
||||
|
||||
/**
|
||||
* nsIGroupedSHistory represent a combined session history across multiple
|
||||
* root docshells (usually browser tabs). The participating nsISHistory can
|
||||
* either be in chrome process or in content process, but nsIGroupedSHistory
|
||||
* itself lives in chrome process. The communication is proxyed through
|
||||
* nsIPartialSHistory.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(813e498d-73a8-449a-be09-6187e62c5352)]
|
||||
interface nsIGroupedSHistory : nsISupports
|
||||
{
|
||||
// The total number of entries of all its partial session histories.
|
||||
[infallible] readonly attribute unsigned long count;
|
||||
|
||||
/**
|
||||
* The currently active frameloader controlled by this nsIGroupedSHistory.
|
||||
*/
|
||||
readonly attribute nsIFrameLoader activeFrameLoader;
|
||||
|
||||
/**
|
||||
* Remove all partial histories after currently active one (if any) and then
|
||||
* append the given partial session history to the end of the list.
|
||||
*/
|
||||
void appendPartialSHistory(in nsIPartialSHistory aPartialHistory);
|
||||
|
||||
/**
|
||||
* Notify the grouped session history that the active partial session history
|
||||
* has been modified.
|
||||
*
|
||||
* @param aPartialHistory The partial history which was updated
|
||||
* @param aTruncate If this parameter is true, all partial session histories
|
||||
* after this one will be removed.
|
||||
*/
|
||||
void handleSHistoryUpdate(in nsIPartialSHistory aPartialHistory, in boolean aTruncate);
|
||||
|
||||
/**
|
||||
* Find the proper partial session history and navigate to the entry
|
||||
* corresponding to the given global index. Note it doesn't swap frameloaders,
|
||||
* but rather return the target loader for the caller to swap.
|
||||
*
|
||||
* This function may throw NS_ERROR_NOT_AVAILABLE if the frameloader to swap
|
||||
* to is dead.
|
||||
*
|
||||
* @param aGlobalIndex
|
||||
* The global index to navigate to.
|
||||
* @return The frameloader which needs to be swapped in, or null if no
|
||||
* frameloader needs to be swapped.
|
||||
*/
|
||||
nsIFrameLoader gotoIndex(in unsigned long aGlobalIndex);
|
||||
|
||||
/**
|
||||
* Close the FrameLoaderOwners of the inactive PartialSHistories in this GlobalSHistory.
|
||||
* This does not remove the PartialSHistories from the GroupedSHistory.
|
||||
*/
|
||||
void closeInactiveFrameLoaderOwners();
|
||||
|
||||
/**
|
||||
* Add a partialSHistory as a "prerendering" partialSHistory. This
|
||||
* partialSHistory's tab will have its lifetime managed by the
|
||||
* GroupedSHistory, and will be closed when closeInactiveFrameLoaderOwners is
|
||||
* called, or whenever a SHistory update is received.
|
||||
*/
|
||||
void addPrerenderingPartialSHistory(in nsIPartialSHistory aPrerendering, in long aId);
|
||||
|
||||
/**
|
||||
* Switch to the prerendering partialSHistory identified by aId, appending it after the current partialSHistory.
|
||||
*/
|
||||
[implicit_jscontext] nsISupports activatePrerendering(in long aId);
|
||||
|
||||
/**
|
||||
* Cancel the prerendering with the given ID.
|
||||
*/
|
||||
void cancelPrerendering(in long aId);
|
||||
};
|
@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIGroupedSHistory;
|
||||
interface nsIFrameLoader;
|
||||
|
||||
/**
|
||||
* nsIPartialSHistory represents a part of nsIGroupedSHistory. It associates to
|
||||
* a "partial" nsISHistory in either local or remote process.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(5cd75e28-838c-4a0a-972e-6005f736ef7a)]
|
||||
interface nsIPartialSHistory : nsISupports
|
||||
{
|
||||
// The number of entries of its corresponding nsISHistory.
|
||||
[infallible] readonly attribute unsigned long count;
|
||||
|
||||
// The current global index of the active shentry in this partialSHistory.
|
||||
[infallible] readonly attribute long globalIndex;
|
||||
|
||||
// If it's part of a grouped session history, globalIndexOffset denotes the
|
||||
// number of entries ahead.
|
||||
[infallible] readonly attribute unsigned long globalIndexOffset;
|
||||
|
||||
// The frameloader which owns this partial session history.
|
||||
readonly attribute nsIFrameLoader ownerFrameLoader;
|
||||
|
||||
// The groupedSHistory which this partialSHistory is a part of, or null.
|
||||
readonly attribute nsIGroupedSHistory groupedSHistory;
|
||||
|
||||
// The current state of the nsIPartialSHistory, whether it is active,
|
||||
// inactive, or currently prerendering.
|
||||
const long STATE_INACTIVE = 0;
|
||||
const long STATE_ACTIVE = 1;
|
||||
const long STATE_PRERENDER = 2;
|
||||
|
||||
[infallible] attribute long activeState;
|
||||
|
||||
/**
|
||||
* Notify that it's been added to a grouped session history. It also implies
|
||||
* it's becoming the active partial history of the group.
|
||||
*
|
||||
* @param aGroup The GroupedSHistory which this partialSHistory
|
||||
* is joining.
|
||||
*
|
||||
* @param aOffset The number of entries in preceding partial
|
||||
* session histories.
|
||||
*/
|
||||
void onAttachGroupedSHistory(in nsIGroupedSHistory aGroup, in unsigned long aOffset);
|
||||
|
||||
/**
|
||||
* This method is used by the TabParent to notify the PartialSHistory
|
||||
* that the state of its corresponding nsISHistory in the content process
|
||||
* has been updated. It is unused in the in-process case.
|
||||
*
|
||||
* @param aCount The number of entries in the associated session history.
|
||||
* @param aLocalIndex The local index of the currently active entry in the
|
||||
* associated session history
|
||||
*/
|
||||
void handleSHistoryUpdate(in unsigned long aCount, in unsigned long aLocalIndex, in boolean aTruncate);
|
||||
|
||||
/**
|
||||
* Notify that the partial session history has been swapped in as the active
|
||||
* session history. Only an active session history can possibly add / remove /
|
||||
* replace its history entries.
|
||||
*
|
||||
* @param aGlobalLength The up-to-date global length.
|
||||
* @param aTargetLocalIndex The local index to navigate to.
|
||||
*/
|
||||
void onActive(in unsigned long aGlobalLength, in unsigned long aTargetLocalIndex);
|
||||
|
||||
/**
|
||||
* Notify that the partial session history has been swapped out and is no
|
||||
* longer active.
|
||||
*/
|
||||
void onDeactive();
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Listener to handle cross partial nsISHistory navigation requests.
|
||||
*/
|
||||
[scriptable, uuid(be0cd2b6-6f03-4366-9fe2-184c914ff3df)]
|
||||
interface nsIPartialSHistoryListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called when the navigation target belongs to another nsISHistory within
|
||||
* the same nsIGroupedSHistory, and it needs to initiate cross nsISHistory
|
||||
* navigation.
|
||||
*
|
||||
* @param aIndex The index of complete history to navigate to.
|
||||
*/
|
||||
void onRequestCrossBrowserNavigation(in unsigned long aIndex);
|
||||
};
|
@ -8,7 +8,6 @@
|
||||
interface nsISHEntry;
|
||||
interface nsISHistoryListener;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIPartialSHistoryListener;
|
||||
|
||||
/**
|
||||
* An interface to the primary properties of the Session History
|
||||
@ -41,20 +40,6 @@ interface nsISHistory: nsISupports
|
||||
*/
|
||||
const long VIEWER_WINDOW = 3;
|
||||
|
||||
/**
|
||||
* An attribute denoting whether the nsISHistory is associated to a grouped
|
||||
* session history.
|
||||
*
|
||||
* The abstraction of grouped session history is implemented at
|
||||
* nsIWebNavigation level, so those canGoBack / canGoForward / gotoIndex
|
||||
* functions work transparently;
|
||||
*
|
||||
* On the other hand, nsISHistory works on partial session history directly.
|
||||
* Unless otherwise specified, count / index attributes and parameters all
|
||||
* indicate local count / index, so we won't mess up docshell.
|
||||
*/
|
||||
readonly attribute bool isPartial;
|
||||
|
||||
/**
|
||||
* A readonly property of the interface that returns
|
||||
* the number of toplevel documents currently available
|
||||
@ -62,30 +47,12 @@ interface nsISHistory: nsISupports
|
||||
*/
|
||||
readonly attribute long count;
|
||||
|
||||
/**
|
||||
* If isPartial, globalCount denotes the total number of entries in the
|
||||
* grouped session history; Otherwise it has the same value as count.
|
||||
*/
|
||||
readonly attribute long globalCount;
|
||||
|
||||
/**
|
||||
* A readonly property which represents the difference between global indices
|
||||
* of grouped session history and local indices of this particular session
|
||||
* history object.
|
||||
*/
|
||||
readonly attribute long globalIndexOffset;
|
||||
|
||||
/**
|
||||
* A readonly property of the interface that returns
|
||||
* the index of the current document in session history.
|
||||
*/
|
||||
readonly attribute long index;
|
||||
|
||||
/**
|
||||
* A readonly property which equals index + globalIndexOffset.
|
||||
*/
|
||||
readonly attribute long globalIndex;
|
||||
|
||||
/**
|
||||
* A readonly property of the interface that returns
|
||||
* the index of the last document that started to load and
|
||||
@ -173,12 +140,6 @@ interface nsISHistory: nsISupports
|
||||
*/
|
||||
void removeSHistoryListener(in nsISHistoryListener aListener);
|
||||
|
||||
/**
|
||||
* Set the listener to handle cross nsISHistory navigation when it works
|
||||
* in "partial" mode.
|
||||
*/
|
||||
void setPartialSHistoryListener(in nsIPartialSHistoryListener aListener);
|
||||
|
||||
/**
|
||||
* Called to obtain a enumerator for all the documents stored in
|
||||
* session history. The enumerator object thus returned by this method
|
||||
@ -215,28 +176,4 @@ interface nsISHistory: nsISupports
|
||||
* index for the given history entry.
|
||||
*/
|
||||
long getIndexOfEntry(in nsISHEntry aEntry);
|
||||
|
||||
/**
|
||||
* Called when this nsISHistory has became the active history of a grouped
|
||||
* session history.
|
||||
*
|
||||
* @param globalLength The up to date number of entries in the grouped
|
||||
* session history.
|
||||
* @param targetIndex The local index to navigate to.
|
||||
*/
|
||||
void onPartialSHistoryActive(in long globalLength, in long targetIndex);
|
||||
|
||||
/**
|
||||
* Called when this nsISHistory has became inactive history of a grouped
|
||||
* session history.
|
||||
*/
|
||||
void onPartialSHistoryDeactive();
|
||||
|
||||
/**
|
||||
* Called when it's attached to a nsIGroupedSHistory instance.
|
||||
*
|
||||
* @param offset The number of entries in the grouped session
|
||||
* history before this session history object.
|
||||
*/
|
||||
void onAttachGroupedSHistory(in long offset);
|
||||
};
|
||||
|
@ -235,10 +235,7 @@ nsSHistory::nsSHistory()
|
||||
: mIndex(-1)
|
||||
, mLength(0)
|
||||
, mRequestedIndex(-1)
|
||||
, mGlobalIndexOffset(0)
|
||||
, mEntriesInFollowingPartialHistories(0)
|
||||
, mRootDocShell(nullptr)
|
||||
, mIsPartial(false)
|
||||
{
|
||||
// Add this new SHistory object to the list
|
||||
gSHistoryList.insertBack(this);
|
||||
@ -666,10 +663,6 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist)
|
||||
NOTIFY_LISTENERS(OnLengthChanged, (mLength));
|
||||
NOTIFY_LISTENERS(OnIndexChanged, (mIndex));
|
||||
|
||||
// Much like how mLength works above, when changing our entries, all following
|
||||
// partial histories should be purged, so we just reset the number to zero.
|
||||
mEntriesInFollowingPartialHistories = 0;
|
||||
|
||||
// If this is the very first transaction, initialize the list
|
||||
if (!mListRoot) {
|
||||
mListRoot = txn;
|
||||
@ -683,14 +676,6 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetIsPartial(bool* aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mIsPartial;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Get size of the history list */
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetCount(int32_t* aResult)
|
||||
@ -700,60 +685,6 @@ nsSHistory::GetCount(int32_t* aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetGlobalCount(int32_t* aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mGlobalIndexOffset + mLength + mEntriesInFollowingPartialHistories;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetGlobalIndexOffset(int32_t* aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mGlobalIndexOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::OnPartialSHistoryActive(int32_t aGlobalLength, int32_t aTargetIndex)
|
||||
{
|
||||
NS_ENSURE_TRUE(mRootDocShell && mIsPartial, NS_ERROR_UNEXPECTED);
|
||||
|
||||
int32_t extraLength = aGlobalLength - mLength - mGlobalIndexOffset;
|
||||
NS_ENSURE_TRUE(extraLength >= 0, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (extraLength != mEntriesInFollowingPartialHistories) {
|
||||
mEntriesInFollowingPartialHistories = extraLength;
|
||||
}
|
||||
|
||||
return RestoreToEntryAtIndex(aTargetIndex);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::OnPartialSHistoryDeactive()
|
||||
{
|
||||
NS_ENSURE_TRUE(mRootDocShell && mIsPartial, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Ensure the deactive docshell loads about:blank.
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mRootDocShell);
|
||||
nsCOMPtr<nsIURI> currentURI;
|
||||
webNav->GetCurrentURI(getter_AddRefs(currentURI));
|
||||
if (NS_IsAboutBlank(currentURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// At this point we've swapped out to an invisble tab, and can not prompt here.
|
||||
// The check should have been done in nsDocShell::InternalLoad, so we'd
|
||||
// just force docshell to load about:blank.
|
||||
if (NS_FAILED(mRootDocShell->ForceCreateAboutBlankContentViewer(nullptr))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Get index of the history list */
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetIndex(int32_t* aResult)
|
||||
@ -763,14 +694,6 @@ nsSHistory::GetIndex(int32_t* aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetGlobalIndex(int32_t* aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult, "null out param?");
|
||||
*aResult = mIndex + mGlobalIndexOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Get the requestedIndex */
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GetRequestedIndex(int32_t* aResult)
|
||||
@ -1022,9 +945,6 @@ nsSHistory::PurgeHistory(int32_t aEntries)
|
||||
mLength -= cnt;
|
||||
mIndex -= cnt;
|
||||
|
||||
// All following partial histories will be deleted in this case.
|
||||
mEntriesInFollowingPartialHistories = 0;
|
||||
|
||||
// Now if we were not at the end of the history, mIndex could have
|
||||
// become far too negative. If so, just set it to -1.
|
||||
if (mIndex < -1) {
|
||||
@ -1068,13 +988,6 @@ nsSHistory::RemoveSHistoryListener(nsISHistoryListener* aListener)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::SetPartialSHistoryListener(nsIPartialSHistoryListener* aListener)
|
||||
{
|
||||
mPartialHistoryListener = do_GetWeakReference(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Replace an entry in the History list at a particular index.
|
||||
* Do not update index or count.
|
||||
*/
|
||||
@ -1153,11 +1066,6 @@ nsSHistory::GetCanGoBack(bool* aCanGoBack)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanGoBack);
|
||||
|
||||
if (mGlobalIndexOffset) {
|
||||
*aCanGoBack = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t index = -1;
|
||||
NS_ENSURE_SUCCESS(GetIndex(&index), NS_ERROR_FAILURE);
|
||||
if (index > 0) {
|
||||
@ -1174,11 +1082,6 @@ nsSHistory::GetCanGoForward(bool* aCanGoForward)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanGoForward);
|
||||
|
||||
if (mEntriesInFollowingPartialHistories) {
|
||||
*aCanGoForward = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t index = -1;
|
||||
int32_t count = -1;
|
||||
NS_ENSURE_SUCCESS(GetIndex(&index), NS_ERROR_FAILURE);
|
||||
@ -1771,7 +1674,6 @@ nsSHistory::RemoveDuplicate(int32_t aIndex, bool aKeepNext)
|
||||
mRequestedIndex = mRequestedIndex - 1;
|
||||
}
|
||||
--mLength;
|
||||
mEntriesInFollowingPartialHistories = 0;
|
||||
NOTIFY_LISTENERS(OnLengthChanged, (mLength));
|
||||
return true;
|
||||
}
|
||||
@ -1931,12 +1833,9 @@ nsSHistory::LoadURI(const char16_t* aURI,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::GotoIndex(int32_t aGlobalIndex)
|
||||
nsSHistory::GotoIndex(int32_t aIndex)
|
||||
{
|
||||
// We provide abstraction of grouped session history for nsIWebNavigation
|
||||
// functions, so the index passed in here is global index.
|
||||
return LoadEntry(aGlobalIndex - mGlobalIndexOffset, nsIDocShellLoadInfo::loadHistory,
|
||||
HIST_CMD_GOTOINDEX);
|
||||
return LoadEntry(aIndex, nsIDocShellLoadInfo::loadHistory, HIST_CMD_GOTOINDEX);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1963,50 +1862,35 @@ nsSHistory::LoadEntry(int32_t aIndex, long aLoadType, uint32_t aHistCmd)
|
||||
nsCOMPtr<nsIURI> nextURI;
|
||||
nsCOMPtr<nsISHEntry> prevEntry;
|
||||
nsCOMPtr<nsISHEntry> nextEntry;
|
||||
bool isCrossBrowserNavigation = false;
|
||||
if (aIndex < 0 || aIndex >= mLength) {
|
||||
if (aIndex + mGlobalIndexOffset < 0) {
|
||||
// The global index is negative.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aIndex - mLength >= mEntriesInFollowingPartialHistories) {
|
||||
// The global index exceeds max possible value.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// The global index is valid. Mark that we're going to navigate to another
|
||||
// partial history, but wait until we've notified all listeners before
|
||||
// actually do so.
|
||||
isCrossBrowserNavigation = true;
|
||||
} else {
|
||||
// This is a normal local history navigation.
|
||||
// Keep note of requested history index in mRequestedIndex.
|
||||
mRequestedIndex = aIndex;
|
||||
|
||||
GetEntryAtIndex(mIndex, false, getter_AddRefs(prevEntry));
|
||||
GetEntryAtIndex(mRequestedIndex, false, getter_AddRefs(nextEntry));
|
||||
if (!nextEntry || !prevEntry) {
|
||||
mRequestedIndex = -1;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Remember that this entry is getting loaded at this point in the sequence
|
||||
nsCOMPtr<nsISHEntryInternal> entryInternal = do_QueryInterface(nextEntry);
|
||||
|
||||
if (entryInternal) {
|
||||
entryInternal->SetLastTouched(++gTouchCounter);
|
||||
}
|
||||
|
||||
// Get the uri for the entry we are about to visit
|
||||
nextEntry->GetURI(getter_AddRefs(nextURI));
|
||||
// The index is out of range
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(isCrossBrowserNavigation || (prevEntry && nextEntry && nextURI),
|
||||
"prevEntry, nextEntry and nextURI can be null only if isCrossBrowserNavigation is set");
|
||||
// This is a normal local history navigation.
|
||||
// Keep note of requested history index in mRequestedIndex.
|
||||
mRequestedIndex = aIndex;
|
||||
|
||||
// Send appropriate listener notifications. Note nextURI could be null in case
|
||||
// of grouped session history navigation.
|
||||
GetEntryAtIndex(mIndex, false, getter_AddRefs(prevEntry));
|
||||
GetEntryAtIndex(mRequestedIndex, false, getter_AddRefs(nextEntry));
|
||||
if (!nextEntry || !prevEntry) {
|
||||
mRequestedIndex = -1;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Remember that this entry is getting loaded at this point in the sequence
|
||||
nsCOMPtr<nsISHEntryInternal> entryInternal = do_QueryInterface(nextEntry);
|
||||
|
||||
if (entryInternal) {
|
||||
entryInternal->SetLastTouched(++gTouchCounter);
|
||||
}
|
||||
|
||||
// Get the uri for the entry we are about to visit
|
||||
nextEntry->GetURI(getter_AddRefs(nextURI));
|
||||
|
||||
MOZ_ASSERT((prevEntry && nextEntry && nextURI), "prevEntry, nextEntry and nextURI can't be null");
|
||||
|
||||
// Send appropriate listener notifications.
|
||||
bool canNavigate = true;
|
||||
if (aHistCmd == HIST_CMD_BACK) {
|
||||
// We are going back one entry. Send GoBack notifications
|
||||
@ -2029,23 +1913,6 @@ nsSHistory::LoadEntry(int32_t aIndex, long aLoadType, uint32_t aHistCmd)
|
||||
return NS_OK; // XXX Maybe I can return some other error code?
|
||||
}
|
||||
|
||||
if (isCrossBrowserNavigation) {
|
||||
nsCOMPtr<nsIPartialSHistoryListener> listener =
|
||||
do_QueryReferent(mPartialHistoryListener);
|
||||
if (!listener) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// CreateAboutBlankContentViewer would check for permit unload, fire proper
|
||||
// pagehide / unload events and transfer content viewer ownership to SHEntry.
|
||||
if (NS_FAILED(mRootDocShell->CreateAboutBlankContentViewer(nullptr))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return listener->OnRequestCrossBrowserNavigation(aIndex +
|
||||
mGlobalIndexOffset);
|
||||
}
|
||||
|
||||
if (mRequestedIndex == mIndex) {
|
||||
// Possibly a reload case
|
||||
return InitiateLoad(nextEntry, mRootDocShell, aLoadType);
|
||||
@ -2236,25 +2103,6 @@ nsSHistory::GetSHistoryEnumerator(nsISimpleEnumerator** aEnumerator)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::OnAttachGroupedSHistory(int32_t aOffset)
|
||||
{
|
||||
NS_ENSURE_TRUE(!mIsPartial && mRootDocShell, NS_ERROR_UNEXPECTED);
|
||||
NS_ENSURE_TRUE(aOffset >= 0, NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
mIsPartial = true;
|
||||
mGlobalIndexOffset = aOffset;
|
||||
|
||||
// The last attached history is always at the end of the group.
|
||||
mEntriesInFollowingPartialHistories = 0;
|
||||
|
||||
// Setting grouped history info may change canGoBack / canGoForward.
|
||||
// Send a location change to update these values.
|
||||
mRootDocShell->DispatchLocationChangeEvent();
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
nsSHEnumerator::nsSHEnumerator(nsSHistory* aSHistory) : mIndex(-1)
|
||||
{
|
||||
mSHistory = aSHistory;
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
#include "nsIPartialSHistoryListener.h"
|
||||
#include "nsISHistory.h"
|
||||
#include "nsISHistoryInternal.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
@ -182,24 +181,12 @@ private:
|
||||
int32_t mLength;
|
||||
int32_t mRequestedIndex;
|
||||
|
||||
// The number of entries before this session history object.
|
||||
int32_t mGlobalIndexOffset;
|
||||
|
||||
// The number of entries after this session history object.
|
||||
int32_t mEntriesInFollowingPartialHistories;
|
||||
|
||||
// Session History listeners
|
||||
nsAutoTObserverArray<nsWeakPtr, 2> mListeners;
|
||||
|
||||
// Partial session history listener
|
||||
nsWeakPtr mPartialHistoryListener;
|
||||
|
||||
// Weak reference. Do not refcount this.
|
||||
nsIDocShell* mRootDocShell;
|
||||
|
||||
// Set to true if attached to a grouped session history.
|
||||
bool mIsPartial;
|
||||
|
||||
// Max viewers allowed total, across all SHistory objects
|
||||
static int32_t sHistoryMaxTotalViewers;
|
||||
};
|
||||
|
@ -106,11 +106,5 @@ skip-if = true # Bug 1220415
|
||||
[browser_timelineMarkers-04.js]
|
||||
[browser_timelineMarkers-05.js]
|
||||
[browser_ua_emulation.js]
|
||||
[browser_grouped_shistory_dead_navigate.js]
|
||||
skip-if = !e10s
|
||||
[browser_grouped_shistory_crossproc.js]
|
||||
skip-if = !e10s
|
||||
[browser_grouped_shistory_bfcache_cleaning.js]
|
||||
skip-if = !e10s
|
||||
[browser_history_triggeringprincipal_viewsource.js]
|
||||
[browser_click_link_within_view_source.js]
|
||||
|
@ -1,59 +0,0 @@
|
||||
add_task(async function() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true]]
|
||||
});
|
||||
|
||||
// Wait for a process change and then fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("BrowserChangedProcess", function(e) {
|
||||
ok(true, "The browser changed process!");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
function isAlive(tab) {
|
||||
return tab.linkedBrowser &&
|
||||
tab.linkedBrowser.frameLoader &&
|
||||
!tab.linkedBrowser.frameLoader.isDead;
|
||||
}
|
||||
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, async function(browser1) {
|
||||
// Set up the grouped SHEntry setup
|
||||
let tab2 = gBrowser.loadOneTab("data:text/html,b", {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
|
||||
await awaitProcessChange(browser1);
|
||||
ok(isAlive(tab2));
|
||||
|
||||
// Load some URIs and make sure that we lose the old process once we are 3 history entries away.
|
||||
browser1.loadURI("data:text/html,c", null, null);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
ok(isAlive(tab2), "frameloader should still be alive");
|
||||
browser1.loadURI("data:text/html,d", null, null);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
ok(isAlive(tab2), "frameloader should still be alive");
|
||||
browser1.loadURI("data:text/html,e", null, null);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
ok(isAlive(tab2), "frameloader should still be alive");
|
||||
|
||||
// The 4th navigation should kill the frameloader
|
||||
browser1.loadURI("data:text/html,f", null, null);
|
||||
await new Promise(resolve => {
|
||||
tab2.addEventListener("TabClose", function() {
|
||||
ok(true, "The tab is being closed!\n");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
// We don't check for !isAlive() as TabClose is called during
|
||||
// _beginRemoveTab, which means that the frameloader may not be dead yet. We
|
||||
// avoid races by not checking.
|
||||
});
|
||||
});
|
@ -1,52 +0,0 @@
|
||||
add_task(async function() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true]]
|
||||
});
|
||||
|
||||
// Wait for a process change and then fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("BrowserChangedProcess", function(e) {
|
||||
ok(true, "The browser changed process!");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for the given tab being closed.
|
||||
function awaitTabClose(tab) {
|
||||
return new Promise(resolve => {
|
||||
tab.addEventListener("TabClose", function() {
|
||||
ok(true, "The tab is being closed!\n");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, async function(browser1) {
|
||||
// Set up the grouped SHEntry setup
|
||||
let tab2 = gBrowser.loadOneTab("data:text/html,b", {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
|
||||
await awaitProcessChange(browser1);
|
||||
|
||||
// Load a URI which will involve loading in the parent process
|
||||
let tabClose = awaitTabClose(tab2);
|
||||
browser1.loadURI("about:config", Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
let docshell = browser1.frameLoader.docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
ok(docshell, "The browser should be loaded in the chrome process");
|
||||
is(docshell.canGoForward, false, "canGoForward is correct");
|
||||
is(docshell.canGoBack, true, "canGoBack is correct");
|
||||
is(docshell.sessionHistory.count, 3, "Count is correct");
|
||||
is(browser1.frameLoader.groupedSHistory, null,
|
||||
"browser1's session history is now complete");
|
||||
await tabClose;
|
||||
});
|
||||
});
|
@ -1,45 +0,0 @@
|
||||
add_task(async function() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true],
|
||||
["dom.ipc.processCount", 1]]
|
||||
});
|
||||
|
||||
// Wait for a process change and then fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("BrowserChangedProcess", function(e) {
|
||||
ok(true, "The browser changed process!");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, async function(browser1) {
|
||||
// Set up the grouped SHEntry setup
|
||||
let tab2 = gBrowser.loadOneTab("data:text/html,b", {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
|
||||
await awaitProcessChange(browser1);
|
||||
|
||||
// Close tab2 such that the back frameloader is dead
|
||||
await BrowserTestUtils.removeTab(tab2);
|
||||
await BrowserTestUtils.waitForCondition(() => browser1.canGoBack);
|
||||
browser1.goBack();
|
||||
await BrowserTestUtils.browserLoaded(browser1);
|
||||
await ContentTask.spawn(browser1, null, function() {
|
||||
is(content.window.location + "", "data:text/html,a");
|
||||
let webNav = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
is(webNav.canGoForward, true, "canGoForward is correct");
|
||||
is(webNav.canGoBack, false, "canGoBack is correct");
|
||||
});
|
||||
is(browser1.frameLoader.groupedSHistory, null,
|
||||
"browser1's session history is now complete");
|
||||
});
|
||||
});
|
@ -1,354 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GroupedSHistory.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "TabParent.h"
|
||||
#include "PartialSHistory.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(GroupedSHistory)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupedSHistory)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPartialHistories)
|
||||
tmp->mPrerenderingHistories.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupedSHistory)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPartialHistories)
|
||||
for (GroupedSHistory::PrerenderingHistory& h : tmp->mPrerenderingHistories) {
|
||||
ImplCycleCollectionTraverse(cb, h.mPartialHistory, "mPrerenderingHistories[i]->mPartialHistory", 0);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupedSHistory)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupedSHistory)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupedSHistory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGroupedSHistory)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGroupedSHistory)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
GroupedSHistory::GroupedSHistory()
|
||||
: mCount(0),
|
||||
mIndexOfActivePartialHistory(-1)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::GetCount(uint32_t* aResult)
|
||||
{
|
||||
MOZ_ASSERT(aResult);
|
||||
*aResult = mCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::AppendPartialSHistory(nsIPartialSHistory* aPartialHistory)
|
||||
{
|
||||
if (!aPartialHistory) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory(aPartialHistory);
|
||||
if (!partialHistory || mPartialHistories.Contains(partialHistory)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Remove all items after active one and deactive it, unless it's the first
|
||||
// call and no active partial history has been set yet.
|
||||
if (mIndexOfActivePartialHistory >= 0) {
|
||||
PurgePartialHistories(mIndexOfActivePartialHistory);
|
||||
nsCOMPtr<nsIPartialSHistory> prevPartialHistory =
|
||||
mPartialHistories[mIndexOfActivePartialHistory];
|
||||
if (NS_WARN_IF(!prevPartialHistory)) {
|
||||
// Cycle collected?
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
prevPartialHistory->OnDeactive();
|
||||
}
|
||||
|
||||
// Attach the partial history.
|
||||
uint32_t offset = mCount;
|
||||
mCount += partialHistory->GetCount();
|
||||
mPartialHistories.AppendElement(partialHistory);
|
||||
partialHistory->OnAttachGroupedSHistory(this, offset);
|
||||
mIndexOfActivePartialHistory = mPartialHistories.Count() - 1;
|
||||
|
||||
// Remove the prerendered documents, as there was a history navigation
|
||||
PurgePrerendering();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::HandleSHistoryUpdate(nsIPartialSHistory* aPartial, bool aTruncate)
|
||||
{
|
||||
if (!aPartial) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory = aPartial;
|
||||
|
||||
int32_t index = partialHistory->GetGlobalIndex();
|
||||
// Get the lower and upper bounds for the viewer window
|
||||
int32_t lower = index - nsISHistory::VIEWER_WINDOW;
|
||||
int32_t upper = index + nsISHistory::VIEWER_WINDOW;
|
||||
for (uint32_t i = 0; i < mPartialHistories.Length(); ++i) {
|
||||
nsIPartialSHistory* pHistory = mPartialHistories[i];
|
||||
// Skip the active partial history.
|
||||
if (pHistory == partialHistory) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the given partialshistory entry is too far away in history, and
|
||||
// if it is, close it.
|
||||
int32_t thisCount = pHistory->GetCount();
|
||||
int32_t thisOffset = pHistory->GetGlobalIndexOffset();
|
||||
if ((thisOffset > upper) || ((thisCount + thisOffset) < lower)) {
|
||||
nsCOMPtr<nsIFrameLoader> loader;
|
||||
pHistory->GetOwnerFrameLoader(getter_AddRefs(loader));
|
||||
if (loader && !loader->GetIsDead()) {
|
||||
loader->RequestFrameLoaderClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the prerendered documents, as there was a history navigation
|
||||
PurgePrerendering();
|
||||
|
||||
// If we should be truncating, make sure to purge any partialSHistories which
|
||||
// follow the one being updated.
|
||||
if (aTruncate) {
|
||||
int32_t index = mPartialHistories.IndexOf(partialHistory);
|
||||
if (NS_WARN_IF(index != mIndexOfActivePartialHistory) ||
|
||||
NS_WARN_IF(index < 0)) {
|
||||
// Non-active or not attached partialHistory
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
PurgePartialHistories(index);
|
||||
|
||||
// Update global count.
|
||||
uint32_t count = partialHistory->GetCount();
|
||||
uint32_t offset = partialHistory->GetGlobalIndexOffset();
|
||||
mCount = count + offset;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::GotoIndex(uint32_t aGlobalIndex,
|
||||
nsIFrameLoader** aTargetLoaderToSwap)
|
||||
{
|
||||
MOZ_ASSERT(aTargetLoaderToSwap);
|
||||
*aTargetLoaderToSwap = nullptr;
|
||||
|
||||
nsCOMPtr<nsIPartialSHistory> currentPartialHistory =
|
||||
mPartialHistories[mIndexOfActivePartialHistory];
|
||||
if (!currentPartialHistory) {
|
||||
// Cycle collected?
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mPartialHistories.Length(); i++) {
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory = mPartialHistories[i];
|
||||
if (NS_WARN_IF(!partialHistory)) {
|
||||
// Cycle collected?
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Examine index range.
|
||||
uint32_t offset = partialHistory->GetGlobalIndexOffset();
|
||||
uint32_t count = partialHistory->GetCount();
|
||||
if (offset <= aGlobalIndex && (offset + count) > aGlobalIndex) {
|
||||
uint32_t targetIndex = aGlobalIndex - offset;
|
||||
|
||||
// Check if we are trying to swap to a dead frameloader, and return
|
||||
// NS_ERROR_NOT_AVAILABLE if we are.
|
||||
nsCOMPtr<nsIFrameLoader> frameLoader;
|
||||
partialHistory->GetOwnerFrameLoader(getter_AddRefs(frameLoader));
|
||||
if (!frameLoader || frameLoader->GetIsDead()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if ((size_t)mIndexOfActivePartialHistory == i) {
|
||||
return NS_OK;
|
||||
}
|
||||
mIndexOfActivePartialHistory = i;
|
||||
if (NS_FAILED(currentPartialHistory->OnDeactive()) ||
|
||||
NS_FAILED(partialHistory->OnActive(mCount, targetIndex))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Return the target frameloader to the caller.
|
||||
frameLoader.forget(aTargetLoaderToSwap);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Index not found.
|
||||
NS_WARNING("Out of index request!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
GroupedSHistory::PurgePartialHistories(uint32_t aLastPartialIndexToKeep)
|
||||
{
|
||||
uint32_t lastIndex = mPartialHistories.Length() - 1;
|
||||
if (aLastPartialIndexToKeep >= lastIndex) {
|
||||
// Nothing to remove.
|
||||
return;
|
||||
}
|
||||
|
||||
// Close tabs.
|
||||
for (uint32_t i = lastIndex; i > aLastPartialIndexToKeep; i--) {
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory = mPartialHistories[i];
|
||||
if (!partialHistory) {
|
||||
// Cycle collected?
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> loader;
|
||||
partialHistory->GetOwnerFrameLoader(getter_AddRefs(loader));
|
||||
loader->RequestFrameLoaderClose();
|
||||
}
|
||||
|
||||
// Remove references.
|
||||
mPartialHistories.RemoveElementsAt(aLastPartialIndexToKeep + 1,
|
||||
lastIndex - aLastPartialIndexToKeep);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
GroupedSHistory::GroupedHistoryEnabled() {
|
||||
static bool sGroupedSHistoryEnabled = false;
|
||||
static bool sGroupedSHistoryPrefCached = false;
|
||||
if (!sGroupedSHistoryPrefCached) {
|
||||
sGroupedSHistoryPrefCached = true;
|
||||
Preferences::AddBoolVarCache(&sGroupedSHistoryEnabled,
|
||||
"browser.groupedhistory.enabled",
|
||||
false);
|
||||
}
|
||||
|
||||
return sGroupedSHistoryEnabled;
|
||||
}
|
||||
|
||||
void
|
||||
GroupedSHistory::PurgePrerendering()
|
||||
{
|
||||
nsTArray<PrerenderingHistory> histories = Move(mPrerenderingHistories);
|
||||
// Remove the frameloaders which are owned by the prerendering history, and
|
||||
// remove them from mPrerenderingHistories.
|
||||
for (uint32_t i = 0; i < histories.Length(); ++i) {
|
||||
nsCOMPtr<nsIFrameLoader> loader;
|
||||
histories[i].mPartialHistory->GetOwnerFrameLoader(getter_AddRefs(loader));
|
||||
if (loader) {
|
||||
loader->RequestFrameLoaderClose();
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(mPrerenderingHistories.IsEmpty());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::CloseInactiveFrameLoaderOwners()
|
||||
{
|
||||
MOZ_ASSERT(mIndexOfActivePartialHistory >= 0);
|
||||
// Remove inactive frameloaders which are participating in the grouped shistory
|
||||
for (uint32_t i = 0; i < mPartialHistories.Length(); ++i) {
|
||||
if (i != static_cast<uint32_t>(mIndexOfActivePartialHistory)) {
|
||||
nsCOMPtr<nsIFrameLoader> loader;
|
||||
mPartialHistories[i]->GetOwnerFrameLoader(getter_AddRefs(loader));
|
||||
loader->RequestFrameLoaderClose();
|
||||
}
|
||||
}
|
||||
|
||||
PurgePrerendering();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::AddPrerenderingPartialSHistory(nsIPartialSHistory* aPrerendering, int32_t aId)
|
||||
{
|
||||
NS_ENSURE_TRUE(aPrerendering && aId, NS_ERROR_UNEXPECTED);
|
||||
aPrerendering->SetActiveState(nsIPartialSHistory::STATE_PRERENDER);
|
||||
PrerenderingHistory history = { aPrerendering, aId };
|
||||
mPrerenderingHistories.AppendElement(history);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::GetActiveFrameLoader(nsIFrameLoader** aFrameLoader)
|
||||
{
|
||||
if (mIndexOfActivePartialHistory >= 0) {
|
||||
return mPartialHistories[mIndexOfActivePartialHistory]->GetOwnerFrameLoader(aFrameLoader);
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::ActivatePrerendering(int32_t aId, JSContext* aCx, nsISupports** aPromise)
|
||||
{
|
||||
NS_ENSURE_TRUE(aId && aCx && aPromise, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Look for an entry with the given aId in mPrerenderingHistories.
|
||||
for (uint32_t i = 0; i < mPrerenderingHistories.Length(); ++i) {
|
||||
if (mPrerenderingHistories[i].mId == aId) {
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory = mPrerenderingHistories[i].mPartialHistory;
|
||||
mPrerenderingHistories.RemoveElementAt(i);
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> fl;
|
||||
partialHistory->GetOwnerFrameLoader(getter_AddRefs(fl));
|
||||
NS_ENSURE_TRUE(fl, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> activeFl;
|
||||
GetActiveFrameLoader(getter_AddRefs(activeFl));
|
||||
NS_ENSURE_TRUE(activeFl, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = fl->MakePrerenderedLoaderActive();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return activeFl->AppendPartialSHistoryAndSwap(fl, aPromise);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a rejected promise as the entry was not found.
|
||||
nsCOMPtr<nsIGlobalObject> go = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
|
||||
if (NS_WARN_IF(!go)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Reject(go, aCx, JS::UndefinedHandleValue, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
promise.forget(aPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GroupedSHistory::CancelPrerendering(int32_t aId)
|
||||
{
|
||||
for (uint32_t i = 0; i < mPrerenderingHistories.Length(); ++i) {
|
||||
if (mPrerenderingHistories[i].mId == aId) {
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory = mPrerenderingHistories[i].mPartialHistory;
|
||||
nsCOMPtr<nsIFrameLoader> fl;
|
||||
partialHistory->GetOwnerFrameLoader(getter_AddRefs(fl));
|
||||
if (fl) {
|
||||
fl->RequestFrameLoaderClose();
|
||||
}
|
||||
mPrerenderingHistories.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -1,122 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GroupedSHistory_h
|
||||
#define GroupedSHistory_h
|
||||
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsIGroupedSHistory.h"
|
||||
#include "nsIPartialSHistory.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
||||
/**
|
||||
* GroupedSHistory connects session histories across multiple frameloaders.
|
||||
* Each frameloader has a PartialSHistory, and GroupedSHistory has an array
|
||||
* refering to all participating PartialSHistory(s).
|
||||
*
|
||||
* The following figure illustrates the idea. In this case, the GroupedSHistory
|
||||
* is composed of 3 frameloaders, and the active one is frameloader 1.
|
||||
* GroupedSHistory is always attached to the active frameloader.
|
||||
*
|
||||
* +----------------------------------------------------+
|
||||
* | |
|
||||
* | v
|
||||
* +------------------+ +-------------------+ +-----------------+
|
||||
* | FrameLoader 1 | | PartialSHistory 1 | | GroupedSHistory |
|
||||
* | (active) |----->| (active) |<--+---| |
|
||||
* +------------------+ +-------------------+ | +-----------------+
|
||||
* |
|
||||
* +------------------+ +-------------------+ |
|
||||
* | FrameLoader 2 | | PartialSHistory 2 | |
|
||||
* | (inactive) |----->| (inactive) |<--+
|
||||
* +------------------+ +-------------------+ |
|
||||
* |
|
||||
* +------------------+ +-------------------+ |
|
||||
* | FrameLoader 3 | | PartialSHistory 3 | |
|
||||
* | (inactive) |----->| (inactive) |<--+
|
||||
* +------------------+ +-------------------+
|
||||
*
|
||||
* If a history navigation leads to frameloader 3, it becomes the active one,
|
||||
* and GroupedSHistory is re-attached to frameloader 3.
|
||||
*
|
||||
* +------------------+ +-------------------+
|
||||
* | FrameLoader 1 | | PartialSHistory 1 |
|
||||
* | (inactive) |----->| (inactive) |<--+
|
||||
* +------------------+ +-------------------+ |
|
||||
* |
|
||||
* +------------------+ +-------------------+ |
|
||||
* | FrameLoader 2 | | PartialSHistory 2 | |
|
||||
* | (inactive) |----->| (inactive) |<--+
|
||||
* +------------------+ +-------------------+ |
|
||||
* |
|
||||
* +------------------+ +-------------------+ | +-----------------+
|
||||
* | FrameLoader 3 | | PartialSHistory 3 | | | GroupedSHistory |
|
||||
* | (active) |----->| (active) |<--+---| |
|
||||
* +------------------+ +-------------------+ +-----------------+
|
||||
* | ^
|
||||
* | |
|
||||
* +----------------------------------------------------+
|
||||
*/
|
||||
class GroupedSHistory final : public nsIGroupedSHistory
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(GroupedSHistory)
|
||||
NS_DECL_NSIGROUPEDSHISTORY
|
||||
GroupedSHistory();
|
||||
|
||||
/**
|
||||
* Get the value of preference "browser.groupedhistory.enabled" to determine
|
||||
* if grouped session history should be enabled.
|
||||
*/
|
||||
static bool GroupedHistoryEnabled();
|
||||
|
||||
private:
|
||||
~GroupedSHistory() {}
|
||||
|
||||
/**
|
||||
* Remove all partial histories and close tabs after the given index (of
|
||||
* mPartialHistories, not the index of session history entries).
|
||||
*/
|
||||
void PurgePartialHistories(uint32_t aLastPartialIndexToKeep);
|
||||
|
||||
/**
|
||||
* Remove the frameloaders which are owned by the prerendering history, and
|
||||
* remove them from mPrerenderingHistories.
|
||||
*/
|
||||
void PurgePrerendering();
|
||||
|
||||
// The total number of entries in all partial histories.
|
||||
uint32_t mCount;
|
||||
|
||||
// The index of currently active partial history in mPartialHistories.
|
||||
// Use int32_t as we have invalid index and nsCOMArray also uses int32_t.
|
||||
int32_t mIndexOfActivePartialHistory;
|
||||
|
||||
// All participating nsIPartialSHistory objects.
|
||||
nsCOMArray<nsIPartialSHistory> mPartialHistories;
|
||||
|
||||
// All nsIPartialSHistories which are being prerendered.
|
||||
struct PrerenderingHistory
|
||||
{
|
||||
nsCOMPtr<nsIPartialSHistory> mPartialHistory;
|
||||
int32_t mId;
|
||||
};
|
||||
nsTArray<PrerenderingHistory> mPrerenderingHistories;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GroupedSHistory_h */
|
@ -188,14 +188,6 @@ Link::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender()
|
||||
}
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::ePRERENDER) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri && mElement->OwnerDoc()) {
|
||||
mElement->OwnerDoc()->PrerenderHref(uri);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
if (nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
|
@ -1,359 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PartialSHistory.h"
|
||||
|
||||
#include "nsIWebNavigation.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(PartialSHistory, mOwnerFrameLoader, mGroupedSHistory)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PartialSHistory)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PartialSHistory)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PartialSHistory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIPartialSHistory)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPartialSHistory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISHistoryListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIPartialSHistoryListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
PartialSHistory::PartialSHistory(nsIFrameLoader* aOwnerFrameLoader)
|
||||
: mCount(0),
|
||||
mGlobalIndexOffset(0),
|
||||
mActive(nsIPartialSHistory::STATE_ACTIVE),
|
||||
mOwnerFrameLoader(aOwnerFrameLoader)
|
||||
{
|
||||
MOZ_ASSERT(aOwnerFrameLoader);
|
||||
}
|
||||
|
||||
already_AddRefed<nsISHistory>
|
||||
PartialSHistory::GetSessionHistory()
|
||||
{
|
||||
if (!mOwnerFrameLoader) {
|
||||
// Cycle collected?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
mOwnerFrameLoader->GetDocShell(getter_AddRefs(docShell));
|
||||
if (!docShell) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
|
||||
nsCOMPtr<nsISHistory> shistory;
|
||||
webNav->GetSessionHistory(getter_AddRefs(shistory));
|
||||
return shistory.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<TabParent>
|
||||
PartialSHistory::GetTabParent()
|
||||
{
|
||||
if (!mOwnerFrameLoader) {
|
||||
// Cycle collected?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITabParent> tabParent;
|
||||
mOwnerFrameLoader->GetTabParent(getter_AddRefs(tabParent));
|
||||
return RefPtr<TabParent>(static_cast<TabParent*>(tabParent.get())).forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::GetCount(uint32_t* aResult)
|
||||
{
|
||||
if (!aResult) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// If we have direct reference to nsISHistory, simply pass through.
|
||||
nsCOMPtr<nsISHistory> shistory(GetSessionHistory());
|
||||
if (shistory) {
|
||||
int32_t count;
|
||||
nsresult rv = shistory->GetCount(&count);
|
||||
if (NS_FAILED(rv) || count < 0) {
|
||||
*aResult = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aResult = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Otherwise use the cached value.
|
||||
*aResult = mCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::GetGlobalIndex(int32_t* aResult)
|
||||
{
|
||||
if (!aResult) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHistory> shistory = GetSessionHistory();
|
||||
if (shistory) {
|
||||
int32_t idx;
|
||||
nsresult rv = shistory->GetIndex(&idx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aResult = idx + GetGlobalIndexOffset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aResult = mIndex + GetGlobalIndexOffset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::GetGlobalIndexOffset(uint32_t* aResult)
|
||||
{
|
||||
if (!aResult) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// If we have direct reference to nsISHistory, simply pass through.
|
||||
nsCOMPtr<nsISHistory> shistory(GetSessionHistory());
|
||||
if (shistory) {
|
||||
int32_t offset;
|
||||
nsresult rv = shistory->GetGlobalIndexOffset(&offset);
|
||||
if (NS_FAILED(rv) || offset < 0) {
|
||||
*aResult = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aResult = offset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Otherwise use the cached value.
|
||||
*aResult = mGlobalIndexOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::GetOwnerFrameLoader(nsIFrameLoader** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIFrameLoader> loader(mOwnerFrameLoader);
|
||||
loader.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnAttachGroupedSHistory(nsIGroupedSHistory* aGroup, uint32_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(!mGroupedSHistory, "Only may join a single GroupedSHistory");
|
||||
|
||||
mActive = nsIPartialSHistory::STATE_ACTIVE;
|
||||
mGlobalIndexOffset = aOffset;
|
||||
mGroupedSHistory = aGroup;
|
||||
|
||||
// If we have direct reference to nsISHistory, simply pass through.
|
||||
nsCOMPtr<nsISHistory> shistory(GetSessionHistory());
|
||||
if (shistory) {
|
||||
// nsISHistory uses int32_t
|
||||
if (aOffset > INT32_MAX) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return shistory->OnAttachGroupedSHistory(aOffset);
|
||||
}
|
||||
|
||||
// Otherwise notify through TabParent.
|
||||
RefPtr<TabParent> tabParent(GetTabParent());
|
||||
if (!tabParent) {
|
||||
// We have neither shistory nor tabParent?
|
||||
NS_WARNING("Unable to get shitory nor tabParent!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
Unused << tabParent->SendNotifyAttachGroupedSHistory(aOffset);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::HandleSHistoryUpdate(uint32_t aCount, uint32_t aIndex, bool aTruncate)
|
||||
{
|
||||
// Update our local cache of mCount and mIndex
|
||||
mCount = aCount;
|
||||
mIndex = aIndex;
|
||||
return SHistoryDidUpdate(aTruncate);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PartialSHistory::SHistoryDidUpdate(bool aTruncate /* = false */)
|
||||
{
|
||||
if (!mOwnerFrameLoader) {
|
||||
// Cycle collected?
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!mGroupedSHistory) {
|
||||
// It's OK if we don't have a grouped history, that just means that we
|
||||
// aren't in a grouped shistory, so we don't need to do anything.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mGroupedSHistory->HandleSHistoryUpdate(this, aTruncate);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnActive(uint32_t aGlobalLength, uint32_t aTargetLocalIndex)
|
||||
{
|
||||
MOZ_ASSERT(mGroupedSHistory);
|
||||
|
||||
mActive = nsIPartialSHistory::STATE_ACTIVE;
|
||||
|
||||
// In-process case.
|
||||
nsCOMPtr<nsISHistory> shistory(GetSessionHistory());
|
||||
if (shistory) {
|
||||
// nsISHistory uses int32_t
|
||||
if (aGlobalLength > INT32_MAX || aTargetLocalIndex > INT32_MAX) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return shistory->OnPartialSHistoryActive(aGlobalLength, aTargetLocalIndex);
|
||||
}
|
||||
|
||||
// Cross-process case.
|
||||
RefPtr<TabParent> tabParent(GetTabParent());
|
||||
if (!tabParent) {
|
||||
// We have neither shistory nor tabParent?
|
||||
NS_WARNING("Unable to get shitory nor tabParent!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
Unused << tabParent->SendNotifyPartialSHistoryActive(aGlobalLength,
|
||||
aTargetLocalIndex);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnDeactive()
|
||||
{
|
||||
MOZ_ASSERT(mGroupedSHistory);
|
||||
|
||||
mActive = nsIPartialSHistory::STATE_INACTIVE;
|
||||
|
||||
// In-process case.
|
||||
nsCOMPtr<nsISHistory> shistory(GetSessionHistory());
|
||||
if (shistory) {
|
||||
if (NS_FAILED(shistory->OnPartialSHistoryDeactive())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cross-process case.
|
||||
RefPtr<TabParent> tabParent(GetTabParent());
|
||||
if (!tabParent) {
|
||||
// We have neither shistory nor tabParent?
|
||||
NS_WARNING("Unable to get shitory nor tabParent!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
Unused << tabParent->SendNotifyPartialSHistoryDeactive();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::GetActiveState(int32_t* aActive)
|
||||
{
|
||||
*aActive = mActive;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::SetActiveState(int32_t aActive)
|
||||
{
|
||||
mActive = aActive;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::GetGroupedSHistory(nsIGroupedSHistory** aGrouped)
|
||||
{
|
||||
nsCOMPtr<nsIGroupedSHistory> shistory = mGroupedSHistory;
|
||||
shistory.forget(aGrouped);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* nsIPartialSHistoryListener
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnRequestCrossBrowserNavigation(uint32_t aIndex)
|
||||
{
|
||||
if (!mOwnerFrameLoader) {
|
||||
// Cycle collected?
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
return mOwnerFrameLoader->RequestGroupedHistoryNavigation(aIndex, getter_AddRefs(promise));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* nsISHistoryListener
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnLengthChanged(int32_t aCount)
|
||||
{
|
||||
return SHistoryDidUpdate(/* aTruncate = */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnIndexChanged(int32_t aIndex)
|
||||
{
|
||||
return SHistoryDidUpdate(/* aTruncate = */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryNewEntry(nsIURI *aNewURI, int32_t aOldIndex)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryGoBack(nsIURI *aBackURI, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryGoForward(nsIURI *aForwardURI, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryReload(nsIURI *aReloadURI, uint32_t aReloadFlags, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryGotoIndex(int32_t aIndex, nsIURI *aGotoURI, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryPurge(int32_t aNumEntries, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PartialSHistory::OnHistoryReplaceEntry(int32_t aIndex)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -1,72 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef PartialSHistory_h
|
||||
#define PartialSHistory_h
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIGroupedSHistory.h"
|
||||
#include "nsIPartialSHistoryListener.h"
|
||||
#include "nsIPartialSHistory.h"
|
||||
#include "nsISHistory.h"
|
||||
#include "nsISHistoryListener.h"
|
||||
#include "TabParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PartialSHistory final : public nsIPartialSHistory,
|
||||
public nsISHistoryListener,
|
||||
public nsIPartialSHistoryListener,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PartialSHistory, nsIPartialSHistory)
|
||||
NS_DECL_NSIPARTIALSHISTORY
|
||||
NS_DECL_NSIPARTIALSHISTORYLISTENER
|
||||
NS_DECL_NSISHISTORYLISTENER
|
||||
|
||||
/**
|
||||
* Note that PartialSHistory must be constructed after frameloader has
|
||||
* created a valid docshell or tabparent.
|
||||
*/
|
||||
explicit PartialSHistory(nsIFrameLoader* aOwnerFrameLoader);
|
||||
|
||||
private:
|
||||
~PartialSHistory() {}
|
||||
already_AddRefed<nsISHistory> GetSessionHistory();
|
||||
already_AddRefed<TabParent> GetTabParent();
|
||||
|
||||
nsresult SHistoryDidUpdate(bool aTruncate = false);
|
||||
|
||||
// The cache of number of entries in corresponding nsISHistory. It's only
|
||||
// used for remote process case. If nsISHistory is in-process, mCount will not
|
||||
// be used at all.
|
||||
uint32_t mCount;
|
||||
|
||||
// The current local index of the active document in this partial SHistory.
|
||||
uint32_t mIndex;
|
||||
|
||||
// The cache of globalIndexOffset in corresponding nsISHistory. It's only
|
||||
// used for remote process case.
|
||||
uint32_t mGlobalIndexOffset;
|
||||
|
||||
// One of the possible active states from nsIPartialSHistory
|
||||
int32_t mActive;
|
||||
|
||||
// The frameloader which owns this PartialSHistory.
|
||||
nsCOMPtr<nsIFrameLoader> mOwnerFrameLoader;
|
||||
|
||||
// The GroupedSHistory which this PartialSHistory is part of, or null.
|
||||
nsCOMPtr<nsIGroupedSHistory> mGroupedSHistory;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* PartialSHistory_h */
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "RuleNodeCacheConditions.h"
|
||||
#include "nsGlobalWindowInner.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -185,7 +185,6 @@ EXPORTS.mozilla.dom += [
|
||||
'FormData.h',
|
||||
'FragmentOrElement.h',
|
||||
'FromParser.h',
|
||||
'GroupedSHistory.h',
|
||||
'IdleDeadline.h',
|
||||
'IdleRequest.h',
|
||||
'IDTracker.h',
|
||||
@ -199,7 +198,6 @@ EXPORTS.mozilla.dom += [
|
||||
'NodeInfo.h',
|
||||
'NodeInfoInlines.h',
|
||||
'NodeIterator.h',
|
||||
'PartialSHistory.h',
|
||||
'Pose.h',
|
||||
'ProcessGlobal.h',
|
||||
'ResponsiveImageSelector.h',
|
||||
@ -261,7 +259,6 @@ UNIFIED_SOURCES += [
|
||||
'EventSource.cpp',
|
||||
'FormData.cpp',
|
||||
'FragmentOrElement.cpp',
|
||||
'GroupedSHistory.cpp',
|
||||
'IdleDeadline.cpp',
|
||||
'IdleRequest.cpp',
|
||||
'IDTracker.cpp',
|
||||
@ -343,7 +340,6 @@ UNIFIED_SOURCES += [
|
||||
'nsXHTMLContentSerializer.cpp',
|
||||
'nsXMLContentSerializer.cpp',
|
||||
'nsXMLNameSpaceMap.cpp',
|
||||
'PartialSHistory.cpp',
|
||||
'Pose.cpp',
|
||||
'PostMessageEvent.cpp',
|
||||
'ProcessGlobal.cpp',
|
||||
|
@ -730,14 +730,6 @@ nsContentSink::ProcessLinkFromHeader(const nsAString& aAnchor, const nsAString&
|
||||
PrefetchPreloadHref(aHref, mDocument, linkTypes, aAs, aType, aMedia);
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::ePRERENDER) {
|
||||
nsCOMPtr<nsIURI> href;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(href), aHref);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mDocument->PrerenderHref(href);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aHref.IsEmpty() && (linkTypes & nsStyleLinkElement::eDNS_PREFETCH)) {
|
||||
PrefetchDNS(aHref);
|
||||
}
|
||||
|
@ -3323,78 +3323,6 @@ nsIDocument::IsScriptTracking(const nsACString& aURL) const
|
||||
return mTrackingScripts.Contains(aURL);
|
||||
}
|
||||
|
||||
bool
|
||||
nsIDocument::PrerenderHref(nsIURI* aHref)
|
||||
{
|
||||
MOZ_ASSERT(aHref);
|
||||
|
||||
static bool sPrerenderEnabled = false;
|
||||
static bool sPrerenderPrefCached = false;
|
||||
if (!sPrerenderPrefCached) {
|
||||
sPrerenderPrefCached = true;
|
||||
Preferences::AddBoolVarCache(&sPrerenderEnabled,
|
||||
"dom.linkPrerender.enabled",
|
||||
false);
|
||||
}
|
||||
|
||||
// Check if prerender is enabled
|
||||
if (!sPrerenderEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> referrer = GetDocumentURI();
|
||||
bool urisMatch = false;
|
||||
aHref->EqualsExceptRef(referrer, &urisMatch);
|
||||
if (urisMatch) {
|
||||
// Prerender current document isn't quite meaningful, and we may not be able
|
||||
// to load it out of process.
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = GetDocShell();
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
|
||||
NS_ENSURE_TRUE(webNav, false);
|
||||
|
||||
bool canGoForward = false;
|
||||
nsresult rv = webNav->GetCanGoForward(&canGoForward);
|
||||
if (NS_FAILED(rv) || canGoForward) {
|
||||
// Skip prerender on history navigation as we don't support it yet.
|
||||
// Remove this check once bug 1323650 is implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the document is in prerender state. We don't prerender in a
|
||||
// prerendered document.
|
||||
if (docShell->GetIsPrerendered()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We currently do not support prerendering in documents loaded within the
|
||||
// chrome process.
|
||||
if (!XRE_IsContentProcess()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adopting an prerendered document is similar to performing a load within a
|
||||
// different docshell, as the prerendering must have occurred in a different
|
||||
// docshell.
|
||||
if (!docShell->GetIsOnlyToplevelInTabGroup()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TabChild* tabChild = TabChild::GetFrom(docShell);
|
||||
NS_ENSURE_TRUE(tabChild, false);
|
||||
|
||||
nsCOMPtr<nsIWebBrowserChrome3> wbc3;
|
||||
tabChild->GetWebBrowserChrome(getter_AddRefs(wbc3));
|
||||
NS_ENSURE_TRUE(wbc3, false);
|
||||
|
||||
rv = wbc3->StartPrerenderingDocument(aHref, referrer, NodePrincipal());
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetApplicationCache(nsIApplicationCache **aApplicationCache)
|
||||
{
|
||||
@ -12355,13 +12283,6 @@ nsDocument::GetVisibilityState() const
|
||||
// Otherwise, we're visible.
|
||||
if (!IsVisible() || !mWindow || !mWindow->GetOuterWindow() ||
|
||||
mWindow->GetOuterWindow()->IsBackground()) {
|
||||
|
||||
// Check if the document is in prerender state.
|
||||
nsCOMPtr<nsIDocShell> docshell = GetDocShell();
|
||||
if (docshell && docshell->GetIsPrerendered()) {
|
||||
return dom::VisibilityState::Prerender;
|
||||
}
|
||||
|
||||
return dom::VisibilityState::Hidden;
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,6 @@
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsView.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "GroupedSHistory.h"
|
||||
#include "PartialSHistory.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
@ -97,9 +95,9 @@
|
||||
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
#include "mozilla/WebBrowserPersistLocalDocument.h"
|
||||
#include "mozilla/dom/GroupedHistoryEvent.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/dom/GroupedHistoryEvent.h"
|
||||
|
||||
#include "mozilla/dom/HTMLBodyElement.h"
|
||||
|
||||
@ -148,8 +146,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader,
|
||||
mDocShell,
|
||||
mMessageManager,
|
||||
mChildMessageManager,
|
||||
mOpener,
|
||||
mPartialSHistory)
|
||||
mOpener)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
|
||||
|
||||
@ -170,7 +167,6 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, nsPIDOMWindowOuter* aOpener,
|
||||
, mJSPluginID(aJSPluginID)
|
||||
, mEventMode(EVENT_MODE_NORMAL_DISPATCH)
|
||||
, mBrowserChangingProcessBlockers(nullptr)
|
||||
, mIsPrerendered(false)
|
||||
, mDepthTooGreat(false)
|
||||
, mIsTopLevelContent(false)
|
||||
, mDestroyCalled(false)
|
||||
@ -369,135 +365,6 @@ nsFrameLoader::LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::SetIsPrerendered(ErrorResult& aRv)
|
||||
{
|
||||
nsresult rv = SetIsPrerendered();
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::SetIsPrerendered()
|
||||
{
|
||||
MOZ_ASSERT(!mDocShell, "Please call SetIsPrerendered before docShell is created");
|
||||
mIsPrerendered = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::MakePrerenderedLoaderActive(ErrorResult& aRv)
|
||||
{
|
||||
nsresult rv = MakePrerenderedLoaderActive();
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::MakePrerenderedLoaderActive()
|
||||
{
|
||||
MOZ_ASSERT(mIsPrerendered, "This frameloader was not in prerendered mode.");
|
||||
|
||||
mIsPrerendered = false;
|
||||
if (IsRemoteFrame()) {
|
||||
if (!mRemoteBrowser) {
|
||||
NS_WARNING("Missing remote browser.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mRemoteBrowser->SetDocShellIsActive(true);
|
||||
} else {
|
||||
if (!mDocShell) {
|
||||
NS_WARNING("Missing docshell.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = mDocShell->SetIsActive(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPartialSHistory>
|
||||
nsFrameLoader::GetPartialSHistory()
|
||||
{
|
||||
nsCOMPtr<nsIPartialSHistory> partialSHistory;
|
||||
MOZ_ALWAYS_SUCCEEDS(GetPartialSHistory(getter_AddRefs(partialSHistory)));
|
||||
return partialSHistory.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::GetPartialSHistory(nsIPartialSHistory** aResult)
|
||||
{
|
||||
if (mRemoteBrowser && !mPartialSHistory) {
|
||||
// For remote case we can lazy initialize PartialSHistory since
|
||||
// it doens't need to be registered as a listener to nsISHistory directly.
|
||||
mPartialSHistory = new PartialSHistory(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory(mPartialSHistory);
|
||||
partialHistory.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIGroupedSHistory>
|
||||
nsFrameLoader::EnsureGroupedSHistory(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGroupedSHistory> result;
|
||||
nsresult rv = EnsureGroupedSHistory(getter_AddRefs(result));
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::EnsureGroupedSHistory(nsIGroupedSHistory** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory;
|
||||
GetPartialSHistory(getter_AddRefs(partialHistory));
|
||||
MOZ_ASSERT(partialHistory);
|
||||
|
||||
nsCOMPtr<nsIGroupedSHistory> groupedHistory;
|
||||
partialHistory->GetGroupedSHistory(getter_AddRefs(groupedHistory));
|
||||
if (!groupedHistory) {
|
||||
groupedHistory = new GroupedSHistory();
|
||||
groupedHistory->AppendPartialSHistory(partialHistory);
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIGroupedSHistory> test;
|
||||
GetGroupedSHistory(getter_AddRefs(test));
|
||||
MOZ_ASSERT(test == groupedHistory, "GroupedHistory must match");
|
||||
#endif
|
||||
}
|
||||
|
||||
groupedHistory.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIGroupedSHistory>
|
||||
nsFrameLoader::GetGroupedSHistory()
|
||||
{
|
||||
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
||||
MOZ_ALWAYS_SUCCEEDS(GetGroupedSHistory(getter_AddRefs(groupedSHistory)));
|
||||
return groupedSHistory.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::GetGroupedSHistory(nsIGroupedSHistory** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
||||
if (mPartialSHistory) {
|
||||
mPartialSHistory->GetGroupedSHistory(getter_AddRefs(groupedSHistory));
|
||||
}
|
||||
groupedSHistory.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::SwapBrowsersAndNotify(nsFrameLoader* aOther)
|
||||
{
|
||||
@ -535,193 +402,6 @@ nsFrameLoader::SwapBrowsersAndNotify(nsFrameLoader* aOther)
|
||||
return true;
|
||||
}
|
||||
|
||||
class AppendPartialSHistoryAndSwapHelper : public PromiseNativeHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(AppendPartialSHistoryAndSwapHelper)
|
||||
|
||||
AppendPartialSHistoryAndSwapHelper(nsFrameLoader* aThis,
|
||||
nsFrameLoader* aOther,
|
||||
Promise* aPromise)
|
||||
: mThis(aThis), mOther(aOther), mPromise(aPromise) {}
|
||||
|
||||
void
|
||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||
{
|
||||
nsCOMPtr<nsIGroupedSHistory> otherGroupedHistory;
|
||||
mOther->GetGroupedSHistory(getter_AddRefs(otherGroupedHistory));
|
||||
MOZ_ASSERT(!otherGroupedHistory,
|
||||
"Cannot append a GroupedSHistory owner to another.");
|
||||
if (otherGroupedHistory) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Append ourselves.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
||||
rv = mThis->EnsureGroupedSHistory(getter_AddRefs(groupedSHistory));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Append the other.
|
||||
nsCOMPtr<nsIPartialSHistory> otherPartialSHistory;
|
||||
MOZ_ALWAYS_SUCCEEDS(mOther->GetPartialSHistory(getter_AddRefs(otherPartialSHistory)));
|
||||
rv = groupedSHistory->AppendPartialSHistory(otherPartialSHistory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap the browsers and fire the BrowserChangedProcess event.
|
||||
if (mThis->SwapBrowsersAndNotify(mOther)) {
|
||||
mPromise->MaybeResolveWithUndefined();
|
||||
} else {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||
{
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
}
|
||||
|
||||
private:
|
||||
~AppendPartialSHistoryAndSwapHelper() {}
|
||||
RefPtr<nsFrameLoader> mThis;
|
||||
RefPtr<nsFrameLoader> mOther;
|
||||
RefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AppendPartialSHistoryAndSwapHelper)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AppendPartialSHistoryAndSwapHelper)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AppendPartialSHistoryAndSwapHelper)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTION(AppendPartialSHistoryAndSwapHelper,
|
||||
mThis, mPromise)
|
||||
|
||||
class RequestGroupedHistoryNavigationHelper : public PromiseNativeHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(RequestGroupedHistoryNavigationHelper)
|
||||
|
||||
RequestGroupedHistoryNavigationHelper(nsFrameLoader* aThis,
|
||||
uint32_t aGlobalIndex,
|
||||
Promise* aPromise)
|
||||
: mThis(aThis), mGlobalIndex(aGlobalIndex), mPromise(aPromise) {}
|
||||
|
||||
void
|
||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||
{
|
||||
if (NS_WARN_IF(!mThis->mOwnerContent)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
||||
mThis->GetGroupedSHistory(getter_AddRefs(groupedSHistory));
|
||||
if (NS_WARN_IF(!groupedSHistory)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Navigate the loader to the new index
|
||||
nsCOMPtr<nsIFrameLoader> otherLoader;
|
||||
nsresult rv = groupedSHistory->GotoIndex(mGlobalIndex, getter_AddRefs(otherLoader));
|
||||
|
||||
// Check if the gotoIndex failed because the target frameloader is dead. We
|
||||
// need to perform a navigateAndRestoreByIndex and then return to recover.
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
// Get the nsIXULBrowserWindow so that we can call NavigateAndRestoreByIndex on it.
|
||||
nsCOMPtr<nsIDocShell> docShell = mThis->mOwnerContent->OwnerDoc()->GetDocShell();
|
||||
if (NS_WARN_IF(!docShell)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
||||
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
||||
if (NS_WARN_IF(!treeOwner)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXULWindow> window = do_GetInterface(treeOwner);
|
||||
if (NS_WARN_IF(!window)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXULBrowserWindow> xbw;
|
||||
window->GetXULBrowserWindow(getter_AddRefs(xbw));
|
||||
if (NS_WARN_IF(!xbw)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBrowser> ourBrowser = do_QueryInterface(mThis->mOwnerContent);
|
||||
if (NS_WARN_IF(!ourBrowser)) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
rv = xbw->NavigateAndRestoreByIndex(ourBrowser, mGlobalIndex);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
mPromise->MaybeResolveWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for any other type of failure
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform the swap.
|
||||
nsFrameLoader* other = static_cast<nsFrameLoader*>(otherLoader.get());
|
||||
if (!other || other == mThis) {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap the browsers and fire the BrowserChangedProcess event.
|
||||
if (mThis->SwapBrowsersAndNotify(other)) {
|
||||
mPromise->MaybeResolveWithUndefined();
|
||||
} else {
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||
{
|
||||
mPromise->MaybeRejectWithUndefined();
|
||||
}
|
||||
|
||||
private:
|
||||
~RequestGroupedHistoryNavigationHelper() {}
|
||||
RefPtr<nsFrameLoader> mThis;
|
||||
uint32_t mGlobalIndex;
|
||||
RefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(RequestGroupedHistoryNavigationHelper)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(RequestGroupedHistoryNavigationHelper)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RequestGroupedHistoryNavigationHelper)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTION(RequestGroupedHistoryNavigationHelper,
|
||||
mThis, mPromise)
|
||||
|
||||
already_AddRefed<Promise>
|
||||
nsFrameLoader::FireWillChangeProcessEvent()
|
||||
{
|
||||
@ -758,94 +438,6 @@ nsFrameLoader::FireWillChangeProcessEvent()
|
||||
return allPromise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
nsFrameLoader::AppendPartialSHistoryAndSwap(nsIFrameLoader& aOther, ErrorResult& aRv)
|
||||
{
|
||||
nsresult rv = SetIsPrerendered();
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (&aOther == this) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsFrameLoader> otherLoader = static_cast<nsFrameLoader*>(&aOther);
|
||||
|
||||
RefPtr<Promise> ready = FireWillChangeProcessEvent();
|
||||
if (NS_WARN_IF(!ready)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This promise will be resolved when the swap has finished, we return it now
|
||||
// and pass it to our helper so our helper can resolve it.
|
||||
RefPtr<Promise> complete = Promise::Create(mOwnerContent->GetOwnerGlobal(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Attach our handler to the ready promise, and make it fulfil the complete
|
||||
// promise when we are done.
|
||||
RefPtr<AppendPartialSHistoryAndSwapHelper> helper =
|
||||
new AppendPartialSHistoryAndSwapHelper(this, otherLoader, complete);
|
||||
ready->AppendNativeHandler(helper);
|
||||
return complete.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::AppendPartialSHistoryAndSwap(nsIFrameLoader* aOther, nsISupports** aPromise)
|
||||
{
|
||||
if (!aOther) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> complete = AppendPartialSHistoryAndSwap(*aOther, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
complete.forget(aPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
nsFrameLoader::RequestGroupedHistoryNavigation(uint32_t aGlobalIndex, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<Promise> ready = FireWillChangeProcessEvent();
|
||||
if (NS_WARN_IF(!ready)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This promise will be resolved when the swap has finished, we return it now
|
||||
// and pass it to our helper so our helper can resolve it.
|
||||
RefPtr<Promise> complete = Promise::Create(mOwnerContent->GetOwnerGlobal(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Attach our handler to the ready promise, and make it fulfil the complete
|
||||
// promise when we are done.
|
||||
RefPtr<RequestGroupedHistoryNavigationHelper> helper =
|
||||
new RequestGroupedHistoryNavigationHelper(this, aGlobalIndex, complete);
|
||||
ready->AppendNativeHandler(helper);
|
||||
return complete.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::RequestGroupedHistoryNavigation(uint32_t aGlobalIndex, nsISupports** aPromise)
|
||||
{
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> complete = RequestGroupedHistoryNavigation(aGlobalIndex, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
complete.forget(aPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::AddProcessChangeBlockingPromise(Promise& aPromise, ErrorResult& aRv)
|
||||
{
|
||||
@ -2222,19 +1814,6 @@ nsFrameLoader::StartDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the other frame loader owners now that we are being destroyed.
|
||||
if (mPartialSHistory &&
|
||||
mPartialSHistory->GetActiveState() == nsIPartialSHistory::STATE_ACTIVE) {
|
||||
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
||||
GetGroupedSHistory(getter_AddRefs(groupedSHistory));
|
||||
if (groupedSHistory) {
|
||||
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
|
||||
"nsFrameLoader::StartDestroy", [groupedSHistory]() {
|
||||
groupedSHistory->CloseInactiveFrameLoaderOwners();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> destroyRunnable = new nsFrameLoaderDestroyRunnable(this);
|
||||
if (mNeedsAsyncDestroy || !doc ||
|
||||
NS_FAILED(doc->FinalizeFrameLoader(this, destroyRunnable))) {
|
||||
@ -2517,11 +2096,6 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
if (mIsPrerendered) {
|
||||
nsresult rv = mDocShell->SetIsPrerendered();
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
|
||||
if (!mNetworkCreated) {
|
||||
if (mDocShell) {
|
||||
mDocShell->SetCreatedDynamically(true);
|
||||
@ -2626,15 +2200,6 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
|
||||
webNav->SetSessionHistory(sessionHistory);
|
||||
|
||||
|
||||
if (GroupedSHistory::GroupedHistoryEnabled()) {
|
||||
mPartialSHistory = new PartialSHistory(this);
|
||||
nsCOMPtr<nsISHistoryListener> listener(do_QueryInterface(mPartialSHistory));
|
||||
nsCOMPtr<nsIPartialSHistoryListener> partialListener(do_QueryInterface(mPartialSHistory));
|
||||
sessionHistory->AddSHistoryListener(listener);
|
||||
sessionHistory->SetPartialSHistoryListener(partialListener);
|
||||
}
|
||||
}
|
||||
|
||||
OriginAttributes attrs;
|
||||
@ -4046,7 +3611,6 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
|
||||
bool tabContextUpdated =
|
||||
aTabContext->SetTabContext(OwnerIsMozBrowserFrame(),
|
||||
mIsPrerendered,
|
||||
showAccelerators,
|
||||
showFocusRings,
|
||||
attrs,
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "Units.h"
|
||||
#include "nsIWebBrowserPersistable.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIGroupedSHistory.h"
|
||||
#include "nsPluginTags.h"
|
||||
|
||||
class nsIURI;
|
||||
@ -74,8 +73,6 @@ class nsFrameLoader final : public nsIFrameLoader,
|
||||
{
|
||||
friend class AutoResetInShow;
|
||||
friend class AutoResetInFrameSwap;
|
||||
friend class AppendPartialSHistoryAndSwapHelper;
|
||||
friend class RequestGroupedHistoryNavigationHelper;
|
||||
typedef mozilla::dom::PBrowserParent PBrowserParent;
|
||||
typedef mozilla::dom::TabParent TabParent;
|
||||
typedef mozilla::layout::RenderFrameParent RenderFrameParent;
|
||||
@ -124,16 +121,6 @@ public:
|
||||
nsresult LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal,
|
||||
bool aOriginalSrc);
|
||||
|
||||
void SetIsPrerendered(mozilla::ErrorResult& aRv);
|
||||
|
||||
void MakePrerenderedLoaderActive(mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise>
|
||||
AppendPartialSHistoryAndSwap(nsIFrameLoader& aOther, mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise>
|
||||
RequestGroupedHistoryNavigation(uint32_t aGlobalIndex, mozilla::ErrorResult& aRv);
|
||||
|
||||
void AddProcessChangeBlockingPromise(mozilla::dom::Promise& aPromise, mozilla::ErrorResult& aRv);
|
||||
|
||||
void Destroy(mozilla::ErrorResult& aRv);
|
||||
@ -173,8 +160,6 @@ public:
|
||||
nsIWebProgressListener* aProgressListener,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsIGroupedSHistory> EnsureGroupedSHistory(mozilla::ErrorResult& aRv);
|
||||
|
||||
void StartPersistence(uint64_t aOuterWindowID,
|
||||
nsIWebBrowserPersistDocumentReceiver* aRecv,
|
||||
mozilla::ErrorResult& aRv);
|
||||
@ -191,10 +176,6 @@ public:
|
||||
|
||||
uint32_t LazyHeight() const;
|
||||
|
||||
already_AddRefed<nsIPartialSHistory> GetPartialSHistory();
|
||||
|
||||
already_AddRefed<nsIGroupedSHistory> GetGroupedSHistory();
|
||||
|
||||
uint64_t ChildID() const { return mChildID; }
|
||||
|
||||
bool ClampScrollPosition() const { return mClampScrollPosition; }
|
||||
@ -485,13 +466,10 @@ private:
|
||||
// Holds the last known size of the frame.
|
||||
mozilla::ScreenIntSize mLazySize;
|
||||
|
||||
nsCOMPtr<nsIPartialSHistory> mPartialSHistory;
|
||||
|
||||
// A stack-maintained reference to an array of promises which are blocking
|
||||
// grouped history navigation
|
||||
nsTArray<RefPtr<mozilla::dom::Promise>>* mBrowserChangingProcessBlockers;
|
||||
|
||||
bool mIsPrerendered : 1;
|
||||
bool mDepthTooGreat : 1;
|
||||
bool mIsTopLevelContent : 1;
|
||||
bool mDestroyCalled : 1;
|
||||
|
@ -1129,7 +1129,6 @@ GK_ATOM(precedingSibling, "preceding-sibling")
|
||||
GK_ATOM(predicate, "predicate")
|
||||
GK_ATOM(prefix, "prefix")
|
||||
GK_ATOM(preload, "preload")
|
||||
GK_ATOM(prerendered, "prerendered")
|
||||
GK_ATOM(mozpresentation, "mozpresentation")
|
||||
GK_ATOM(preserve, "preserve")
|
||||
GK_ATOM(preserveSpace, "preserve-space")
|
||||
|
@ -7570,13 +7570,6 @@ nsGlobalWindowInner::CreateNamedPropertiesObject(JSContext *aCx,
|
||||
return WindowNamedPropertiesHandler::Create(aCx, aProto);
|
||||
}
|
||||
|
||||
bool
|
||||
nsGlobalWindowInner::GetIsPrerendered()
|
||||
{
|
||||
nsIDocShell* docShell = GetDocShell();
|
||||
return docShell && docShell->GetIsPrerendered();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::RedefineProperty(JSContext* aCx, const char* aPropName,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
|
@ -1166,8 +1166,6 @@ public:
|
||||
|
||||
void FireOfflineStatusEventIfChanged();
|
||||
|
||||
bool GetIsPrerendered();
|
||||
|
||||
public:
|
||||
// Inner windows only.
|
||||
nsresult ScheduleNextIdleObserverCallback();
|
||||
|
@ -7601,13 +7601,6 @@ nsGlobalWindowOuter::Orientation(CallerType aCallerType) const
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
nsGlobalWindowOuter::GetIsPrerendered()
|
||||
{
|
||||
nsIDocShell* docShell = GetDocShell();
|
||||
return docShell && docShell->GetIsPrerendered();
|
||||
}
|
||||
|
||||
void
|
||||
nsPIDOMWindowOuter::SetLargeAllocStatus(LargeAllocStatus aStatus)
|
||||
{
|
||||
|
@ -908,8 +908,6 @@ public:
|
||||
const nsAString &aPopupWindowName,
|
||||
const nsAString &aPopupWindowFeatures);
|
||||
|
||||
bool GetIsPrerendered();
|
||||
|
||||
private:
|
||||
void ReportLargeAllocStatus();
|
||||
|
||||
|
@ -78,7 +78,7 @@ nsHistory::GetLength(ErrorResult& aRv) const
|
||||
}
|
||||
|
||||
int32_t len;
|
||||
nsresult rv = sHistory->GetGlobalCount(&len);
|
||||
nsresult rv = sHistory->GetCount(&len);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
@ -210,8 +210,8 @@ nsHistory::Go(int32_t aDelta, ErrorResult& aRv)
|
||||
|
||||
int32_t curIndex = -1;
|
||||
int32_t len = 0;
|
||||
session_history->GetGlobalIndex(&curIndex);
|
||||
session_history->GetGlobalCount(&len);
|
||||
session_history->GetIndex(&curIndex);
|
||||
session_history->GetCount(&len);
|
||||
|
||||
int32_t index = curIndex + aDelta;
|
||||
if (index > -1 && index < len)
|
||||
|
@ -3118,8 +3118,6 @@ public:
|
||||
void NoteScriptTrackingStatus(const nsACString& aURL, bool isTracking);
|
||||
bool IsScriptTracking(const nsACString& aURL) const;
|
||||
|
||||
bool PrerenderHref(nsIURI* aHref);
|
||||
|
||||
// For more information on Flash classification, see
|
||||
// toolkit/components/url-classifier/flash-block-lists.rst
|
||||
virtual mozilla::dom::FlashClassification DocumentFlashClassification() = 0;
|
||||
|
@ -17,8 +17,6 @@ interface nsITabParent;
|
||||
interface nsILoadContext;
|
||||
interface nsIPrintSettings;
|
||||
interface nsIWebProgressListener;
|
||||
interface nsIGroupedSHistory;
|
||||
interface nsIPartialSHistory;
|
||||
|
||||
[builtinclass, uuid(1645af04-1bc7-4363-8f2c-eb9679220ab1)]
|
||||
interface nsIFrameLoader : nsISupports
|
||||
@ -53,31 +51,6 @@ interface nsIFrameLoader : nsISupports
|
||||
*/
|
||||
void loadURI(in nsIURI aURI, in boolean originalSrc);
|
||||
|
||||
/**
|
||||
* Puts the frameloader in prerendering mode.
|
||||
*/
|
||||
void setIsPrerendered();
|
||||
|
||||
/**
|
||||
* Make the prerendered frameloader being active (and clear isPrerendered flag).
|
||||
*/
|
||||
void makePrerenderedLoaderActive();
|
||||
|
||||
/**
|
||||
* Append partial session history from another frame loader.
|
||||
*
|
||||
* @return A promise which will be resolved when the navigation is complete.
|
||||
*/
|
||||
nsISupports appendPartialSHistoryAndSwap(in nsIFrameLoader aOther);
|
||||
|
||||
/**
|
||||
* If grouped session history is applied, use this function to navigate to
|
||||
* an entry of session history object of another frameloader.
|
||||
*
|
||||
* @return A promise which will be resolved when the navigation is complete.
|
||||
*/
|
||||
nsISupports requestGroupedHistoryNavigation(in unsigned long aGlobalIndex);
|
||||
|
||||
/**
|
||||
* Adds a blocking promise for the current cross process navigation.
|
||||
* This method can only be called while the "BrowserWillChangeProcess" event
|
||||
@ -170,11 +143,6 @@ interface nsIFrameLoader : nsISupports
|
||||
in nsIPrintSettings aPrintSettings,
|
||||
in nsIWebProgressListener aProgressListener);
|
||||
|
||||
/**
|
||||
* Ensure that the current nsIFrameLoader has a GroupedSHistory.
|
||||
*/
|
||||
nsIGroupedSHistory ensureGroupedSHistory();
|
||||
|
||||
/**
|
||||
* The default event mode automatically forwards the events
|
||||
* handled in EventStateManager::HandleCrossProcessEvent to
|
||||
@ -244,17 +212,6 @@ interface nsIFrameLoader : nsISupports
|
||||
*/
|
||||
readonly attribute unsigned long lazyHeight;
|
||||
|
||||
/**
|
||||
* The partial session history.
|
||||
*/
|
||||
readonly attribute nsIPartialSHistory partialSHistory;
|
||||
|
||||
/**
|
||||
* The grouped session history composed of multiple session history objects
|
||||
* across root docshells.
|
||||
*/
|
||||
readonly attribute nsIGroupedSHistory groupedSHistory;
|
||||
|
||||
/**
|
||||
* Is `true` if the frameloader is dead (destroy has been called on it)
|
||||
*/
|
||||
@ -276,11 +233,6 @@ interface nsIFrameLoaderOwner : nsISupports
|
||||
[binaryname(FrameLoaderXPCOM)] readonly attribute nsIFrameLoader frameLoader;
|
||||
[noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader();
|
||||
|
||||
/**
|
||||
* Puts the FrameLoaderOwner in prerendering mode.
|
||||
*/
|
||||
void setIsPrerendered();
|
||||
|
||||
/**
|
||||
* This method is used internally by SwapFrameLoaders to set the frame loader
|
||||
* on the target nsFrameLoader.
|
||||
|
@ -1146,12 +1146,6 @@ nsObjectLoadingContent::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, mozilla:
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::SetIsPrerendered()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::InternalSetFrameLoader(nsIFrameLoader* aNewFrameLoader)
|
||||
{
|
||||
|
@ -152,8 +152,6 @@ static uint32_t ToLinkMask(const nsAString& aLink)
|
||||
return nsStyleLinkElement::ePRECONNECT;
|
||||
else if (aLink.EqualsLiteral("preload"))
|
||||
return nsStyleLinkElement::ePRELOAD;
|
||||
else if (aLink.EqualsLiteral("prerender"))
|
||||
return nsStyleLinkElement::ePRERENDER;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
eNEXT = 0x00000008,
|
||||
eALTERNATE = 0x00000010,
|
||||
ePRECONNECT = 0x00000020,
|
||||
ePRERENDER = 0x00000040,
|
||||
// NOTE: 0x40 is unused
|
||||
ePRELOAD = 0x00000080
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,6 @@ support-files =
|
||||
window_nsITextInputProcessor.xul
|
||||
title_window.xul
|
||||
window_swapFrameLoaders.xul
|
||||
window_groupedSHistory.xul
|
||||
|
||||
[test_bug120684.xul]
|
||||
[test_bug206691.xul]
|
||||
@ -76,5 +75,4 @@ support-files = ../dummy.html
|
||||
support-files = file_title.xul
|
||||
[test_windowroot.xul]
|
||||
[test_swapFrameLoaders.xul]
|
||||
[test_groupedSHistory.xul]
|
||||
[test_bug1339722.html]
|
||||
|
@ -1,32 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1276553
|
||||
-->
|
||||
<window title="Mozilla Bug 1276553"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="loadTest();">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1276553"
|
||||
target="_blank">Mozilla Bug 1276553</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Test for GroupedSHistory **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function loadTest() {
|
||||
window.open("window_groupedSHistory.xul", "", "width=360,height=240,chrome");
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
@ -1,637 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
The test case creates 3 <xul:browser>s, load entries into them, modify the
|
||||
documents, and then check if grouped history merge / back / forward all work
|
||||
with bfcache preserved.
|
||||
|
||||
Related bugs:
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1276553
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1310768
|
||||
-->
|
||||
<window title="Test GroupedSHistory"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="run();">
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
const {interfaces: Ci, classes: Cc, results: Cr, utils: Cu} = Components;
|
||||
Cu.import("resource://testing-common/TestUtils.jsm");
|
||||
Cu.import("resource://testing-common/ContentTask.jsm");
|
||||
Cu.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||
ContentTask.setTestScope(window.opener.wrappedJSObject);
|
||||
|
||||
let imports = ['SimpleTest', 'SpecialPowers', 'ok', 'is', 'info'];
|
||||
for (let name of imports) {
|
||||
window[name] = window.opener.wrappedJSObject[name];
|
||||
}
|
||||
|
||||
function run() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set' : [[ 'browser.groupedhistory.enabled', true ]]})
|
||||
// Since we're not going to use GroupedSHistory in non-10s or
|
||||
// chrome-only URLs, we don't test for non-remote browsers anymore.
|
||||
//
|
||||
// As a note, there are 2 known issues in non-10s:
|
||||
// 1. nsDocShell::InternalLoad could start before nsFrameLoader calls
|
||||
// EvictAllContentViewers, and causes RestoreFromHistory fails.
|
||||
// 2. If using sendAsyncMessage, messages may be queued in
|
||||
// SameProcessMessageQueue, and cause "pagehide" being delivered to the
|
||||
// message manager of background <xul:browser> after swap.
|
||||
.then(() => test(true))
|
||||
.then(() => {
|
||||
window.close();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
function test(remote) {
|
||||
let act, bg1, bg2;
|
||||
return Promise.resolve()
|
||||
|
||||
// create background browser 1 with 1 entry
|
||||
.then(() => info('TEST-INFO | test create browser #1, remote=' + remote))
|
||||
.then(() => createBrowser('pineapple', remote))
|
||||
.then(b => bg1 = b)
|
||||
.then(() => verifyBrowser(bg1, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
false /* partial */ ))
|
||||
.then(() => addBfcachedText(bg1))
|
||||
|
||||
// create background browser 2 with 2 entries
|
||||
.then(() => info('TEST-INFO | test create browser #2, remote=' + remote))
|
||||
.then(() => createBrowser('apple', remote))
|
||||
.then(b => bg2 = b)
|
||||
.then(() => verifyBrowser(bg2, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
false /* partial */ ))
|
||||
.then(() => addBfcachedText(bg2))
|
||||
.then(() => loadURI(bg2, getDummyHtml('pencil')))
|
||||
.then(() => verifyBrowser(bg2, 'pencil' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
false /* partial */ ))
|
||||
.then(() => addBfcachedText(bg2))
|
||||
|
||||
// create active browser with 1 entry
|
||||
.then(() => info('TEST-INFO | test create browser #3, remote=' + remote))
|
||||
.then(() => createBrowser('pen', remote, true))
|
||||
.then(b => act = b)
|
||||
.then(() => verifyBrowser(act, 'pen' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
false /* partial */ ))
|
||||
.then(() => addBfcachedText(act))
|
||||
|
||||
// merge to 2 entries pen-pineapple
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
.then(() => info('TEST-INFO | test merge history #1, remote=' + remote))
|
||||
.then(() => mergeHistory(act, bg1, 'pineapple'))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
2 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// merge to 4 entries pen-pineapple-apple-pencil
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test merge history #2, remote=' + remote))
|
||||
.then(() => mergeHistory(act, bg2, 'pencil'))
|
||||
.then(() => verifyBrowser(act, 'pencil' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test go back
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test history go back #1, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.goBack.bind(act), 'pencil', 'apple'))
|
||||
.then(() => verifyBrowser(act, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test go back
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test history go back #2, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.goBack.bind(act), 'apple', 'pineapple', bg2))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test go back
|
||||
// act: pen
|
||||
// bg1: pineapple
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test history go back #3, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.goBack.bind(act), 'pineapple', 'pen', bg1))
|
||||
.then(() => verifyBrowser(act, 'pen' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
0 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test go forward
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test history go forward #1, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.goForward.bind(act), 'pen', 'pineapple', bg1))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test go forward
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test history go forward #2, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.goForward.bind(act), 'pineapple', 'apple', bg2))
|
||||
.then(() => verifyBrowser(act, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test go forward
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test history go forward #3, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.goForward.bind(act), 'apple', 'pencil'))
|
||||
.then(() => verifyBrowser(act, 'pencil' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test goto index
|
||||
// act: pen
|
||||
// bg1: apple-pencil
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test history goto index #1, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.gotoIndex.bind(act, 0), 'pencil', 'pen', bg1))
|
||||
.then(() => verifyBrowser(act, 'pen' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
0 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test goto index
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test history goto index #2, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.gotoIndex.bind(act, 2), 'pen', 'apple', bg1))
|
||||
.then(() => verifyBrowser(act, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test goto index
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test history goto index #3, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.gotoIndex.bind(act, 1), 'apple', 'pineapple', bg2))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test goto index
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test history goto index #4, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.gotoIndex.bind(act, 3), 'pineapple', 'pencil', bg2))
|
||||
.then(() => verifyBrowser(act, 'pencil' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test content go back
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test content history go back #1, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGoBack.bind(null, act), 'pencil', 'apple'))
|
||||
.then(() => verifyBrowser(act, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test content go back
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test content history go back #2, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGoBack.bind(null, act), 'apple', 'pineapple', bg2))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test content go back
|
||||
// act: pen
|
||||
// bg1: pineapple
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test content history go back #3, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGoBack.bind(null, act), 'pineapple', 'pen', bg1))
|
||||
.then(() => verifyBrowser(act, 'pen' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
0 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test content go forward
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test content history go forward #1, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGoForward.bind(null, act), 'pen', 'pineapple', bg1))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test content go forward
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test content history go forward #2, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGoForward.bind(null, act), 'pineapple', 'apple', bg2))
|
||||
.then(() => verifyBrowser(act, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test content go forward
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test content history go forward #3, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGoForward.bind(null, act), 'apple', 'pencil'))
|
||||
.then(() => verifyBrowser(act, 'pencil' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test content go
|
||||
// act: pen
|
||||
// bg1: apple-pencil
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test content history go #1, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGo.bind(null, act, -3), 'pencil', 'pen', bg1))
|
||||
.then(() => verifyBrowser(act, 'pen' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
false /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
0 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test content go
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test content history go #2, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGo.bind(null, act, 2), 'pen', 'apple', bg1))
|
||||
.then(() => verifyBrowser(act, 'apple' /* title */,
|
||||
0 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test content go
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test content history go #3, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGo.bind(null, act, -1), 'apple', 'pineapple', bg2))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
// test content go
|
||||
// act: apple-pencil
|
||||
// bg1: pen
|
||||
// bg2: pineapple
|
||||
.then(() => info('TEST-INFO | test content history go #4, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, contentGo.bind(null, act, 2), 'pineapple', 'pencil', bg2))
|
||||
.then(() => verifyBrowser(act, 'pencil' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
2 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// test history change to 3 entries pen-pineapple-banana
|
||||
// act: pineapple
|
||||
// bg1: pen
|
||||
// bg2: apple-pencil
|
||||
.then(() => info('TEST-INFO | test history change, remote=' + remote))
|
||||
.then(() => wrapHistoryNavFn(act, act.gotoIndex.bind(act, 1), 'pencil', 'pineapple', bg2))
|
||||
.then(() => verifyBrowser(act, 'pineapple' /* title */,
|
||||
0 /* index */,
|
||||
1 /* length */,
|
||||
true /* canGoBack */,
|
||||
true /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
4 /* globalLength */,
|
||||
true /* bfcached */ ))
|
||||
|
||||
// act: pineapple-banana
|
||||
// bg1: pen
|
||||
// bg2: (removed from group)
|
||||
.then(() => loadURI(act, getDummyHtml('banana')))
|
||||
.then(() => verifyBrowser(act, 'banana' /* title */,
|
||||
1 /* index */,
|
||||
2 /* length */,
|
||||
true /* canGoBack */,
|
||||
false /* canGoForward */,
|
||||
true /* partial */,
|
||||
1 /* offset */,
|
||||
3 /* globalLength */ ))
|
||||
}
|
||||
|
||||
function getDummyHtml(title) {
|
||||
return 'data:text/html;charset=UTF-8,' +
|
||||
'<html><head><title>' + title + '</title><script>' +
|
||||
'window.addEventListener("pageshow", e => document.dispatchEvent(' +
|
||||
' new CustomEvent("test:content-pageshow", {detail: document.title})));' +
|
||||
'window.addEventListener("pagehide", e => document.dispatchEvent(' +
|
||||
' new CustomEvent("test:content-pagehide", {detail: document.title})));' +
|
||||
'window.addEventListener("visibilitychange", e => document.dispatchEvent(' +
|
||||
' new CustomEvent("test:content-visibilitychange", {detail: ' +
|
||||
' {title: document.title, visibility: document.visibilityState}})));' +
|
||||
'</script></head><body><h1>' + title + '</h1><p id="p1"></p></body></html>';
|
||||
}
|
||||
|
||||
let gBrowserCount = 0;
|
||||
function createBrowser(title, remote, active = false) {
|
||||
let browser = document.createElement('browser');
|
||||
browser.testId = ++gBrowserCount; // for debugging
|
||||
browser.setAttribute('type', 'content');
|
||||
browser.setAttribute('remote', remote);
|
||||
browser.setAttribute('src', getDummyHtml(title));
|
||||
browser.docShellIsActive = active;
|
||||
document.getElementById('stack').appendChild(browser);
|
||||
return BrowserTestUtils.browserLoaded(browser)
|
||||
.then(() => {
|
||||
// Register our own event listeners.
|
||||
//
|
||||
// We don't use BrowserTestUtils.waitForContentEvents, because when
|
||||
// swapping frameloaders, the event listeners at content side are
|
||||
// also swapped to another browser. The message listener registered
|
||||
// by waitForContentEvents will never receive messages consequently.
|
||||
browser.messageManager.loadFrameScript('data:,' +
|
||||
'addEventListener("test:content-pageshow", e => {' +
|
||||
'if (e.target == content.document) {' +
|
||||
'sendAsyncMessage("test:content-pageshow", { title: e.detail });' +
|
||||
'}' +
|
||||
'}, true, true);' +
|
||||
'addEventListener("test:content-pagehide", e => {' +
|
||||
'if (e.target == content.document) {' +
|
||||
'sendAsyncMessage("test:content-pagehide", { title: e.detail });' +
|
||||
'}' +
|
||||
'}, true, true);' +
|
||||
'addEventListener("test:content-visibilitychange", e => {' +
|
||||
'sendAsyncMessage("test:content-visibilitychange", e.detail);' +
|
||||
'}, true, true);',
|
||||
true);
|
||||
|
||||
// Log for debugging purpose.
|
||||
browser.messageManager.addMessageListener('test:content-pageshow',
|
||||
msg => info('TEST-INFO | pageshow#' + browser.testId + ' ' + JSON.stringify(msg.data)));
|
||||
browser.messageManager.addMessageListener('test:content-pagehide',
|
||||
msg => info('TEST-INFO | pagehide#' + browser.testId + ' ' + JSON.stringify(msg.data)));
|
||||
browser.messageManager.addMessageListener('test:content-visibilitychange',
|
||||
msg => info('TEST-INFO | visibilitychange#' + browser.testId + ' ' + JSON.stringify(msg.data)));
|
||||
})
|
||||
.then(() => {
|
||||
// A trick to ensure webProgress object is created for e10s case.
|
||||
// Otherwise canGoBack / canGoForward won't be updated.
|
||||
ok(browser.webProgress, 'check browser.webProgress exists');
|
||||
return browser;
|
||||
});
|
||||
}
|
||||
|
||||
function addBfcachedText(browser) {
|
||||
return ContentTask.spawn(browser, null, () => {
|
||||
content.document.getElementById('p1').textContent = 'modified';
|
||||
});
|
||||
}
|
||||
|
||||
function loadURI(browser, uri) {
|
||||
let promise = BrowserTestUtils.browserLoaded(browser, false);
|
||||
browser.loadURI(uri);
|
||||
return promise;
|
||||
}
|
||||
|
||||
function mergeHistory(b1, b2, title) {
|
||||
let promises = [];
|
||||
let pagehide1, pagehide2;
|
||||
|
||||
promises.push(BrowserTestUtils.waitForMessage(b1.messageManager,
|
||||
'test:content-visibilitychange', msg => msg.data &&
|
||||
(msg.data.title == title) && (msg.data.visibility == 'visible')));
|
||||
|
||||
// For swapping remote browsers, we'll also receive Content:LocationChange
|
||||
if (b1.isRemoteBrowser) {
|
||||
// It's guaranteed location change can be delivered to b1's message
|
||||
// manager, since frameloader is synchronously swapping on main thread
|
||||
// after calling PartialSHistory::OnActive(). Therefore the message could
|
||||
// only be handled after swapping.
|
||||
promises.push(BrowserTestUtils.waitForMessage(b1.messageManager, 'Content:LocationChange'));
|
||||
}
|
||||
|
||||
promises.push(Promise.resolve().then(() => {
|
||||
let f1 = b1.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
|
||||
let f2 = b2.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
|
||||
return f1.appendPartialSHistoryAndSwap(f2);
|
||||
}));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function wrapHistoryNavFn(browser, navFn, prevTitle, nextTitle, browserToSwap) {
|
||||
let promises = [];
|
||||
|
||||
// Expecting pagehide from previous page, and a pageshow from next page.
|
||||
//
|
||||
// "Pagehide" is sent before calling OnRequestCrossBrowserNavigation(),
|
||||
// so it should be handled before swapping. "Pageshow" on the other hand
|
||||
// should be handled after swapping cause frameloader is synchronously
|
||||
// swapping on main thread after calling PartialSHistory::OnActive().
|
||||
//
|
||||
// Therefore both messages should be delivered to browser.messageManager.
|
||||
promises.push(BrowserTestUtils.waitForMessage(browser.messageManager,
|
||||
'test:content-pagehide', msg => msg.data && (msg.data.title == prevTitle)));
|
||||
promises.push(BrowserTestUtils.waitForMessage(browser.messageManager,
|
||||
'test:content-pageshow', msg => msg.data && (msg.data.title == nextTitle)));
|
||||
promises.push(navFn() || Promise.resolve());
|
||||
|
||||
// For swapping remote browsers, we'll also receive Content:LocationChange
|
||||
if (browserToSwap && browser.isRemoteBrowser) {
|
||||
promises.push(BrowserTestUtils.waitForMessage(browser.messageManager,
|
||||
'Content:LocationChange'));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function contentGoBack(browser) {
|
||||
ContentTask.spawn(browser, null, () => content.history.back());
|
||||
}
|
||||
|
||||
function contentGoForward(browser) {
|
||||
ContentTask.spawn(browser, null, () => content.history.forward());
|
||||
}
|
||||
|
||||
function contentGo(browser, offset) {
|
||||
ContentTask.spawn(browser, { offset },
|
||||
({ offset }) => content.history.go(offset));
|
||||
}
|
||||
|
||||
function verifyBrowser(browser, title, index, length, canGoBack, canGoForward,
|
||||
partial, offset = 0, globalLength = length, bfcached = false) {
|
||||
is(browser.canGoBack, canGoBack, 'check browser.canGoBack');
|
||||
is(browser.canGoForward, canGoForward, 'check browser.canGoForward');
|
||||
if (partial) {
|
||||
let frameLoader = browser.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
|
||||
is(frameLoader.groupedSHistory.count, globalLength, 'check groupedSHistory.count');
|
||||
}
|
||||
|
||||
return ContentTask.spawn(browser,
|
||||
{ title, index, length, canGoBack, canGoForward, partial, offset, globalLength, bfcached },
|
||||
({ title, index, length, canGoBack, canGoForward, partial, offset, globalLength, bfcached }) => {
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let shistory = webNav.sessionHistory;
|
||||
is(webNav.canGoBack, canGoBack, 'check webNav.canGoBack');
|
||||
is(webNav.canGoForward, canGoForward, 'check webNav.canGoForward');
|
||||
is(shistory.index, index, 'check shistory.index');
|
||||
is(shistory.count, length, 'check shistory.count');
|
||||
is(shistory.isPartial, partial, 'check shistory.isPartial');
|
||||
is(shistory.globalIndexOffset, offset, 'check shistory.globalIndexOffset');
|
||||
is(shistory.globalCount, globalLength, 'check shistory.globalCount');
|
||||
is(content.document.title, title, 'check title');
|
||||
is(content.document.getElementById('p1').textContent, bfcached ? 'modified' : '', 'check bfcached content');
|
||||
is(content.history.length, globalLength, 'check history.legnth');
|
||||
});
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
<stack id="stack" flex="1" />
|
||||
</window>
|
@ -2872,43 +2872,6 @@ IsNonExposedGlobal(JSContext* aCx, JSObject* aGlobal,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HandlePrerenderingViolation(nsPIDOMWindowInner* aWindow)
|
||||
{
|
||||
// Freeze the window and its workers, and its children too.
|
||||
aWindow->Freeze();
|
||||
|
||||
// Suspend event handling on the document
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (doc) {
|
||||
doc->SuppressEventHandling();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
EnforceNotInPrerendering(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
JS::Rooted<JSObject*> thisObj(aCx, js::CheckedUnwrap(aObj));
|
||||
if (!thisObj) {
|
||||
// Without a this object, we cannot check the safety.
|
||||
return true;
|
||||
}
|
||||
nsGlobalWindowInner* window = xpc::WindowGlobalOrNull(thisObj);
|
||||
if (!window) {
|
||||
// Without a window, we cannot check the safety.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (window->GetIsPrerendered()) {
|
||||
HandlePrerenderingViolation(window->AsInner());
|
||||
// When the bindings layer sees a false return value, it returns false form
|
||||
// the JSNative in order to trigger an uncatchable exception.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GenericBindingGetter(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
|
@ -2617,6 +2617,20 @@ UseDOMXray(JSObject* obj)
|
||||
IsDOMIfaceAndProtoClass(clasp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsDOMConstructor(JSObject* obj)
|
||||
{
|
||||
if (JS_IsNativeFunction(obj, dom::Constructor)) {
|
||||
// NamedConstructor, like Image
|
||||
return true;
|
||||
}
|
||||
|
||||
const js::Class* clasp = js::GetObjectClass(obj);
|
||||
// Check for a DOM interface object.
|
||||
return dom::IsDOMIfaceAndProtoClass(clasp) &&
|
||||
dom::DOMIfaceAndProtoJSClass::FromJSClass(clasp)->mType == dom::eInterface;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
inline bool
|
||||
HasConstructor(JSObject* obj)
|
||||
@ -3246,21 +3260,6 @@ AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitinfo,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
#endif
|
||||
|
||||
// This function is called by the bindings layer for methods/getters/setters
|
||||
// that are not safe to be called in prerendering mode. It checks to make sure
|
||||
// that the |this| object is not running in a global that is in prerendering
|
||||
// mode. Otherwise, it aborts execution of timers and event handlers, and
|
||||
// returns false which gets converted to an uncatchable exception by the
|
||||
// bindings layer.
|
||||
bool
|
||||
EnforceNotInPrerendering(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
// Handles the violation of a blacklisted action in prerendering mode by
|
||||
// aborting the scripts, and preventing timers and event handlers from running
|
||||
// in the window in the future.
|
||||
void
|
||||
HandlePrerenderingViolation(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
bool
|
||||
CallerSubsumes(JSObject* aObject);
|
||||
|
||||
|
@ -1746,16 +1746,12 @@ addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
|
||||
addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
|
||||
headerFile='Crypto.h')
|
||||
addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True)
|
||||
addExternalIface('nsIGroupedSHistory', nativeType='nsIGroupedSHistory',
|
||||
notflattened=True)
|
||||
addExternalIface('nsILoadGroup', nativeType='nsILoadGroup',
|
||||
headerFile='nsILoadGroup.h', notflattened=True)
|
||||
addExternalIface('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster',
|
||||
headerFile='nsIMessageManager.h', notflattened=True)
|
||||
addExternalIface('nsIMessageSender', nativeType='nsIMessageSender',
|
||||
headerFile='nsIMessageManager.h', notflattened=True)
|
||||
addExternalIface('nsIPartialSHistory', nativeType='nsIPartialSHistory',
|
||||
notflattened=True)
|
||||
addExternalIface('nsIPrintSettings', nativeType='nsIPrintSettings',
|
||||
notflattened=True)
|
||||
addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
|
||||
|
@ -7725,23 +7725,6 @@ class CGPerSignatureCall(CGThing):
|
||||
self.isConstructor = isConstructor
|
||||
cgThings = []
|
||||
|
||||
# Here, we check if the current getter, setter, method, interface or
|
||||
# inherited interfaces have the UnsafeInPrerendering extended attribute
|
||||
# and if so, we add a check to make sure it is safe.
|
||||
if (idlNode.getExtendedAttribute("UnsafeInPrerendering") or
|
||||
descriptor.interface.getExtendedAttribute("UnsafeInPrerendering") or
|
||||
any(i.getExtendedAttribute("UnsafeInPrerendering")
|
||||
for i in descriptor.interface.getInheritedInterfaces())):
|
||||
cgThings.append(CGGeneric(dedent(
|
||||
"""
|
||||
if (!mozilla::dom::EnforceNotInPrerendering(cx, obj)) {
|
||||
// Return false from the JSNative in order to trigger
|
||||
// an uncatchable exception.
|
||||
MOZ_ASSERT(!JS_IsExceptionPending(cx));
|
||||
return false;
|
||||
}
|
||||
""")))
|
||||
|
||||
deprecated = (idlNode.getExtendedAttribute("Deprecated") or
|
||||
(idlNode.isStatic() and descriptor.interface.getExtendedAttribute("Deprecated")))
|
||||
if deprecated:
|
||||
|
@ -1724,7 +1724,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||
identifier == "OverrideBuiltins" or
|
||||
identifier == "ChromeOnly" or
|
||||
identifier == "Unforgeable" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
identifier == "LegacyEventInit" or
|
||||
identifier == "ProbablyShortLivingWrapper" or
|
||||
identifier == "LegacyUnenumerableNamedProperties" or
|
||||
@ -4351,7 +4350,6 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
identifier == "SecureContext" or
|
||||
identifier == "Frozen" or
|
||||
identifier == "NewObject" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
identifier == "NeedsSubjectPrincipal" or
|
||||
identifier == "SetterNeedsSubjectPrincipal" or
|
||||
identifier == "GetterNeedsSubjectPrincipal" or
|
||||
@ -5080,7 +5078,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
identifier == "CanOOM" or
|
||||
identifier == "NewObject" or
|
||||
identifier == "ChromeOnly" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
identifier == "Pref" or
|
||||
identifier == "Deprecated" or
|
||||
identifier == "Func" or
|
||||
|
@ -182,12 +182,6 @@ interface TestInterface {
|
||||
[DependsOn=DeviceState, Affects=Nothing]
|
||||
byte returnDeviceStateDependentByte();
|
||||
|
||||
[UnsafeInPrerendering]
|
||||
void unsafePrerenderMethod();
|
||||
[UnsafeInPrerendering]
|
||||
attribute long unsafePrerenderWritable;
|
||||
[UnsafeInPrerendering]
|
||||
readonly attribute long unsafePrerenderReadonly;
|
||||
readonly attribute short readonlyShort;
|
||||
attribute short writableShort;
|
||||
void passShort(short arg);
|
||||
|
@ -10,13 +10,6 @@ support-files =
|
||||
[test_dom_xrays.html]
|
||||
[test_proxies_via_xray.html]
|
||||
[test_document_location_via_xray_cached.html]
|
||||
[test_blacklisted_prerendering_function.xul]
|
||||
support-files =
|
||||
file_focuser.html
|
||||
file_fullScreenPropertyAccessor.html
|
||||
skip-if = e10s # prerendering doesn't work in e10s yet
|
||||
[test_kill_longrunning_prerendered_content.xul]
|
||||
skip-if = e10s # prerendering doesn't work in e10s yet
|
||||
[test_bug1123516_maplikesetlikechrome.xul]
|
||||
skip-if = debug == false
|
||||
[test_bug1287912.html]
|
||||
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<div id="stage"></div>
|
||||
<script>
|
||||
function stage(str) {
|
||||
var s = document.getElementById("stage");
|
||||
s.textContent = str;
|
||||
}
|
||||
stage("before");
|
||||
setTimeout(function() {
|
||||
stage("in timeout");
|
||||
});
|
||||
setInterval(function() {
|
||||
stage("in interval");
|
||||
});
|
||||
addEventListener("keydown", function() {
|
||||
stage("keydown");
|
||||
}, false);
|
||||
try {
|
||||
focus();
|
||||
stage("after");
|
||||
} catch(e) {
|
||||
stage("exception raised");
|
||||
}
|
||||
</script>
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<div id="stage"></div>
|
||||
<script>
|
||||
function stage(str) {
|
||||
var s = document.getElementById("stage");
|
||||
s.textContent = str;
|
||||
}
|
||||
stage("before");
|
||||
setTimeout(function() {
|
||||
stage("in timeout");
|
||||
});
|
||||
setInterval(function() {
|
||||
stage("in interval");
|
||||
});
|
||||
addEventListener("keydown", function() {
|
||||
stage("keydown");
|
||||
}, false);
|
||||
try {
|
||||
window.fullScreen;
|
||||
stage("after");
|
||||
} catch(e) {
|
||||
stage("exception raised");
|
||||
}
|
||||
</script>
|
@ -1,124 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onload="runTest();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function Listener(aBrowser, aPrerendered, aCallback) {
|
||||
this.init(aBrowser, aPrerendered, aCallback);
|
||||
}
|
||||
|
||||
Listener.prototype = {
|
||||
init: function(aBrowser, aPrerendered, aCallback) {
|
||||
this.mBrowser = aBrowser;
|
||||
this.mPrerendered = aPrerendered;
|
||||
this.mCallback = aCallback;
|
||||
},
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if ((aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
|
||||
(aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT)) {
|
||||
var doc = this.mBrowser.contentDocument;
|
||||
var stage = doc.getElementById("stage");
|
||||
if (this.mPrerendered) {
|
||||
is(stage.textContent, "before", "The blacklisted call should properly be intercepted in prerendering mode");
|
||||
} else {
|
||||
// In normal mode, we may or may not have run the timeout and/or the interval.
|
||||
switch (stage.textContent) {
|
||||
case "after":
|
||||
case "in timeout":
|
||||
case "in interval":
|
||||
ok(true, "The blacklisted call should work fine in normal mode");
|
||||
break;
|
||||
default:
|
||||
ok(false, "The blacklisted call should work fine in normal mode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
progress.removeProgressListener(progressListener);
|
||||
|
||||
// Set three timeouts to see if the interval triggered
|
||||
var self = this;
|
||||
function checkInterval() {
|
||||
var expected = self.mPrerendered ? "before" : "in interval";
|
||||
var desc = self.mPrerendered ? "No timer should be running" : "Timers should run as normal";
|
||||
is(stage.textContent, expected, desc);
|
||||
// Now, dispatch a key event to the window and see if the keydown handler runs
|
||||
synthesizeKey("a", {}, self.mBrowser.contentWindow);
|
||||
expected = self.mPrerendered ? "before" : "keydown";
|
||||
desc = self.mPrerendered ? "No event handler should be running" : "Event handlers should run as normal";
|
||||
is(stage.textContent, expected, desc);
|
||||
self.mCallback();
|
||||
}
|
||||
setTimeout(function() {
|
||||
setTimeout(function() {
|
||||
setTimeout(function() {
|
||||
checkInterval();
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
onProgressChange : function(aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {},
|
||||
onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {},
|
||||
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
|
||||
onSecurityChange : function(aWebProgress, aRequest, aState) {},
|
||||
mBrowser: null,
|
||||
mPrerendered: false,
|
||||
mCallback: null
|
||||
};
|
||||
|
||||
var progress, progressListener;
|
||||
|
||||
function runTest() {
|
||||
testStep(false, "file_focuser.html", function() {
|
||||
testStep(true, "file_focuser.html", function() {
|
||||
testStep(false, "file_fullScreenPropertyAccessor.html", function() {
|
||||
testStep(true, "file_fullScreenPropertyAccessor.html", function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testStep(aPrerendered, aFileName, aCallback) {
|
||||
var browser = document.getElementById(aPrerendered ? "prerendered" : "normal");;
|
||||
progressListener = new Listener(browser, aPrerendered, aCallback);
|
||||
var docShell = browser.docShell;
|
||||
progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebProgress);
|
||||
progress.addProgressListener(progressListener,
|
||||
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
||||
browser.loadURI("chrome://mochitests/content/chrome/dom/bindings/test/" + aFileName);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body id="html_body" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069719">Mozilla Bug 1069719</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
<browser prerendered="true" id="prerendered"/>
|
||||
<browser id="normal"/>
|
||||
</window>
|
@ -1,85 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onload="runTest();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function Listener(aBrowser, aPrerendered, aCallback) {
|
||||
this.init(aBrowser, aPrerendered, aCallback);
|
||||
}
|
||||
|
||||
Listener.prototype = {
|
||||
init: function(aBrowser, aCallback) {
|
||||
this.mBrowser = aBrowser;
|
||||
this.mCallback = aCallback;
|
||||
},
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if ((aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
|
||||
(aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT)) {
|
||||
setTimeout(this.mCallback, 0);
|
||||
}
|
||||
},
|
||||
onProgressChange : function(aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {},
|
||||
onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {},
|
||||
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
|
||||
onSecurityChange : function(aWebProgress, aRequest, aState) {},
|
||||
mBrowser: null,
|
||||
mPrerendered: false,
|
||||
mCallback: null
|
||||
};
|
||||
|
||||
var progress, progressListener;
|
||||
|
||||
function runTest() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.max_script_run_time", 1]
|
||||
]
|
||||
}, function() {
|
||||
test(function() {
|
||||
ok("The page is successfully interrupted.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test(aCallback) {
|
||||
var browser = document.getElementById("prerendered");;
|
||||
progressListener = new Listener(browser, aCallback);
|
||||
var docShell = browser.docShell;
|
||||
progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebProgress);
|
||||
progress.addProgressListener(progressListener,
|
||||
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
||||
browser.loadURI("data:text/html,<script>;for(;;);</script" + ">");
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body id="html_body" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1050456">Mozilla Bug 1050456</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
<browser prerendered="true" id="prerendered"/>
|
||||
</window>
|
@ -8086,3 +8086,6 @@ HTMLMediaElement::ReportCanPlayTelemetry()
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#undef LOG
|
||||
#undef LOG_EVENT
|
||||
|
@ -8,10 +8,15 @@
|
||||
#include "mozilla/dom/HTMLMetaElement.h"
|
||||
#include "mozilla/dom/HTMLMetaElementBinding.h"
|
||||
#include "mozilla/dom/nsCSPService.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
||||
static mozilla::LazyLogModule gMetaElementLog("nsMetaElement");
|
||||
#define LOG(msg) MOZ_LOG(gMetaElementLog, mozilla::LogLevel::Debug, msg)
|
||||
#define LOG_ENABLED() MOZ_LOG_TEST(gMetaElementLog, mozilla::LogLevel::Debug)
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
|
||||
|
||||
namespace mozilla {
|
||||
@ -117,6 +122,17 @@ HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDocument);
|
||||
principal->EnsureCSP(domDoc, getter_AddRefs(csp));
|
||||
if (csp) {
|
||||
if (LOG_ENABLED()) {
|
||||
nsAutoCString documentURIspec;
|
||||
nsIURI* documentURI = aDocument->GetDocumentURI();
|
||||
if (documentURI) {
|
||||
documentURI->GetAsciiSpec(documentURIspec);
|
||||
}
|
||||
|
||||
LOG(("HTMLMetaElement %p sets CSP '%s' on document=%p, document-uri=%s",
|
||||
this, NS_ConvertUTF16toUTF8(content).get(), aDocument, documentURIspec.get()));
|
||||
}
|
||||
|
||||
// Multiple CSPs (delivered through either header of meta tag) need to be
|
||||
// joined together, see:
|
||||
// https://w3c.github.io/webappsec/specs/content-security-policy/#delivery-html-meta-element
|
||||
|
@ -145,9 +145,6 @@ nsGenericHTMLFrameElement::EnsureFrameLoader()
|
||||
mFrameLoader = nsFrameLoader::Create(this,
|
||||
nsPIDOMWindowOuter::From(mOpenerWindow),
|
||||
mNetworkCreated);
|
||||
if (mIsPrerendered) {
|
||||
mFrameLoader->SetIsPrerendered();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -228,14 +225,6 @@ nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoaderOwn
|
||||
rv = loader->SwapWithOtherLoader(otherLoader, this, aOtherLoaderOwner);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericHTMLFrameElement::SetIsPrerendered()
|
||||
{
|
||||
MOZ_ASSERT(!mFrameLoader, "Please call SetIsPrerendered before frameLoader is created");
|
||||
mIsPrerendered = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::LoadSrc()
|
||||
{
|
||||
|
@ -38,7 +38,6 @@ public:
|
||||
, nsBrowserElement()
|
||||
, mSrcLoadHappened(false)
|
||||
, mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
|
||||
, mIsPrerendered(false)
|
||||
, mBrowserFrameListenersRegistered(false)
|
||||
, mFrameLoaderCreationDisallowed(false)
|
||||
, mReallyIsBrowser(false)
|
||||
@ -138,7 +137,6 @@ protected:
|
||||
*/
|
||||
bool mNetworkCreated;
|
||||
|
||||
bool mIsPrerendered;
|
||||
bool mBrowserFrameListenersRegistered;
|
||||
bool mFrameLoaderCreationDisallowed;
|
||||
bool mReallyIsBrowser;
|
||||
|
@ -37,11 +37,6 @@ interface nsITabParent : nsISupports
|
||||
*/
|
||||
readonly attribute boolean hasLayers;
|
||||
|
||||
/**
|
||||
* Whether this tabParent is in prerender mode.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isPrerendered;
|
||||
|
||||
/**
|
||||
* As an optimisation, setting the docshell's active state to
|
||||
* inactive also triggers a layer invalidation to free up some
|
||||
|
@ -575,25 +575,6 @@ parent:
|
||||
// bridge.
|
||||
sync EnsureLayersConnected() returns (CompositorOptions compositorOptions);
|
||||
|
||||
/**
|
||||
* Notify the parent that the session history state has been updated.
|
||||
*
|
||||
* @param aCount
|
||||
* The updated number of entries in child session history
|
||||
* @param aLocalIndex
|
||||
* The local session history index which is loaded.
|
||||
*/
|
||||
async SHistoryUpdate(uint32_t aCount, uint32_t aLocalIndex, bool aTruncate);
|
||||
|
||||
/**
|
||||
* When the session history is across multiple root docshells, this function
|
||||
* is used to notify parent that it needs to navigate to an entry out of
|
||||
* local index of the child.
|
||||
*
|
||||
* @param aGlobalIndex The global index of history entry to navigate to.
|
||||
*/
|
||||
async RequestCrossBrowserNavigation(uint32_t aGlobalIndex);
|
||||
|
||||
/**
|
||||
* This function is used to notify the parent that it should display a
|
||||
* canvas permission prompt.
|
||||
@ -900,32 +881,6 @@ child:
|
||||
*/
|
||||
async UpdateNativeWindowHandle(uintptr_t aNewHandle);
|
||||
|
||||
/**
|
||||
* Called when the session history of this particular PBrowser has been
|
||||
* attached to a grouped session history.
|
||||
*
|
||||
* @param aOffset The number of entries in the grouped session
|
||||
* history before this session history object.
|
||||
*/
|
||||
async NotifyAttachGroupedSHistory(uint32_t aOffset);
|
||||
|
||||
/**
|
||||
* Notify that the session history associated to this PBrowser has become
|
||||
* the active history in the grouped session history.
|
||||
*
|
||||
* @param aGlobalLength The up-to-date number of entries in the grouped
|
||||
* session history.
|
||||
* @param aTargetLocalIndex The target local index to navigate to.
|
||||
*/
|
||||
async NotifyPartialSHistoryActive(uint32_t aGlobalLength,
|
||||
uint32_t aTargetLocalIndex);
|
||||
|
||||
/**
|
||||
* Notify that the session history asssociates to this PBrowser has become
|
||||
* an inactive history in the grouped session history.
|
||||
*/
|
||||
async NotifyPartialSHistoryDeactive();
|
||||
|
||||
/**
|
||||
* Tell the TabChild that it should expect a Large-Allocation load to occur.
|
||||
* Loads which occur until this flag is cleared will not leave the process.
|
||||
|
@ -43,9 +43,6 @@ struct FrameIPCTabContext
|
||||
// <xul:browser> are not considered to be mozbrowser frames.
|
||||
bool isMozBrowserElement;
|
||||
|
||||
// Whether this TabContext should work in prerender mode.
|
||||
bool isPrerendered;
|
||||
|
||||
// The requested presentation URL.
|
||||
// This value would be empty if the TabContext isn't created for
|
||||
// presented content.
|
||||
|
@ -120,7 +120,6 @@
|
||||
#include "nsICommandParams.h"
|
||||
#include "nsISHistory.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "GroupedSHistory.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "nsString.h"
|
||||
@ -158,10 +157,6 @@ using namespace mozilla::jsipc;
|
||||
using mozilla::layers::GeckoContentController;
|
||||
|
||||
NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
|
||||
NS_IMPL_ISUPPORTS(TabChildSHistoryListener,
|
||||
nsISHistoryListener,
|
||||
nsIPartialSHistoryListener,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
|
||||
|
||||
@ -640,11 +635,6 @@ TabChild::Init()
|
||||
window->SetInitialKeyboardIndicators(ShowAccelerators(), ShowFocusRings());
|
||||
}
|
||||
|
||||
// Set prerender flag if necessary.
|
||||
if (mIsPrerendered) {
|
||||
docShell->SetIsPrerendered();
|
||||
}
|
||||
|
||||
nsContentUtils::SetScrollbarsVisibility(window->GetDocShell(),
|
||||
!!(mChromeFlags & nsIWebBrowserChrome::CHROME_SCROLLBARS));
|
||||
|
||||
@ -661,20 +651,6 @@ TabChild::Init()
|
||||
mAPZEventState = new APZEventState(mPuppetWidget, Move(callback));
|
||||
|
||||
mIPCOpen = true;
|
||||
|
||||
if (GroupedSHistory::GroupedHistoryEnabled()) {
|
||||
// Set session history listener.
|
||||
nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
|
||||
if (!shistory) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mHistoryListener = new TabChildSHistoryListener(this);
|
||||
nsCOMPtr<nsISHistoryListener> listener(do_QueryObject(mHistoryListener));
|
||||
shistory->AddSHistoryListener(listener);
|
||||
nsCOMPtr<nsIPartialSHistoryListener> partialListener(do_QueryObject(mHistoryListener));
|
||||
shistory->SetPartialSHistoryListener(partialListener);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1170,10 +1146,6 @@ TabChild::~TabChild()
|
||||
webBrowser->SetContainerWindow(nullptr);
|
||||
}
|
||||
|
||||
if (mHistoryListener) {
|
||||
mHistoryListener->ClearTabChild();
|
||||
}
|
||||
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
@ -1560,54 +1532,6 @@ TabChild::RecvStopIMEStateManagement()
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabChild::RecvNotifyAttachGroupedSHistory(const uint32_t& aOffset)
|
||||
{
|
||||
// nsISHistory uses int32_t
|
||||
if (NS_WARN_IF(aOffset > INT32_MAX)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
|
||||
NS_ENSURE_TRUE(shistory, IPC_FAIL_NO_REASON(this));
|
||||
|
||||
if (NS_FAILED(shistory->OnAttachGroupedSHistory(aOffset))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabChild::RecvNotifyPartialSHistoryActive(const uint32_t& aGlobalLength,
|
||||
const uint32_t& aTargetLocalIndex)
|
||||
{
|
||||
// nsISHistory uses int32_t
|
||||
if (NS_WARN_IF(aGlobalLength > INT32_MAX || aTargetLocalIndex > INT32_MAX)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
|
||||
NS_ENSURE_TRUE(shistory, IPC_FAIL_NO_REASON(this));
|
||||
|
||||
if (NS_FAILED(shistory->OnPartialSHistoryActive(aGlobalLength,
|
||||
aTargetLocalIndex))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabChild::RecvNotifyPartialSHistoryDeactive()
|
||||
{
|
||||
nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
|
||||
NS_ENSURE_TRUE(shistory, IPC_FAIL_NO_REASON(this));
|
||||
|
||||
if (NS_FAILED(shistory->OnPartialSHistoryDeactive())) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabChild::RecvMouseEvent(const nsString& aType,
|
||||
const float& aX,
|
||||
@ -2677,8 +2601,6 @@ TabChild::RemovePendingDocShellBlocker()
|
||||
void
|
||||
TabChild::InternalSetDocShellIsActive(bool aIsActive)
|
||||
{
|
||||
// docshell is consider prerendered only if not active yet
|
||||
mIsPrerendered &= !aIsActive;
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
|
||||
if (docShell) {
|
||||
@ -3621,114 +3543,12 @@ TabChild::BeforeUnloadRemoved()
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsISHistory>
|
||||
TabChild::GetRelatedSHistory()
|
||||
{
|
||||
nsCOMPtr<nsISHistory> shistory;
|
||||
mWebNav->GetSessionHistory(getter_AddRefs(shistory));
|
||||
return shistory.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabChildSHistoryListener::SHistoryDidUpdate(bool aTruncate /* = false */)
|
||||
{
|
||||
RefPtr<TabChild> tabChild(mTabChild);
|
||||
if (NS_WARN_IF(!tabChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHistory> shistory = tabChild->GetRelatedSHistory();
|
||||
NS_ENSURE_TRUE(shistory, NS_ERROR_FAILURE);
|
||||
|
||||
int32_t index, count;
|
||||
nsresult rv = shistory->GetIndex(&index);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = shistory->GetCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX: It would be nice if we could batch these updates like SessionStore
|
||||
// does, and provide a form of `Flush` command which would allow us to trigger
|
||||
// an update, and wait for the state to become consistent.
|
||||
NS_ENSURE_TRUE(tabChild->SendSHistoryUpdate(count, index, aTruncate), NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::dom::TabGroup*
|
||||
TabChild::TabGroup()
|
||||
{
|
||||
return mTabGroup;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* nsISHistoryListener
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryNewEntry(nsIURI *aNewURI, int32_t aOldIndex)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryGoBack(nsIURI *aBackURI, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryGoForward(nsIURI *aForwardURI, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryReload(nsIURI *aReloadURI, uint32_t aReloadFlags, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryGotoIndex(int32_t aIndex, nsIURI *aGotoURI, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryPurge(int32_t aNumEntries, bool *_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnHistoryReplaceEntry(int32_t aIndex)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnLengthChanged(int32_t aCount)
|
||||
{
|
||||
return SHistoryDidUpdate(/* aTruncate = */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnIndexChanged(int32_t aIndex)
|
||||
{
|
||||
return SHistoryDidUpdate(/* aTruncate = */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildSHistoryListener::OnRequestCrossBrowserNavigation(uint32_t aIndex)
|
||||
{
|
||||
RefPtr<TabChild> tabChild(mTabChild);
|
||||
if (!tabChild) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return tabChild->SendRequestCrossBrowserNavigation(aIndex) ?
|
||||
NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
TabChildGlobal::TabChildGlobal(TabChild* aTabChild)
|
||||
: mTabChild(aTabChild)
|
||||
{
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsISHistoryListener.h"
|
||||
#include "nsIPartialSHistoryListener.h"
|
||||
|
||||
class nsIDOMWindowUtils;
|
||||
class nsIHttpChannel;
|
||||
@ -186,29 +185,6 @@ protected:
|
||||
TabChild* mTabChild;
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens on session history change, and sends NotifySessionHistoryChange to
|
||||
* parent process.
|
||||
*/
|
||||
class TabChildSHistoryListener final : public nsISHistoryListener,
|
||||
public nsIPartialSHistoryListener,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
explicit TabChildSHistoryListener(TabChild* aTabChild) : mTabChild(aTabChild) {}
|
||||
void ClearTabChild() { mTabChild = nullptr; }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISHISTORYLISTENER
|
||||
NS_DECL_NSIPARTIALSHISTORYLISTENER
|
||||
|
||||
private:
|
||||
nsresult SHistoryDidUpdate(bool aTruncate = false);
|
||||
|
||||
~TabChildSHistoryListener() {}
|
||||
TabChild* mTabChild;
|
||||
};
|
||||
|
||||
// This is base clase which helps to share Viewport and touch related
|
||||
// functionality between b2g/android FF/embedlite clients implementation.
|
||||
// It make sense to place in this class all helper functions, and functionality
|
||||
@ -739,8 +715,6 @@ public:
|
||||
bool StopAwaitingLargeAlloc();
|
||||
bool IsAwaitingLargeAlloc();
|
||||
|
||||
already_AddRefed<nsISHistory> GetRelatedSHistory();
|
||||
|
||||
mozilla::dom::TabGroup* TabGroup();
|
||||
|
||||
#if defined(ACCESSIBILITY)
|
||||
@ -819,13 +793,6 @@ protected:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvStopIMEStateManagement() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyAttachGroupedSHistory(const uint32_t& aOffset) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyPartialSHistoryActive(const uint32_t& aGlobalLength,
|
||||
const uint32_t& aTargetLocalIndex) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyPartialSHistoryDeactive() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvAwaitLargeAlloc() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvSetWindowName(const nsString& aName) override;
|
||||
@ -907,7 +874,6 @@ private:
|
||||
nsCOMPtr<nsIURI> mLastURI;
|
||||
RenderFrameChild* mRemoteFrame;
|
||||
RefPtr<nsIContentChild> mManager;
|
||||
RefPtr<TabChildSHistoryListener> mHistoryListener;
|
||||
uint32_t mChromeFlags;
|
||||
uint32_t mMaxTouchPoints;
|
||||
int32_t mActiveSuppressDisplayport;
|
||||
|
@ -21,8 +21,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
TabContext::TabContext()
|
||||
: mIsPrerendered(false)
|
||||
, mInitialized(false)
|
||||
: mInitialized(false)
|
||||
, mIsMozBrowserElement(false)
|
||||
, mJSPluginID(-1)
|
||||
, mShowAccelerators(UIStateChangeType_NoChange)
|
||||
@ -119,7 +118,6 @@ TabContext::ShowFocusRings() const
|
||||
|
||||
bool
|
||||
TabContext::SetTabContext(bool aIsMozBrowserElement,
|
||||
bool aIsPrerendered,
|
||||
UIStateChangeType aShowAccelerators,
|
||||
UIStateChangeType aShowFocusRings,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
@ -132,7 +130,6 @@ TabContext::SetTabContext(bool aIsMozBrowserElement,
|
||||
|
||||
mInitialized = true;
|
||||
mIsMozBrowserElement = aIsMozBrowserElement;
|
||||
mIsPrerendered = aIsPrerendered;
|
||||
mOriginAttributes = aOriginAttributes;
|
||||
mPresentationURL = aPresentationURL;
|
||||
mShowAccelerators = aShowAccelerators;
|
||||
@ -159,7 +156,6 @@ TabContext::AsIPCTabContext() const
|
||||
|
||||
return IPCTabContext(FrameIPCTabContext(mOriginAttributes,
|
||||
mIsMozBrowserElement,
|
||||
mIsPrerendered,
|
||||
mPresentationURL,
|
||||
mShowAccelerators,
|
||||
mShowFocusRings));
|
||||
@ -169,7 +165,6 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||
: mInvalidReason(nullptr)
|
||||
{
|
||||
bool isMozBrowserElement = false;
|
||||
bool isPrerendered = false;
|
||||
int32_t jsPluginId = -1;
|
||||
OriginAttributes originAttributes;
|
||||
nsAutoString presentationURL;
|
||||
@ -235,7 +230,6 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||
aParams.get_FrameIPCTabContext();
|
||||
|
||||
isMozBrowserElement = ipcContext.isMozBrowserElement();
|
||||
isPrerendered = ipcContext.isPrerendered();
|
||||
presentationURL = ipcContext.presentationURL();
|
||||
showAccelerators = ipcContext.showAccelerators();
|
||||
showFocusRings = ipcContext.showFocusRings();
|
||||
@ -264,7 +258,6 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||
rv = mTabContext.SetTabContextForJSPluginFrame(jsPluginId);
|
||||
} else {
|
||||
rv = mTabContext.SetTabContext(isMozBrowserElement,
|
||||
isPrerendered,
|
||||
showAccelerators,
|
||||
showFocusRings,
|
||||
originAttributes,
|
||||
|
@ -105,7 +105,6 @@ protected:
|
||||
void SetPrivateBrowsingAttributes(bool aIsPrivateBrowsing);
|
||||
|
||||
bool SetTabContext(bool aIsMozBrowserElement,
|
||||
bool aIsPrerendered,
|
||||
UIStateChangeType aShowAccelerators,
|
||||
UIStateChangeType aShowFocusRings,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
@ -122,11 +121,6 @@ protected:
|
||||
*/
|
||||
bool UpdateTabContextAfterSwap(const TabContext& aContext);
|
||||
|
||||
/**
|
||||
* Whether this TabContext is in prerender mode.
|
||||
*/
|
||||
bool mIsPrerendered;
|
||||
|
||||
/**
|
||||
* Set this TabContext to be for a JS plugin. aPluginID is the id of the JS plugin
|
||||
* (@see nsFakePlugin::mId).
|
||||
@ -183,14 +177,12 @@ public:
|
||||
|
||||
bool
|
||||
SetTabContext(bool aIsMozBrowserElement,
|
||||
bool aIsPrerendered,
|
||||
UIStateChangeType aShowAccelerators,
|
||||
UIStateChangeType aShowFocusRings,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aPresentationURL = EmptyString())
|
||||
{
|
||||
return TabContext::SetTabContext(aIsMozBrowserElement,
|
||||
aIsPrerendered,
|
||||
aShowAccelerators,
|
||||
aShowFocusRings,
|
||||
aOriginAttributes,
|
||||
|
@ -98,8 +98,6 @@
|
||||
#include "UnitTransforms.h"
|
||||
#include <algorithm>
|
||||
#include "mozilla/WebBrowserPersistDocumentParent.h"
|
||||
#include "nsIGroupedSHistory.h"
|
||||
#include "PartialSHistory.h"
|
||||
#include "ProcessPriorityManager.h"
|
||||
#include "nsString.h"
|
||||
#include "NullPrincipal.h"
|
||||
@ -2904,8 +2902,6 @@ TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
|
||||
NS_IMETHODIMP
|
||||
TabParent::SetDocShellIsActive(bool isActive)
|
||||
{
|
||||
// docshell is consider prerendered only if not active yet
|
||||
mIsPrerendered &= !isActive;
|
||||
mDocShellIsActive = isActive;
|
||||
SetRenderLayers(isActive);
|
||||
Unused << SendSetDocShellIsActive(isActive);
|
||||
@ -2941,13 +2937,6 @@ TabParent::GetDocShellIsActive(bool* aIsActive)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabParent::GetIsPrerendered(bool* aIsPrerendered)
|
||||
{
|
||||
*aIsPrerendered = mIsPrerendered;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabParent::SetRenderLayers(bool aEnabled)
|
||||
{
|
||||
@ -3599,45 +3588,6 @@ TabParent::RecvLookUpDictionary(const nsString& aText,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabParent::RecvSHistoryUpdate(const uint32_t& aCount, const uint32_t& aLocalIndex, const bool& aTruncate)
|
||||
{
|
||||
RefPtr<nsFrameLoader> frameLoader(GetFrameLoader());
|
||||
if (!frameLoader) {
|
||||
// FrameLoader can be nullptr if the it is destroying.
|
||||
// In this case session history change can simply be ignored.
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPartialSHistory> partialHistory;
|
||||
frameLoader->GetPartialSHistory(getter_AddRefs(partialHistory));
|
||||
if (!partialHistory) {
|
||||
// PartialSHistory is not enabled
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
partialHistory->HandleSHistoryUpdate(aCount, aLocalIndex, aTruncate);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabParent::RecvRequestCrossBrowserNavigation(const uint32_t& aGlobalIndex)
|
||||
{
|
||||
RefPtr<nsFrameLoader> frameLoader(GetFrameLoader());
|
||||
if (!frameLoader) {
|
||||
// FrameLoader can be nullptr if the it is destroying.
|
||||
// In this case we can ignore the request.
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
if (NS_FAILED(frameLoader->RequestGroupedHistoryNavigation(aGlobalIndex,
|
||||
getter_AddRefs(promise)))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabParent::RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI)
|
||||
{
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "nsWeakReference.h"
|
||||
#include "Units.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIPartialSHistory.h"
|
||||
|
||||
class nsFrameLoader;
|
||||
class nsIFrameLoader;
|
||||
@ -643,11 +642,6 @@ protected:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetTabCount(uint32_t* aValue) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvSHistoryUpdate(const uint32_t& aCount,
|
||||
const uint32_t& aLocalIndex,
|
||||
const bool& aTruncate) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvRequestCrossBrowserNavigation(const uint32_t& aGlobalIndex) override;
|
||||
virtual mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) override;
|
||||
|
||||
ContentCacheInParent mContentCache;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "AudioChannelService.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
@ -171,6 +172,7 @@ nsSynthVoiceRegistry::GetInstance()
|
||||
|
||||
if (!gSynthVoiceRegistry) {
|
||||
gSynthVoiceRegistry = new nsSynthVoiceRegistry();
|
||||
ClearOnShutdown(&gSynthVoiceRegistry);
|
||||
if (XRE_IsParentProcess()) {
|
||||
// Start up all speech synth services.
|
||||
NS_CreateServicesFromCategory(NS_SPEECH_SYNTH_STARTED, nullptr,
|
||||
@ -189,14 +191,6 @@ nsSynthVoiceRegistry::GetInstanceForService()
|
||||
return registry.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsSynthVoiceRegistry::Shutdown()
|
||||
{
|
||||
LOG(LogLevel::Debug, ("[%s] nsSynthVoiceRegistry::Shutdown()",
|
||||
(XRE_IsContentProcess()) ? "Content" : "Default"));
|
||||
gSynthVoiceRegistry = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSynthVoiceRegistry::SendInitialVoicesAndState(SpeechSynthesisParent* aParent)
|
||||
{
|
||||
|
@ -67,8 +67,6 @@ public:
|
||||
|
||||
static void RecvNotifyVoicesChanged();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
virtual ~nsSynthVoiceRegistry();
|
||||
|
||||
|
@ -37,12 +37,6 @@ static const mozilla::Module::CategoryEntry kCategories[] = {
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static void
|
||||
UnloadSpeechDispatcherModule()
|
||||
{
|
||||
SpeechDispatcherService::Shutdown();
|
||||
}
|
||||
|
||||
static const mozilla::Module kModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kCIDs,
|
||||
@ -50,7 +44,7 @@ static const mozilla::Module kModule = {
|
||||
kCategories,
|
||||
nullptr,
|
||||
nullptr,
|
||||
UnloadSpeechDispatcherModule
|
||||
nullptr,
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(synthspeechdispatcher) = &kModule;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "mozilla/dom/nsSpeechTask.h"
|
||||
#include "mozilla/dom/nsSynthVoiceRegistry.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsISupports.h"
|
||||
@ -560,6 +561,7 @@ SpeechDispatcherService::GetInstance(bool create)
|
||||
if (!sSingleton && create) {
|
||||
sSingleton = new SpeechDispatcherService();
|
||||
sSingleton->Init();
|
||||
ClearOnShutdown(&sSingleton);
|
||||
}
|
||||
|
||||
return sSingleton;
|
||||
@ -585,15 +587,5 @@ SpeechDispatcherService::EventNotify(uint32_t aMsgId, uint32_t aState)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpeechDispatcherService::Shutdown()
|
||||
{
|
||||
if (!sSingleton) {
|
||||
return;
|
||||
}
|
||||
|
||||
sSingleton = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -42,8 +42,6 @@ public:
|
||||
static SpeechDispatcherService* GetInstance(bool create = true);
|
||||
static already_AddRefed<SpeechDispatcherService> GetInstanceForService();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
static StaticRefPtr<SpeechDispatcherService> sSingleton;
|
||||
|
||||
private:
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/FakePluginTagInitBinding.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
@ -150,7 +151,7 @@ LazyLogModule nsPluginLogging::gPluginLog(PLUGIN_LOG_NAME);
|
||||
#define DEFAULT_NUMBER_OF_STOPPED_INSTANCES 50
|
||||
|
||||
nsIFile *nsPluginHost::sPluginTempDir;
|
||||
nsPluginHost *nsPluginHost::sInst;
|
||||
StaticRefPtr<nsPluginHost> nsPluginHost::sInst;
|
||||
|
||||
/* to cope with short read */
|
||||
/* we should probably put this into a global library now that this is the second
|
||||
@ -296,7 +297,6 @@ nsPluginHost::~nsPluginHost()
|
||||
PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("nsPluginHost::dtor\n"));
|
||||
|
||||
UnloadPlugins();
|
||||
sInst = nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPluginHost,
|
||||
@ -311,13 +311,10 @@ nsPluginHost::GetInst()
|
||||
{
|
||||
if (!sInst) {
|
||||
sInst = new nsPluginHost();
|
||||
if (!sInst)
|
||||
return nullptr;
|
||||
NS_ADDREF(sInst);
|
||||
ClearOnShutdown(&sInst);
|
||||
}
|
||||
|
||||
RefPtr<nsPluginHost> inst = sInst;
|
||||
return inst.forget();
|
||||
return do_AddRef(sInst);
|
||||
}
|
||||
|
||||
bool nsPluginHost::IsRunningPlugin(nsPluginTag * aPluginTag)
|
||||
@ -3381,7 +3378,6 @@ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
|
||||
{
|
||||
if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
|
||||
UnloadPlugins();
|
||||
sInst->Release();
|
||||
}
|
||||
if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
|
||||
mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define nsPluginHost_h_
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsIObserver.h"
|
||||
@ -415,7 +416,7 @@ private:
|
||||
|
||||
// We need to hold a global ptr to ourselves because we register for
|
||||
// two different CIDs for some reason...
|
||||
static nsPluginHost* sInst;
|
||||
static mozilla::StaticRefPtr<nsPluginHost> sInst;
|
||||
};
|
||||
|
||||
class PluginDestructionGuard : public mozilla::LinkedListElement<PluginDestructionGuard>
|
||||
|
@ -426,6 +426,16 @@ nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
|
||||
aReportOnly, this,
|
||||
aDeliveredViaMetaTag);
|
||||
if (policy) {
|
||||
if (policy->hasDirective(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
|
||||
nsAutoCString selfURIspec, referrer;
|
||||
if (mSelfURI) {
|
||||
mSelfURI->GetAsciiSpec(selfURIspec);
|
||||
}
|
||||
referrer = NS_ConvertUTF16toUTF8(mReferrer);
|
||||
CSPCONTEXTLOG(("nsCSPContext::AppendPolicy added UPGRADE_IF_INSECURE_DIRECTIVE self-uri=%s referrer=%s",
|
||||
selfURIspec.get(), referrer.get()));
|
||||
}
|
||||
|
||||
mPolicies.AppendElement(policy);
|
||||
// reset cache since effective policy changes
|
||||
mShouldLoadCache.Clear();
|
||||
|
@ -67,11 +67,6 @@ support-files =
|
||||
support-files =
|
||||
test_new_window_from_content_child.html
|
||||
[browser_xhr_sandbox.js]
|
||||
[browser_prerendering.js]
|
||||
support-files =
|
||||
prerender.html
|
||||
prerender_target.html
|
||||
skip-if = true || !e10s # Prerendering requires e10s, turned off for e10s-multi Bug 1315042
|
||||
[browser_noopener.js]
|
||||
support-files =
|
||||
test_noopener_source.html
|
||||
|
@ -1,177 +0,0 @@
|
||||
const URL = "https://example.com/browser/dom/tests/browser/prerender.html";
|
||||
const PRERENDERED_URL = "https://example.com/browser/dom/tests/browser/prerender_target.html";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
// Returns a promise which resolves to whether or not PRERENDERED_URL has been visited.
|
||||
function prerenderedVisited() {
|
||||
let uri = Services.io.newURI(PRERENDERED_URL);
|
||||
return new Promise(resolve => {
|
||||
PlacesUtils.asyncHistory.isURIVisited(uri, (aUri, aIsVisited) => {
|
||||
resolve(aIsVisited);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for a process change and then fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("BrowserChangedProcess", function(e) {
|
||||
info("The browser changed process!");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for onbeforeunload dialog, and dismiss it immediately.
|
||||
function awaitAndCloseBeforeUnloadDialog() {
|
||||
return new Promise(resolve => {
|
||||
function onDialogShown(node) {
|
||||
info("Found onbeforeunload dialog");
|
||||
Services.obs.removeObserver(onDialogShown,
|
||||
"tabmodal-dialog-loaded");
|
||||
let dismissButton = node.ui.button0;
|
||||
dismissButton.click();
|
||||
resolve();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onDialogShown, "tabmodal-dialog-loaded");
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true],
|
||||
["dom.linkPrerender.enabled", true],
|
||||
["dom.require_user_interaction_for_beforeunload", false]]
|
||||
});
|
||||
});
|
||||
|
||||
// Test 1: Creating a prerendered browser, and clicking on a link to that browser,
|
||||
// will cause changes.
|
||||
add_task(async function() {
|
||||
await PlacesUtils.history.clear();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, URL);
|
||||
|
||||
is(await prerenderedVisited(), false, "Should not have been visited");
|
||||
|
||||
await new Promise(resolve => {
|
||||
tab.linkedBrowser.messageManager.addMessageListener("Prerender:Request", function f() {
|
||||
tab.linkedBrowser.messageManager.removeMessageListener("Prerender:Request", f);
|
||||
info("Successfully received the prerender request");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab);
|
||||
|
||||
is(await prerenderedVisited(), false, "Should not have been visited");
|
||||
|
||||
// Check that visibilityState is set correctly in the prerendered tab. We
|
||||
// check all of the tabs because we have no easy way to tell which one is
|
||||
// which.
|
||||
let foundTab;
|
||||
for (let i = 0; i < gBrowser.tabs.length; ++i) {
|
||||
foundTab = await ContentTask.spawn(gBrowser.tabs[i].linkedBrowser, null,
|
||||
() => content.document.visibilityState == "prerender");
|
||||
if (foundTab) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(foundTab, "The prerender tab was found!");
|
||||
|
||||
let dialogShown = awaitAndCloseBeforeUnloadDialog();
|
||||
ContentTask.spawn(tab.linkedBrowser, null, async function() {
|
||||
let anchor = content.document.querySelector("a");
|
||||
anchor.click();
|
||||
});
|
||||
await dialogShown;
|
||||
|
||||
await awaitProcessChange(tab.linkedBrowser);
|
||||
|
||||
await ContentTask.spawn(tab.linkedBrowser, PRERENDERED_URL, async function(PRERENDERED_URL) {
|
||||
is(content.document.location.toString(), PRERENDERED_URL);
|
||||
isnot(content.document.visibilityState, "prerender",
|
||||
"VisibilityState of formerly prerendered window must not be prerender");
|
||||
});
|
||||
|
||||
is(await prerenderedVisited(), true, "Should have been visited");
|
||||
|
||||
let groupedSHistory = tab.linkedBrowser.frameLoader.groupedSHistory;
|
||||
is(groupedSHistory.count, 2, "Check total length of grouped shistory.");
|
||||
is(gBrowser.tabs.length, 3, "Check number of opened tabs.");
|
||||
|
||||
// We don't touch the about:blank tab opened when browser mochitest runs.
|
||||
// The tabs under test are the other 2 tabs, so we're expecting 2 TabClose.
|
||||
let closed = new Promise(resolve => {
|
||||
let seen = 0;
|
||||
gBrowser.tabContainer.addEventListener("TabClose", function f() {
|
||||
if (++seen == 2) {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", f);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
await closed;
|
||||
|
||||
is(await prerenderedVisited(), true, "Should have been visited");
|
||||
|
||||
is(gBrowser.tabs.length, 1);
|
||||
});
|
||||
|
||||
// Test 2: Creating a prerendered browser, and navigating to a different url,
|
||||
// succeeds, and closes the prerendered browser.
|
||||
add_task(async function() {
|
||||
await PlacesUtils.history.clear();
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, URL);
|
||||
|
||||
is(await prerenderedVisited(), false, "Should not have been visited");
|
||||
|
||||
await Promise.all([
|
||||
BrowserTestUtils.browserLoaded(tab.linkedBrowser),
|
||||
new Promise(resolve => {
|
||||
tab.linkedBrowser.messageManager.addMessageListener("Prerender:Request", function f() {
|
||||
tab.linkedBrowser.messageManager.removeMessageListener("Prerender:Request", f);
|
||||
info("Successfully received the prerender request");
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
BrowserTestUtils.switchTab(gBrowser, tab),
|
||||
]);
|
||||
|
||||
let dialogShown = awaitAndCloseBeforeUnloadDialog();
|
||||
ContentTask.spawn(tab.linkedBrowser, null, async function() {
|
||||
let anchor = content.document.querySelector("a");
|
||||
anchor.setAttribute("href", "data:text/html,something_else");
|
||||
anchor.click();
|
||||
});
|
||||
await dialogShown;
|
||||
|
||||
is(await prerenderedVisited(), false, "Should not have been visited");
|
||||
|
||||
await Promise.all([
|
||||
BrowserTestUtils.browserLoaded(tab.linkedBrowser),
|
||||
new Promise(resolve => {
|
||||
let seen = false;
|
||||
gBrowser.tabContainer.addEventListener("TabClose", function() {
|
||||
if (!seen) {
|
||||
seen = true;
|
||||
info("The tab was closed");
|
||||
resolve();
|
||||
}
|
||||
}, {once: true});
|
||||
}),
|
||||
]);
|
||||
|
||||
await ContentTask.spawn(tab.linkedBrowser, null, async function() {
|
||||
is(content.document.location.toString(), "data:text/html,something_else");
|
||||
});
|
||||
|
||||
is(await prerenderedVisited(), false, "Should not have been visited");
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<head><title>Prerender Test</title></head>
|
||||
<body onbeforeunload="return 'stay with me';">
|
||||
<link rel="prerender" href="https://example.com/browser/dom/tests/browser/prerender_target.html">
|
||||
<a href="https://example.com/browser/dom/tests/browser/prerender_target.html">clicky here</a>
|
||||
</body>
|
||||
</html>
|
@ -1,4 +0,0 @@
|
||||
<!doctype html>
|
||||
<body>
|
||||
<p>This is just a random HTML document which will be loaded as a target for prerendering.</p>
|
||||
</body>
|
@ -25,8 +25,10 @@ function finishBlockedRequest(request, response, query)
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "application/javascript", false);
|
||||
response.write("window.script_executed_" + query[1] + " = true; ok(true, 'Script " + query[1] + " executed');");
|
||||
response.write("scriptLoaded('" + query[1] + "');");
|
||||
response.finish();
|
||||
|
||||
setGlobalState(undefined, query[1]);
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
@ -37,7 +39,7 @@ function handleRequest(request, response)
|
||||
var alreadyUnblocked = getGlobalState(query[1]);
|
||||
|
||||
response.processAsync();
|
||||
if (alreadyUnblocked) {
|
||||
if (alreadyUnblocked === true) {
|
||||
// the unblock request came before the blocked request, just go on and finish synchronously
|
||||
finishBlockedRequest(request, response, query);
|
||||
} else {
|
||||
@ -52,10 +54,10 @@ function handleRequest(request, response)
|
||||
response.write("\x89PNG"); // just a broken image is enough for our purpose
|
||||
|
||||
var blockedResponse = getGlobalState(query[1]);
|
||||
if (!blockedResponse) {
|
||||
if (blockedResponse === undefined) {
|
||||
// the unblock request came before the blocked request, remember to not block it
|
||||
setGlobalState(true, query[1]);
|
||||
} else {
|
||||
} else if (typeof blockedResponse == "object") {
|
||||
finishBlockedRequest(request, blockedResponse, query);
|
||||
}
|
||||
break;
|
||||
|
@ -3,5 +3,4 @@ support-files =
|
||||
file_blocked_script.sjs
|
||||
|
||||
[test_bug1053321.html]
|
||||
skip-if = os == 'android' # bug 1386644
|
||||
[test_whitespace.html]
|
||||
|
@ -10,32 +10,41 @@ are unexpectedly blocked.
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script>
|
||||
// The two scripts below are expected to load and call scriptLoaded().
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.expected_scripts = {
|
||||
"defer": true,
|
||||
"async": true,
|
||||
};
|
||||
|
||||
function scriptLoaded(script)
|
||||
{
|
||||
ok(true, 'Script ' + script + ' executed');
|
||||
delete window.expected_scripts[script];
|
||||
|
||||
let expecting = Object.keys(window.expected_scripts).length;
|
||||
info("Expecting " + expecting + " more script(s) to execute");
|
||||
|
||||
if (expecting == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- this script is not loaded until file_blocked_script.sjs?unblock&defer request is made,
|
||||
when this script is executed, it sets window.script_executed_defer to true
|
||||
when this script is executed, it calls SimpleTest.finish().
|
||||
-->
|
||||
<script defer src="file_blocked_script.sjs?blocked&defer"></script>
|
||||
|
||||
<!-- this script is not loaded until file_blocked_script.sjs?unblock&async request is made,
|
||||
when this script is executed, it sets window.script_executed_async to true
|
||||
when this script is executed, it calls SimpleTest.finish().
|
||||
-->
|
||||
<script async src="file_blocked_script.sjs?blocked&async"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// We can't test whether the two scripts have not been executed here, since
|
||||
// preloads of the two images below (that unblock the two tested <head>
|
||||
// scripts) may happen sooner than this script executes.
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
ok(window.script_executed_defer, "Deferred script executed before DOMContentLoaded");
|
||||
});
|
||||
window.addEventListener("load", function() {
|
||||
ok(window.script_executed_async, "Async script executed before onload");
|
||||
SimpleTest.finish();
|
||||
}, true);
|
||||
</script>
|
||||
<img src="file_blocked_script.sjs?unblock&defer"/>
|
||||
<img src="file_blocked_script.sjs?unblock&async"/>
|
||||
</body>
|
||||
|
@ -31,9 +31,6 @@ with Files("browser/browser_cancel_keydown_keypress_event.js"):
|
||||
with Files("browser/*local*"):
|
||||
BUG_COMPONENT = ("Core", "DOM")
|
||||
|
||||
with Files("browser/*prerender*"):
|
||||
BUG_COMPONENT = ("Core", "Document Navigation")
|
||||
|
||||
with Files("browser/browser_test_focus_after_modal_state.js"):
|
||||
BUG_COMPONENT = ("Core", "Event Handling")
|
||||
|
||||
|
@ -32,7 +32,7 @@ interface AudioBufferSourceNode : AudioScheduledSourceNode {
|
||||
attribute double loopStart;
|
||||
attribute double loopEnd;
|
||||
|
||||
[Throws, UnsafeInPrerendering]
|
||||
[Throws]
|
||||
void start(optional double when = 0, optional double grainOffset = 0,
|
||||
optional double grainDuration);
|
||||
};
|
||||
|
@ -22,10 +22,10 @@ interface AudioContext : BaseAudioContext {
|
||||
[Throws]
|
||||
Promise<void> close();
|
||||
|
||||
[NewObject, Throws, UnsafeInPrerendering]
|
||||
[NewObject, Throws]
|
||||
MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
|
||||
|
||||
[NewObject, Throws, UnsafeInPrerendering]
|
||||
[NewObject, Throws]
|
||||
MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
|
||||
|
||||
// Bug 1324548: MediaStreamTrackAudioSourceNode createMediaStreamTrackSource (AudioMediaStreamTrack mediaStreamTrack);
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
interface AudioScheduledSourceNode : AudioNode {
|
||||
attribute EventHandler onended;
|
||||
[Throws, UnsafeInPrerendering]
|
||||
[Throws]
|
||||
void start (optional double when = 0);
|
||||
|
||||
[Throws, UnsafeInPrerendering]
|
||||
[Throws]
|
||||
void stop (optional double when = 0);
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ interface URI;
|
||||
interface nsIDocShell;
|
||||
interface nsILoadGroup;
|
||||
|
||||
enum VisibilityState { "hidden", "visible", "prerender" };
|
||||
enum VisibilityState { "hidden", "visible" };
|
||||
|
||||
/* https://dom.spec.whatwg.org/#dictdef-elementcreationoptions */
|
||||
dictionary ElementCreationOptions {
|
||||
|
@ -103,7 +103,7 @@ interface Element : Node {
|
||||
boolean mozMatchesSelector(DOMString selector);
|
||||
|
||||
// Pointer events methods.
|
||||
[Throws, Pref="dom.w3c_pointer_events.enabled", UnsafeInPrerendering]
|
||||
[Throws, Pref="dom.w3c_pointer_events.enabled"]
|
||||
void setPointerCapture(long pointerId);
|
||||
|
||||
[Throws, Pref="dom.w3c_pointer_events.enabled"]
|
||||
@ -276,14 +276,14 @@ Element implements GeometryUtils;
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#api
|
||||
partial interface Element {
|
||||
[Throws, UnsafeInPrerendering, Func="nsDocument::IsUnprefixedFullscreenEnabled", NeedsCallerType]
|
||||
[Throws, Func="nsDocument::IsUnprefixedFullscreenEnabled", NeedsCallerType]
|
||||
void requestFullscreen();
|
||||
[Throws, UnsafeInPrerendering, BinaryName="requestFullscreen", NeedsCallerType]
|
||||
[Throws, BinaryName="requestFullscreen", NeedsCallerType]
|
||||
void mozRequestFullScreen();
|
||||
};
|
||||
|
||||
// https://w3c.github.io/pointerlock/#extensions-to-the-element-interface
|
||||
partial interface Element {
|
||||
[UnsafeInPrerendering, NeedsCallerType]
|
||||
[NeedsCallerType]
|
||||
void requestPointerLock();
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user