Bug 771294. Use window id for webapp installation. r=gavin
authorFelipe Gomes <felipc@gmail.com>
Sat, 14 Jul 2012 01:09:32 -0700
changeset 99283 69a1fb2ddca3e05e327a82c9890bca30a13dc3c7
parent 99282 a405768bd32a8fece62380159003b8923f132f84
child 99284 58d5f1d1443e9ec3f787d6327cc1d6184e833d07
push id23116
push userryanvm@gmail.com
push dateSat, 14 Jul 2012 16:58:48 +0000
treeherdermozilla-central@9046ecf4db8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs771294
milestone16.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 771294. Use window id for webapp installation. r=gavin Test by Myk Melez
browser/modules/webappsUI.jsm
dom/tests/mochitest/webapps/Makefile.in
dom/tests/mochitest/webapps/apps/Makefile.in
dom/tests/mochitest/webapps/apps/bug_765063.xul
dom/tests/mochitest/webapps/apps/bug_771294.xul
dom/tests/mochitest/webapps/test_bug_765063.xul
dom/tests/mochitest/webapps/test_bug_771294.xul
toolkit/content/PopupNotifications.jsm
--- a/browser/modules/webappsUI.jsm
+++ b/browser/modules/webappsUI.jsm
@@ -24,20 +24,22 @@ let webappsUI = {
     Services.obs.removeObserver(this, "webapps-launch");
   },
 
   observe: function webappsUI_observe(aSubject, aTopic, aData) {
     let data = JSON.parse(aData);
 
     switch(aTopic) {
       case "webapps-ask-install":
-        let [chromeWin, browser] = this._getBrowserForId(data.oid);
-        if (chromeWin)
-          this.doInstall(data, browser, chromeWin);
+        let win = this._getWindowForId(data.oid);
+        if (win && win.location.href == data.from) {
+          this.doInstall(data, win);
+        }
         break;
+
       case "webapps-launch":
         DOMApplicationRegistry.getManifestFor(data.origin, (function(aManifest) {
           if (!aManifest)
             return;
           let manifest = new DOMApplicationManifest(aManifest, data.origin);
           this.openURL(manifest.fullLaunchPath(), data.origin);
         }).bind(this));
         break;
@@ -78,73 +80,67 @@ let webappsUI = {
         let tab = browser.addTab(aUrl);
         browser.pinTab(tab);
         browser.selectedTab = tab;
         ss.setTabValue(tab, "appOrigin", aOrigin);
       }
     }
   },
 
-  _getBrowserForId: function(aId) {
-    let someWindow = Services.wm.getMostRecentWindow(null);
+  doInstall: function(aData, aWindow) {
+    let browser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIWebNavigation)
+                         .QueryInterface(Ci.nsIDocShell)
+                         .chromeEventHandler;
 
-    if (someWindow) {
-      let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                  .getInterface(Ci.nsIDOMWindowUtils);
-      let content = windowUtils.getOuterWindowWithId(aId);
-      if (content) {
-        let browser = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIWebNavigation)
-                      .QueryInterface(Ci.nsIDocShell).chromeEventHandler;
-        let win = browser.ownerDocument.defaultView;
-        return [win, browser];
-      }
-    }
-
-    return [null, null];
-  },
-
-  doInstall: function(aData, aBrowser, aWindow) {
-    let bundle = aWindow.gNavigatorBundle;
+    let chromeWin = browser.ownerDocument.defaultView;
+    let bundle = chromeWin.gNavigatorBundle;
 
     let mainAction = {
       label: bundle.getString("webapps.install"),
       accessKey: bundle.getString("webapps.install.accesskey"),
       callback: function() {
         let app = WebappsInstaller.install(aData);
         if (app) {
           let localDir = null;
           if (app.appcacheDefined && app.appProfile) {
             localDir = app.appProfile.localDir;
           }
 
           DOMApplicationRegistry.confirmInstall(aData, false, localDir);
-          installationSuccessNotification(app, aWindow);
+          installationSuccessNotification(app, chromeWin);
         } else {
           DOMApplicationRegistry.denyInstall(aData);
         }
       }
     };
 
-    let requestingURI = aWindow.makeURI(aData.from);
+    let requestingURI = chromeWin.makeURI(aData.from);
     let manifest = new DOMApplicationManifest(aData.app.manifest, aData.app.origin);
 
     let host;
     try {
       host = requestingURI.host;
     } catch(e) {
       host = requestingURI.spec;
     }
 
     let message = bundle.getFormattedString("webapps.requestInstall",
-                                            [manifest.name, host], 2);
+                                            [manifest.name, host]);
+
+    chromeWin.PopupNotifications.show(browser, "webapps-install", message,
+                                      "webapps-notification-icon", mainAction);
+  },
 
-    aWindow.PopupNotifications.show(aBrowser, "webapps-install", message,
-                                    "webapps-notification-icon", mainAction);
-
+  _getWindowForId: function(aId) {
+     let someWindow = Services.wm.getMostRecentWindow(null);
+     return someWindow &&
+            someWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                      .getInterface(Ci.nsIDOMWindowUtils)
+                      .getOuterWindowWithId(aId);
   }
 }
 
 function installationSuccessNotification(app, aWindow) {
   let bundle = aWindow.gNavigatorBundle;
 
   if (("@mozilla.org/alerts-service;1" in Cc)) {
     let notifier;
--- a/dom/tests/mochitest/webapps/Makefile.in
+++ b/dom/tests/mochitest/webapps/Makefile.in
@@ -11,16 +11,17 @@ relativesrcdir	= dom/tests/mochitest/web
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
     apps \
     $(NULL)
 
 MOCHITEST_CHROME_FILES	= \
     test_bug_765063.xul \
+    test_bug_771294.xul \
     test_install_app.xul \
     test_list_api.xul \
     test_install_errors.xul \
     test_cross_domain.xul \
     test_install_utf8.xul \
     test_install_receipts.xul \
     jshelper.js \
     apphelper.js \
--- a/dom/tests/mochitest/webapps/apps/Makefile.in
+++ b/dom/tests/mochitest/webapps/apps/Makefile.in
@@ -7,16 +7,17 @@ topsrcdir	 = @top_srcdir@
 srcdir	= @srcdir@
 VPATH	 = @srcdir@
 relativesrcdir	= dom/tests/mochitest/webapps/apps
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_CHROME_FILES	= \
     bug_765063.xul \
+    bug_771294.xul \
     include.html \
     wild_crazy.webapp \
     wild_crazy.webapp^headers^ \
     super_crazy.webapp \
     super_crazy.webapp^headers^ \
     missing_required_field.webapp \
     missing_required_field.webapp^headers^ \
     json_syntax_error.webapp \
--- a/dom/tests/mochitest/webapps/apps/bug_765063.xul
+++ b/dom/tests/mochitest/webapps/apps/bug_765063.xul
@@ -1,11 +1,11 @@
 <?xml version="1.0"?>
 
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script>
     navigator.mozApps.install("http://www.example.com:80/chrome/dom/tests/mochitest/webapps/apps/super_crazy.webapp", null);
-    document.location = "about:blank";
+    history.pushState({}, "", "modified-url");
   </script>
 </window>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webapps/apps/bug_771294.xul
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script>
+    navigator.mozApps.install("http://www.example.com:80/chrome/dom/tests/mochitest/webapps/apps/super_crazy.webapp", null);
+    window.location = "about:blank";
+  </script>
+</window>
--- a/dom/tests/mochitest/webapps/test_bug_765063.xul
+++ b/dom/tests/mochitest/webapps/test_bug_765063.xul
@@ -13,29 +13,32 @@
   <!-- We only need jshelper.js for debug(), which apphelper.js calls.  But
      - since we include it, we also let it call apphelper.js's popup_listener(),
      - which listens for the install doorhanger and presses its main button. -->
   <script type="application/javascript" src="jshelper.js"/>
 
 <script> 
 SimpleTest.waitForExplicitFinish();
 
-// Observe app installation and confirm that the install origin didn't change.
-var observer = {
-  observe: function observe(subject, topic, data) {
-    Services.obs.removeObserver(observer, "webapps-sync-install");
-    ok(JSON.parse(data).installOrigin == "http://www.example.com",
-       "the install origin didn't change");
+var mmListener = {
+  receiveMessage: function(aMessage) {
+    ppmm.removeMessageListener("Webapps:Install", mmListener);
+
+    var msg = aMessage.json;
+    is(msg.from.indexOf("modified-url"), -1, "the install origin didn't change");
+
     tearDown();
     SimpleTest.finish();
   }
 };
 
-Components.utils.import("resource://gre/modules/Services.jsm");
-Services.obs.addObserver(observer, "webapps-sync-install", false);
+var ppmm = Components.classes["@mozilla.org/parentprocessmessagemanager;1"]
+                     .getService(Components.interfaces.nsIFrameMessageManager);
+
+ppmm.addMessageListener("Webapps:Install", mmListener);
 </script> 
 
   <!-- Load a page that initiates an app installation and then immediately
      - redirects to a page at a different origin.  We can't do this directly
      - inside this test page, because that would cause the test to hang. -->
   <iframe src="http://www.example.com:80/chrome/dom/tests/mochitest/webapps/apps/bug_765063.xul"/>
 
 </window>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webapps/test_bug_771294.xul
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Mozilla Bug 771294">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+  <script type="application/javascript" src="apphelper.js"/>
+  <script type="application/javascript" src="jshelper.js"/>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+
+Components.utils.import('resource://gre/modules/Services.jsm');
+
+var blocked = true;
+
+Services.obs.addObserver(
+  function observeShowing() {
+    Services.obs.removeObserver(observeShowing, "PopupNotifications-showing");
+    blocked = false;
+  },
+  "PopupNotifications-showing",
+  false
+);
+
+Services.obs.addObserver(
+  function observeInstalling() {
+    Services.obs.removeObserver(observeInstalling, "webapps-ask-install");
+    // Spin the event loop before running the test to give the registry time
+    // to process the install request and (hopefully not) show the doorhanger.
+    setTimeout(function verify() {
+      ok(blocked, "Install panel was blocked after immediate redirect");
+      tearDown();
+      SimpleTest.finish();
+    }, 0);
+  },
+  "webapps-ask-install",
+  false
+);
+
+</script>
+
+  <!-- Load a page that initiates an app installation and then immediately
+     - redirects to a page at a different origin.  We can't do this directly
+     - inside this test page, because that would cause the test to hang. -->
+  <iframe src="http://www.example.com:80/chrome/dom/tests/mochitest/webapps/apps/bug_771294.xul"/>
+
+</window>
--- a/toolkit/content/PopupNotifications.jsm
+++ b/toolkit/content/PopupNotifications.jsm
@@ -236,16 +236,19 @@ PopupNotifications.prototype = {
 
     let existingNotification = this.getNotification(id, browser);
     if (existingNotification)
       this._remove(existingNotification);
 
     let notifications = this._getNotificationsForBrowser(browser);
     notifications.push(notification);
 
+    // Notify observers that we're showing the popup (useful for testing)
+    this._notify("showing");
+
     let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
     if (browser == this.tabbrowser.selectedBrowser && fm.activeWindow == this.window) {
       // show panel now
       this._update(notification.anchorElement);
     } else {
       // Otherwise, update() will display the notification the next time the
       // relevant tab/window is selected.