Merge inbound to mozilla-central r=merge a=merge

This commit is contained in:
Coroiu Cristina 2018-01-13 11:55:23 +02:00
commit c6a942e1bf
9077 changed files with 25253 additions and 32672 deletions

View File

@ -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}'

View File

@ -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;
}
};

View File

@ -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",

View File

@ -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.

View File

@ -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");
});

View File

@ -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) {

View File

@ -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 + "'");

View File

@ -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]

View File

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

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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_

View File

@ -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',
]

View File

@ -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));

View File

@ -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;

View File

@ -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.
*/

View File

@ -6,9 +6,6 @@
XPIDL_SOURCES += [
'nsIBFCacheEntry.idl',
'nsIGroupedSHistory.idl',
'nsIPartialSHistory.idl',
'nsIPartialSHistoryListener.idl',
'nsISHContainer.idl',
'nsISHEntry.idl',
'nsISHistory.idl',

View File

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

View File

@ -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();
};

View File

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

View File

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

View File

@ -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;

View File

@ -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;
};

View File

@ -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]

View File

@ -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.
});
});

View File

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

View File

@ -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");
});
});

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -11,6 +11,7 @@
#include "mozilla/Preferences.h"
#include "nsPresContext.h"
#include "RuleNodeCacheConditions.h"
#include "nsGlobalWindowInner.h"
namespace mozilla {
namespace dom {

View File

@ -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',

View File

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

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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")

View File

@ -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,

View File

@ -1166,8 +1166,6 @@ public:
void FireOfflineStatusEventIfChanged();
bool GetIsPrerendered();
public:
// Inner windows only.
nsresult ScheduleNextIdleObserverCallback();

View File

@ -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)
{

View File

@ -908,8 +908,6 @@ public:
const nsAString &aPopupWindowName,
const nsAString &aPopupWindowFeatures);
bool GetIsPrerendered();
private:
void ReportLargeAllocStatus();

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -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)
{

View File

@ -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;
}

View File

@ -64,7 +64,7 @@ public:
eNEXT = 0x00000008,
eALTERNATE = 0x00000010,
ePRECONNECT = 0x00000020,
ePRERENDER = 0x00000040,
// NOTE: 0x40 is unused
ePRELOAD = 0x00000080
};

View File

@ -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]

View File

@ -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>

View File

@ -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>

View File

@ -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)
{

View File

@ -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);

View File

@ -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')

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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]

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -8086,3 +8086,6 @@ HTMLMediaElement::ReportCanPlayTelemetry()
} // namespace dom
} // namespace mozilla
#undef LOG
#undef LOG_EVENT

View File

@ -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

View File

@ -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()
{

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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)
{

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -67,8 +67,6 @@ public:
static void RecvNotifyVoicesChanged();
static void Shutdown();
private:
virtual ~nsSynthVoiceRegistry();

View File

@ -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;

View File

@ -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

View File

@ -42,8 +42,6 @@ public:
static SpeechDispatcherService* GetInstance(bool create = true);
static already_AddRefed<SpeechDispatcherService> GetInstanceForService();
static void Shutdown();
static StaticRefPtr<SpeechDispatcherService> sSingleton;
private:

View File

@ -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);

View File

@ -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>

View File

@ -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();

View File

@ -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

View File

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

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -3,5 +3,4 @@ support-files =
file_blocked_script.sjs
[test_bug1053321.html]
skip-if = os == 'android' # bug 1386644
[test_whitespace.html]

View File

@ -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>

View File

@ -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")

View File

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

View File

@ -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);

View File

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

View File

@ -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 {

View File

@ -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