mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 1192122 - Safe mode startup, Part 2: shell.js hook r=ferjm
This commit is contained in:
parent
97a01329d8
commit
a5da7a70bf
@ -9,8 +9,12 @@ let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let isMulet = "ResponsiveUI" in browserWindow;
|
||||
Cu.import("resource://gre/modules/GlobalSimulatorScreen.jsm");
|
||||
|
||||
// We do this on ContentStart because querying the displayDPI fails otherwise.
|
||||
window.addEventListener('ContentStart', function() {
|
||||
window.addEventListener('ContentStart', onStart);
|
||||
window.addEventListener('SafeModeStart', onStart);
|
||||
|
||||
// We do this on ContentStart and SafeModeStart because querying the
|
||||
// displayDPI fails otherwise.
|
||||
function onStart() {
|
||||
// This is the toplevel <window> element
|
||||
let shell = document.getElementById('shell');
|
||||
|
||||
@ -262,4 +266,4 @@ window.addEventListener('ContentStart', function() {
|
||||
// Exit the b2g client
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -77,6 +77,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
|
||||
"resource://gre/modules/SafeBrowsing.jsm");
|
||||
#endif
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SafeMode",
|
||||
"resource://gre/modules/SafeMode.jsm");
|
||||
|
||||
window.performance.measure('gecko-shell-jsm-loaded', 'gecko-shell-loadstart');
|
||||
|
||||
function getContentWindow() {
|
||||
@ -238,17 +241,21 @@ var shell = {
|
||||
#endif
|
||||
|
||||
window.performance.mark('gecko-shell-bootstrap');
|
||||
let startManifestURL =
|
||||
Cc['@mozilla.org/commandlinehandler/general-startup;1?type=b2gbootstrap']
|
||||
.getService(Ci.nsISupports).wrappedJSObject.startManifestURL;
|
||||
if (startManifestURL) {
|
||||
Cu.import('resource://gre/modules/Bootstraper.jsm');
|
||||
Bootstraper.ensureSystemAppInstall(startManifestURL)
|
||||
.then(this.start.bind(this))
|
||||
.catch(Bootstraper.bailout);
|
||||
} else {
|
||||
this.start();
|
||||
}
|
||||
|
||||
// Before anything, check if we want to start in safe mode.
|
||||
SafeMode.check(window).then(() => {
|
||||
let startManifestURL =
|
||||
Cc['@mozilla.org/commandlinehandler/general-startup;1?type=b2gbootstrap']
|
||||
.getService(Ci.nsISupports).wrappedJSObject.startManifestURL;
|
||||
if (startManifestURL) {
|
||||
Cu.import('resource://gre/modules/Bootstraper.jsm');
|
||||
Bootstraper.ensureSystemAppInstall(startManifestURL)
|
||||
.then(this.start.bind(this))
|
||||
.catch(Bootstraper.bailout);
|
||||
} else {
|
||||
this.start();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
start: function shell_start() {
|
||||
|
151
b2g/components/SafeMode.jsm
Normal file
151
b2g/components/SafeMode.jsm
Normal file
@ -0,0 +1,151 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SafeMode"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
|
||||
const kSafeModePref = "b2g.safe_mode";
|
||||
const kSafeModePage = "safe_mode.html";
|
||||
|
||||
function debug(aStr) {
|
||||
//dump("-*- SafeMode: " + aStr + "\n");
|
||||
}
|
||||
|
||||
// This module is responsible for checking whether we want to start in safe
|
||||
// mode or not. The flow is as follow:
|
||||
// - wait for the `b2g.safe_mode` preference to be set to something different
|
||||
// than `unset` by nsAppShell
|
||||
// - If it's set to `no`, just start normally.
|
||||
// - If it's set to `yes`, we load a stripped down system app from safe_mode.html"
|
||||
// - This page is responsible to dispatch a mozContentEvent to us.
|
||||
// - If the user choose SafeMode, we disable all add-ons.
|
||||
// - We go on with startup.
|
||||
|
||||
this.SafeMode = {
|
||||
// Returns a promise that resolves when nsAppShell has set the
|
||||
// b2g.safe_mode_state_ready preference to `true`.
|
||||
_waitForPref: function() {
|
||||
debug("waitForPref");
|
||||
try {
|
||||
let currentMode = Services.prefs.getCharPref(kSafeModePref);
|
||||
debug("current mode: " + currentMode);
|
||||
if (currentMode !== "unset") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
} catch(e) { debug("No current mode available!"); }
|
||||
|
||||
// Wait for the preference to toggle.
|
||||
return new Promise((aResolve, aReject) => {
|
||||
let observer = function(aSubject, aTopic, aData) {
|
||||
if (Services.prefs.getCharPref(kSafeModePref)) {
|
||||
Services.prefs.removeObserver(kSafeModePref, observer, false);
|
||||
aResolve();
|
||||
}
|
||||
}
|
||||
|
||||
Services.prefs.addObserver(kSafeModePref, observer, false);
|
||||
});
|
||||
},
|
||||
|
||||
// Resolves once the user has decided how to start.
|
||||
// Note that all the actions happen here, so there is no other action from
|
||||
// consumers than to go on.
|
||||
_waitForUser: function() {
|
||||
debug("waitForUser");
|
||||
let isSafeMode = Services.prefs.getCharPref(kSafeModePref) === "yes";
|
||||
if (!isSafeMode) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
debug("Starting in Safe Mode!");
|
||||
|
||||
// Load $system_app/safe_mode.html as a full screen iframe, and wait for
|
||||
// the user to make a choice.
|
||||
return DOMApplicationRegistry.registryReady.then(() => {
|
||||
let shell = SafeMode.window.shell;
|
||||
let document = SafeMode.window.document;
|
||||
|
||||
let url = Services.io.newURI(shell.homeURL, null, null)
|
||||
.resolve(kSafeModePage);
|
||||
debug("Registry is ready, loading " + url);
|
||||
let frame = document.createElementNS("http://www.w3.org/1999/xhtml", "html:iframe");
|
||||
frame.setAttribute("mozbrowser", "true");
|
||||
frame.setAttribute("mozapp", shell.manifestURL);
|
||||
frame.setAttribute("id", "systemapp"); // To keep screen.js happy.
|
||||
let contentBrowser = document.body.appendChild(frame);
|
||||
|
||||
return new Promise((aResolve, aReject) => {
|
||||
let content = contentBrowser.contentWindow;
|
||||
|
||||
// Stripped down version of the system app bootstrap.
|
||||
function handleEvent(e) {
|
||||
switch(e.type) {
|
||||
case "mozbrowserloadstart":
|
||||
if (content.document.location == "about:blank") {
|
||||
contentBrowser.addEventListener("mozbrowserlocationchange", handleEvent, true);
|
||||
contentBrowser.removeEventListener("mozbrowserloadstart", handleEvent, true);
|
||||
return;
|
||||
}
|
||||
|
||||
notifyContentStart();
|
||||
break;
|
||||
case "mozbrowserlocationchange":
|
||||
if (content.document.location == "about:blank") {
|
||||
return;
|
||||
}
|
||||
|
||||
contentBrowser.removeEventListener("mozbrowserlocationchange", handleEvent, true);
|
||||
notifyContentStart();
|
||||
break;
|
||||
case "mozContentEvent":
|
||||
content.removeEventListener("mozContentEvent", handleEvent, true);
|
||||
contentBrowser.parentNode.removeChild(contentBrowser);
|
||||
|
||||
if (e.detail == "safemode-yes") {
|
||||
// Really starting in safe mode, let's disable add-ons first.
|
||||
DOMApplicationRegistry.disableAllAddons().then(aResolve);
|
||||
} else {
|
||||
aResolve();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function notifyContentStart() {
|
||||
let window = SafeMode.window;
|
||||
window.shell.sendEvent(window, "SafeModeStart");
|
||||
contentBrowser.setVisible(true);
|
||||
|
||||
// browser-ui-startup-complete is used by the AppShell to stop the
|
||||
// boot animation and start gecko rendering.
|
||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
content.addEventListener("mozContentEvent", handleEvent, true);
|
||||
}
|
||||
|
||||
contentBrowser.addEventListener("mozbrowserloadstart", handleEvent, true);
|
||||
contentBrowser.src = url;
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Returns a Promise that resolves once we have decided to run in safe mode
|
||||
// or not. All the safe mode switching actions happen before resolving the
|
||||
// promise.
|
||||
check: function(aWindow) {
|
||||
debug("check");
|
||||
this.window = aWindow;
|
||||
if (AppConstants.platform !== "gonk") {
|
||||
// For now we only have gonk support.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return this._waitForPref().then(this._waitForUser);
|
||||
}
|
||||
}
|
@ -68,6 +68,7 @@ EXTRA_JS_MODULES += [
|
||||
'LogParser.jsm',
|
||||
'LogShake.jsm',
|
||||
'OrientationChangeHandler.jsm',
|
||||
'SafeMode.jsm',
|
||||
'Screenshot.jsm',
|
||||
'SignInToWebsite.jsm',
|
||||
'SystemAppProxy.jsm',
|
||||
|
@ -4539,6 +4539,25 @@ this.DOMApplicationRegistry = {
|
||||
}
|
||||
},
|
||||
|
||||
// Returns a promise that resolves once all the add-ons are disabled.
|
||||
disableAllAddons: function() {
|
||||
for (let id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
if (app.role == "addon" && app.enabled) {
|
||||
app.enabled = false;
|
||||
MessageBroadcaster.broadcastMessage("Webapps:UpdateState", {
|
||||
app: app,
|
||||
id: app.id
|
||||
});
|
||||
MessageBroadcaster.broadcastMessage("Webapps:SetEnabled:Return", app);
|
||||
|
||||
UserCustomizations.unregister(app);
|
||||
}
|
||||
}
|
||||
|
||||
return this._saveApps();
|
||||
},
|
||||
|
||||
getManifestFor: function(aManifestURL, aEntryPoint) {
|
||||
let id = this._appIdForManifestURL(aManifestURL);
|
||||
let app = this.webapps[id];
|
||||
|
Loading…
Reference in New Issue
Block a user