diff --git a/build/pgo/index.html b/build/pgo/index.html index 7e6ce301d9e..6bba02400cf 100644 --- a/build/pgo/index.html +++ b/build/pgo/index.html @@ -2,117 +2,7 @@ /* 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/. */ - - function quitHook() - { - var xhr = new XMLHttpRequest(); - xhr.open("GET", "http://" + location.host + "/server/shutdown", true); - xhr.onreadystatechange = function (event) - { - if (xhr.readyState == 4) - goQuitApplication(); - }; - xhr.send(null); - } - - function canQuitApplication() - { - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - if (!os) - { - return true; - } - - try - { - var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"] - .createInstance(Components.interfaces.nsISupportsPRBool); - os.notifyObservers(cancelQuit, "quit-application-requested", null); - - // Something aborted the quit process. - if (cancelQuit.data) - { - return false; - } - } - catch (ex) - { - } - os.notifyObservers(null, "quit-application-granted", null); - return true; - } - - function goQuitApplication() - { - const privs = 'UniversalXPConnect'; - - try - { - netscape.security.PrivilegeManager.enablePrivilege(privs); - } - catch(ex) - { - throw('goQuitApplication: privilege failure ' + ex); - } - - if (!canQuitApplication()) - { - return false; - } - - const kAppStartup = '@mozilla.org/toolkit/app-startup;1'; - const kAppShell = '@mozilla.org/appshell/appShellService;1'; - var appService; - var forceQuit; - - if (kAppStartup in Components.classes) - { - appService = Components.classes[kAppStartup]. - getService(Components.interfaces.nsIAppStartup); - forceQuit = Components.interfaces.nsIAppStartup.eForceQuit; - - } - else if (kAppShell in Components.classes) - { - appService = Components.classes[kAppShell]. - getService(Components.interfaces.nsIAppShellService); - forceQuit = Components.interfaces.nsIAppShellService.eForceQuit; - } - else - { - throw 'goQuitApplication: no AppStartup/appShell'; - } - - var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(); - - var windowManagerInterface = windowManager. - QueryInterface(Components.interfaces.nsIWindowMediator); - - var enumerator = windowManagerInterface.getEnumerator(null); - - while (enumerator.hasMoreElements()) - { - var domWindow = enumerator.getNext(); - if (("tryToClose" in domWindow) && !domWindow.tryToClose()) - { - return false; - } - domWindow.close(); - } - - try - { - appService.quit(forceQuit); - } - catch(ex) - { - throw('goQuitApplication: ' + ex); - } - - return true; - } - + var list = [ "blueprint/sample.html", @@ -162,7 +52,7 @@ if (idx < list.length) { window.setTimeout(loadURL, interval); } else { - window.setTimeout(goQuitApplication, interval); + window.setTimeout(Quitter.quit, interval); } } var i; diff --git a/build/pgo/profileserver.py b/build/pgo/profileserver.py index fae1775e37d..912684a6a27 100644 --- a/build/pgo/profileserver.py +++ b/build/pgo/profileserver.py @@ -48,7 +48,7 @@ if __name__ == '__main__': prefs[pref] = Preferences.cast(prefs[pref]) profile = FirefoxProfile(profile=profilePath, preferences=prefs, - #addons=[os.path.join(here, 'extension')], + addons=[os.path.join(build.distdir, 'xpi-stage', 'quitter')], locations=locations) env = os.environ.copy() diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild index fc0bf8a1f26..ac6a81e62e8 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -181,6 +181,8 @@ add_tier_dir('platform', 'addon-sdk') if CONFIG['ENABLE_MARIONETTE'] or CONFIG['MOZ_WIDGET_TOOLKIT'] not in ('gonk', 'android'): add_tier_dir('platform', 'testing/marionette') +add_tier_dir('platform', 'tools/quitter') + if CONFIG['ENABLE_TESTS']: add_tier_dir('platform', [ 'testing/mochitest', diff --git a/tools/quitter/Makefile.in b/tools/quitter/Makefile.in new file mode 100644 index 00000000000..8a4fd6e1ba2 --- /dev/null +++ b/tools/quitter/Makefile.in @@ -0,0 +1,20 @@ +# +# 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 $(DEPTH)/config/autoconf.mk + +XPI_NAME = quitter +XPI_PKGNAME = quitter@mozilla.org +NO_JS_MANIFEST = 1 + +DIST_FILES = \ + install.rdf \ + chrome.manifest \ + $(NULL) + +# Used in install.rdf +USE_EXTENSION_MANIFEST=1 + +include $(topsrcdir)/config/rules.mk diff --git a/tools/quitter/QuitterObserver.js b/tools/quitter/QuitterObserver.js new file mode 100644 index 00000000000..fe2a810c93d --- /dev/null +++ b/tools/quitter/QuitterObserver.js @@ -0,0 +1,70 @@ +/* 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/. */ + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +const Cc = Components.classes; +const Ci = Components.interfaces; + +const CHILD_SCRIPT = "chrome://quitter/content/contentscript.js"; + +/* XPCOM gunk */ +function QuitterObserver() {} + +QuitterObserver.prototype = { + classDescription: "Quitter Observer for use in testing.", + classID: Components.ID("{c235a986-5ac1-4f28-ad73-825dae9bad90}"), + contractID: "@mozilla.org/quitter-observer;1", + QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]), + _xpcom_categories: [{category: "profile-after-change", service: true }], + isFrameScriptLoaded: false, + + observe: function(aSubject, aTopic, aData) + { + if (aTopic == "profile-after-change") { + this.init(); + } else if (!this.isFrameScriptLoaded && + aTopic == "chrome-document-global-created") { + + var messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. + getService(Ci.nsIMessageBroadcaster); + // Register for any messages our API needs us to handle + messageManager.addMessageListener("Quitter.Quit", this); + + messageManager.loadFrameScript(CHILD_SCRIPT, true); + this.isFrameScriptLoaded = true; + } else if (aTopic == "xpcom-shutdown") { + this.uninit(); + } + }, + + init: function() + { + var obs = Services.obs; + obs.addObserver(this, "xpcom-shutdown", false); + obs.addObserver(this, "chrome-document-global-created", false); + }, + + uninit: function() + { + var obs = Services.obs; + obs.removeObserver(this, "chrome-document-global-created", false); + }, + + /** + * messageManager callback function + * This will get requests from our API in the window and process them in chrome for it + **/ + receiveMessage: function(aMessage) { + switch(aMessage.name) { + case "Quitter.Quit": + let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); + appStartup.quit(Ci.nsIAppStartup.eForceQuit); + break; + } + } +}; + +const NSGetFactory = XPCOMUtils.generateNSGetFactory([QuitterObserver]); diff --git a/tools/quitter/chrome.manifest b/tools/quitter/chrome.manifest new file mode 100644 index 00000000000..feffe54c427 --- /dev/null +++ b/tools/quitter/chrome.manifest @@ -0,0 +1,4 @@ +content quitter chrome/quitter/content/ +component {c235a986-5ac1-4f28-ad73-825dae9bad90} components/QuitterObserver.js +contract @mozilla.org/quitter-observer;1 {c235a986-5ac1-4f28-ad73-825dae9bad90} +category profile-after-change @mozilla.org/quitter-observer;1 @mozilla.org/quitter-observer;1 diff --git a/tools/quitter/contentscript.js b/tools/quitter/contentscript.js new file mode 100644 index 00000000000..a870a6623a8 --- /dev/null +++ b/tools/quitter/contentscript.js @@ -0,0 +1,38 @@ +/* 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/. */ + +var Ci = Components.interfaces; +var Cc = Components.classes; + +function Quitter() { +} + +Quitter.prototype = { + toString: function() { return "[Quitter]"; }, + quit: function() { + sendSyncMessage('Quitter.Quit', {}); + }, + __exposedProps__: { + 'toString': 'r', + 'quit': 'r' + } +}; + +// This is a frame script, so it may be running in a content process. +// In any event, it is targeted at a specific "tab", so we listen for +// the DOMWindowCreated event to be notified about content windows +// being created in this context. + +function QuitterManager() { + addEventListener("DOMWindowCreated", this, false); +} + +QuitterManager.prototype = { + handleEvent: function handleEvent(aEvent) { + var window = aEvent.target.defaultView; + window.wrappedJSObject.Quitter = new Quitter(window); + } +}; + +var quittermanager = new QuitterManager(); diff --git a/tools/quitter/install.rdf b/tools/quitter/install.rdf new file mode 100644 index 00000000000..dfeba946257 --- /dev/null +++ b/tools/quitter/install.rdf @@ -0,0 +1,26 @@ + + + + + + quitter@mozilla.org + 2013.09.14 + 2 + + + + + toolkit@mozilla.org +#expand __MOZILLA_VERSION_U__ +#expand __MOZILLA_VERSION_U__ + + + + + Quitter + Adds a quit method that content pages can use to quit the application. + Mozilla + + diff --git a/tools/quitter/jar.mn b/tools/quitter/jar.mn new file mode 100644 index 00000000000..4467f923b24 --- /dev/null +++ b/tools/quitter/jar.mn @@ -0,0 +1,3 @@ +quitter.jar: +% content quitter %content/ + content/contentscript.js (contentscript.js) diff --git a/tools/quitter/moz.build b/tools/quitter/moz.build new file mode 100644 index 00000000000..d8de684a414 --- /dev/null +++ b/tools/quitter/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +EXTRA_COMPONENTS += [ + 'QuitterObserver.js', +]