bug 641829 - add a Quitter extension for profileserver.py. r=jmaher
authorTed Mielczarek <ted.mielczarek@gmail.com>
Thu, 26 May 2011 09:07:35 -0400
changeset 161041 182cb77cc3e951b0b461800bac10813a0556a4a8
parent 161040 5dbc327401617a3569089f2d72585157232fb44b
child 161042 853f3f44cb3bb8ff7290a266c5290272695982f2
push id407
push userlsblakk@mozilla.com
push dateTue, 03 Dec 2013 03:32:50 +0000
treeherdermozilla-release@babf8c9ebc52 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher
bugs641829
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 641829 - add a Quitter extension for profileserver.py. r=jmaher
build/pgo/index.html
build/pgo/profileserver.py
toolkit/toolkit.mozbuild
tools/quitter/Makefile.in
tools/quitter/QuitterObserver.js
tools/quitter/chrome.manifest
tools/quitter/contentscript.js
tools/quitter/install.rdf
tools/quitter/jar.mn
tools/quitter/moz.build
--- a/build/pgo/index.html
+++ b/build/pgo/index.html
@@ -1,123 +1,13 @@
 <script>
 /* 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",
   "blueprint/forms.html",
   "blueprint/grid.html",
   "blueprint/elements.html",
   "js-input/3d-cube.html",
   "js-input/3d-morph.html",
@@ -157,17 +47,17 @@
      window.setTimeout(loadURL, interval); 
  };
  function loadURL () {
      w.close();
      w = window.open(list[idx++]);
      if (idx < list.length) {
      window.setTimeout(loadURL, interval);
      } else {
-         window.setTimeout(goQuitApplication, interval);
+         window.setTimeout(Quitter.quit, interval);
      }
  }
  var i;
  
  for(i=0; i < list.length;i++) {
      document.write(list[i]);
      document.write("<br>");
  }
--- a/build/pgo/profileserver.py
+++ b/build/pgo/profileserver.py
@@ -43,17 +43,17 @@ if __name__ == '__main__':
     prefs.update(Preferences.read_prefs(prefpath))
     interpolation = { "server": "%s:%d" % httpd.httpd.server_address,
                       "OOP": "false"}
     prefs = json.loads(json.dumps(prefs) % interpolation)
     for pref in prefs:
       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()
     env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
     env["XPCOM_DEBUG_BREAK"] = "warn"
     jarlog = os.getenv("JARLOG_FILE")
     if jarlog:
       env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog)
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -176,16 +176,18 @@ if CONFIG['MOZ_ENABLE_GNOME_COMPONENT']:
 if not CONFIG['MOZ_ENABLE_QTNETWORK'] and CONFIG['MOZ_ENABLE_DBUS']:
     add_tier_dir('platform', 'toolkit/system/dbus')
 
 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',
         'testing/xpcshell',
         'testing/tools/screenshot',
         'testing/peptest',
         'testing/profiles',
         'testing/mozbase',
new file mode 100644
--- /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
new file mode 100644
--- /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]);
new file mode 100644
--- /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
new file mode 100644
--- /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();
new file mode 100644
--- /dev/null
+++ b/tools/quitter/install.rdf
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>quitter@mozilla.org</em:id>
+    <em:version>2013.09.14</em:version>
+    <em:type>2</em:type>
+
+    <!-- Target Application this extension can install into,
+         with minimum and maximum supported versions. -->
+    <em:targetApplication>
+      <Description>
+        <em:id>toolkit@mozilla.org</em:id>
+#expand        <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
+#expand        <em:maxVersion>__MOZILLA_VERSION_U__</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <em:name>Quitter</em:name>
+    <em:description>Adds a quit method that content pages can use to quit the application.</em:description>
+    <em:creator>Mozilla</em:creator>
+  </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/tools/quitter/jar.mn
@@ -0,0 +1,3 @@
+quitter.jar:
+% content quitter %content/
+  content/contentscript.js (contentscript.js)
new file mode 100644
--- /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',
+]