зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1080055: When recreating a browser restore the isAppTab attribute on the docshell. r=mconley.
This commit is contained in:
Родитель
c367a078a7
Коммит
cf49a93879
|
@ -1485,10 +1485,12 @@
|
|||
// Restore the progress listener.
|
||||
aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
|
||||
if (aShouldBeRemote)
|
||||
if (aShouldBeRemote) {
|
||||
tab.setAttribute("remote", "true");
|
||||
else
|
||||
} else {
|
||||
tab.removeAttribute("remote");
|
||||
aBrowser.messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: tab.pinned })
|
||||
}
|
||||
|
||||
if (wasActive)
|
||||
aBrowser.focus();
|
||||
|
@ -3099,6 +3101,13 @@
|
|||
window.focus();
|
||||
break;
|
||||
}
|
||||
case "Browser:Init": {
|
||||
let tab = this.getTabForBrowser(browser);
|
||||
if (!tab)
|
||||
return;
|
||||
browser.messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: tab.pinned })
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -3156,6 +3165,7 @@
|
|||
messageManager.addMessageListener("DOMTitleChanged", this);
|
||||
messageManager.addMessageListener("DOMWindowClose", this);
|
||||
messageManager.addMessageListener("contextmenu", this);
|
||||
messageManager.addMessageListener("Browser:Init", this);
|
||||
|
||||
// If this window has remote tabs, switch to our tabpanels fork
|
||||
// which does asynchronous tab switching.
|
||||
|
|
|
@ -394,6 +394,7 @@ skip-if = buildapp == 'mulet'
|
|||
[browser_removeTabsToTheEnd.js]
|
||||
[browser_removeUnsafeProtocolsFromURLBarPaste.js]
|
||||
skip-if = e10s
|
||||
[browser_restore_isAppTab.js]
|
||||
[browser_sanitize-download-history.js]
|
||||
skip-if = true # bug 432425
|
||||
[browser_sanitize-passwordDisabledHosts.js]
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const DUMMY = "http://example.com/browser/browser/base/content/test/general/dummy_page.html";
|
||||
|
||||
function getMinidumpDirectory() {
|
||||
let dir = Services.dirsvc.get('ProfD', Ci.nsIFile);
|
||||
dir.append("minidumps");
|
||||
return dir;
|
||||
}
|
||||
|
||||
// This observer is needed so we can clean up all evidence of the crash so
|
||||
// the testrunner thinks things are peachy.
|
||||
let CrashObserver = {
|
||||
observe: function(subject, topic, data) {
|
||||
is(topic, 'ipc:content-shutdown', 'Received correct observer topic.');
|
||||
ok(subject instanceof Ci.nsIPropertyBag2,
|
||||
'Subject implements nsIPropertyBag2.');
|
||||
// we might see this called as the process terminates due to previous tests.
|
||||
// We are only looking for "abnormal" exits...
|
||||
if (!subject.hasKey("abnormal")) {
|
||||
info("This is a normal termination and isn't the one we are looking for...");
|
||||
return;
|
||||
}
|
||||
|
||||
let dumpID;
|
||||
if ('nsICrashReporter' in Ci) {
|
||||
dumpID = subject.getPropertyAsAString('dumpID');
|
||||
ok(dumpID, "dumpID is present and not an empty string");
|
||||
}
|
||||
|
||||
if (dumpID) {
|
||||
let minidumpDirectory = getMinidumpDirectory();
|
||||
let file = minidumpDirectory.clone();
|
||||
file.append(dumpID + '.dmp');
|
||||
file.remove(true);
|
||||
file = minidumpDirectory.clone();
|
||||
file.append(dumpID + '.extra');
|
||||
file.remove(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(CrashObserver, 'ipc:content-shutdown', false);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.obs.removeObserver(CrashObserver, 'ipc:content-shutdown');
|
||||
});
|
||||
|
||||
function frameScript() {
|
||||
addMessageListener("Test:GetIsAppTab", function() {
|
||||
sendAsyncMessage("Test:IsAppTab", { isAppTab: docShell.isAppTab });
|
||||
});
|
||||
|
||||
addMessageListener("Test:Crash", function() {
|
||||
privateNoteIntentionalCrash();
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
let zero = new ctypes.intptr_t(8);
|
||||
let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
|
||||
badptr.contents
|
||||
});
|
||||
}
|
||||
|
||||
function loadFrameScript(browser) {
|
||||
browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
|
||||
}
|
||||
|
||||
function isBrowserAppTab(browser) {
|
||||
return new Promise(resolve => {
|
||||
function listener({ data }) {
|
||||
browser.messageManager.removeMessageListener("Test:IsAppTab", listener);
|
||||
resolve(data.isAppTab);
|
||||
}
|
||||
browser.messageManager.addMessageListener("Test:IsAppTab", listener);
|
||||
browser.messageManager.sendAsyncMessage("Test:GetIsAppTab");
|
||||
});
|
||||
}
|
||||
|
||||
// Restarts the child process by crashing it then reloading the tab
|
||||
let restart = Task.async(function*(browser) {
|
||||
// If the tab isn't remote this would crash the main process so skip it
|
||||
if (!browser.isRemoteBrowser)
|
||||
return browser;
|
||||
|
||||
// Make sure the main process has all of the current tab state before crashing
|
||||
TabState.flush(browser);
|
||||
|
||||
browser.messageManager.sendAsyncMessage("Test:Crash");
|
||||
yield promiseWaitForEvent(browser, "AboutTabCrashedLoad", false, true);
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
SessionStore.reviveCrashedTab(tab);
|
||||
|
||||
yield promiseTabLoaded(tab);
|
||||
});
|
||||
|
||||
add_task(function* navigate() {
|
||||
let tab = gBrowser.addTab("about:robots");
|
||||
let browser = tab.linkedBrowser;
|
||||
gBrowser.selectedTab = tab;
|
||||
yield waitForDocLoadComplete();
|
||||
loadFrameScript(browser);
|
||||
let isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(!isAppTab, "Docshell shouldn't think it is an app tab");
|
||||
|
||||
gBrowser.pinTab(tab);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(isAppTab, "Docshell should think it is an app tab");
|
||||
|
||||
gBrowser.loadURI(DUMMY);
|
||||
yield waitForDocLoadComplete();
|
||||
loadFrameScript(browser);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(isAppTab, "Docshell should think it is an app tab");
|
||||
|
||||
gBrowser.unpinTab(tab);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(!isAppTab, "Docshell shouldn't think it is an app tab");
|
||||
|
||||
gBrowser.pinTab(tab);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(isAppTab, "Docshell should think it is an app tab");
|
||||
|
||||
gBrowser.loadURI("about:robots");
|
||||
yield waitForDocLoadComplete();
|
||||
loadFrameScript(browser);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(isAppTab, "Docshell should think it is an app tab");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* crash() {
|
||||
if (!gMultiProcessBrowser || !("nsICrashReporter" in Ci))
|
||||
return;
|
||||
|
||||
let tab = gBrowser.addTab(DUMMY);
|
||||
let browser = tab.linkedBrowser;
|
||||
gBrowser.selectedTab = tab;
|
||||
yield waitForDocLoadComplete();
|
||||
loadFrameScript(browser);
|
||||
let isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(!isAppTab, "Docshell shouldn't think it is an app tab");
|
||||
|
||||
gBrowser.pinTab(tab);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(isAppTab, "Docshell should think it is an app tab");
|
||||
|
||||
yield restart(browser);
|
||||
loadFrameScript(browser);
|
||||
isAppTab = yield isBrowserAppTab(browser);
|
||||
ok(isAppTab, "Docshell should think it is an app tab");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
|
@ -108,16 +108,16 @@ function promiseWaitForCondition(aConditionFn) {
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseWaitForEvent(object, eventName, capturing = false) {
|
||||
function promiseWaitForEvent(object, eventName, capturing = false, chrome = false) {
|
||||
return new Promise((resolve) => {
|
||||
function listener(event) {
|
||||
info("Saw " + eventName);
|
||||
object.removeEventListener(eventName, listener, capturing);
|
||||
object.removeEventListener(eventName, listener, capturing, chrome);
|
||||
resolve(event);
|
||||
}
|
||||
|
||||
info("Waiting for " + eventName);
|
||||
object.addEventListener(eventName, listener, capturing);
|
||||
object.addEventListener(eventName, listener, capturing, chrome);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче