bug 771395 - show origin of page in window title when it is different from webapp's origin; r=felipe
authorMyk Melez <myk@mozilla.org>
Tue, 10 Jul 2012 15:07:31 -0700
changeset 101588 5bb5b5dd4960f358b91b04f906435a3b68374b27
parent 101587 1f07f04ec01decf4086d97cd024cd324d5e9e698
child 101589 3bf8ff8836d19bf73a5c3b61991103d445f2b8f8
push idunknown
push userunknown
push dateunknown
reviewersfelipe
bugs771395
milestone16.0a1
bug 771395 - show origin of page in window title when it is different from webapp's origin; r=felipe
webapprt/CommandLineHandler.js
webapprt/content/webapp.js
webapprt/test/chrome/Makefile.in
webapprt/test/chrome/browser_window-title.js
webapprt/test/chrome/window-title.html
webapprt/test/chrome/window-title.webapp
--- a/webapprt/CommandLineHandler.js
+++ b/webapprt/CommandLineHandler.js
@@ -25,23 +25,23 @@ CommandLineHandler.prototype = {
     // Initialize DOMApplicationRegistry by importing Webapps.jsm, but only
     // after broadcasting webapprt-command-line.  Webapps.jsm calls
     // DOMApplicationRegistry.init() when it's first imported.  init() accesses
     // the WebappRegD directory, which in test mode is special-cased by
     // DirectoryProvider.js after it observes webapprt-command-line.
     Cu.import("resource://gre/modules/Webapps.jsm");
 
     if (!inTestMode) {
-      startUp();
+      startUp(inTestMode);
     } else {
       // startUp() accesses WebappRT.config, which in test mode is not valid
       // until WebappRT.jsm observes an app installation.
       Services.obs.addObserver(function onInstall(subj, topic, data) {
         Services.obs.removeObserver(onInstall, "webapprt-test-did-install");
-        startUp();
+        startUp(inTestMode);
       }, "webapprt-test-did-install", false);
     }
 
     // Open the window with arguments to identify it as the main window
     Services.ww.openWindow(null,
                            "chrome://webapprt/content/webapp.xul",
                            "_blank",
                            "chrome,dialog=no,resizable,scrollbars,centerscreen",
--- a/webapprt/content/webapp.js
+++ b/webapprt/content/webapp.js
@@ -3,64 +3,102 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://webapprt/modules/WebappRT.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "gAppBrowser",
+                            function() document.getElementById("content"));
+
+let progressListener = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+                                         Ci.nsISupportsWeakReference]),
+  onLocationChange: function onLocationChange(progress, request, location,
+                                              flags) {
+    // Set the title of the window to the name of the webapp, adding the origin
+    // of the page being loaded if it's from a different origin than the app
+    // (per security bug 741955, which specifies that other-origin pages loaded
+    // in runtime windows must be identified in chrome).
+    let title = WebappRT.config.app.manifest.name;
+    let origin = location.prePath;
+    if (origin != WebappRT.config.app.origin) {
+      title = origin + " - " + title;
+    }
+    document.documentElement.setAttribute("title", title);
+  }
+};
 
 function onLoad() {
   window.removeEventListener("load", onLoad, false);
 
   let cmdLineArgs = window.arguments && window.arguments[0] ?
                     window.arguments[0].QueryInterface(Ci.nsIPropertyBag2) :
                     null;
 
   // In test mode, listen for test app installations and load the -test-mode URL
   // if present.
   if (cmdLineArgs && cmdLineArgs.hasKey("test-mode")) {
+    // This observer is only present until the first app gets installed.
+    // It adds the progress listener, which can't happen until then because
+    // the progress listener needs to access the app manifest, which isn't
+    // available beforehand.
+    Services.obs.addObserver(function observeOnce(subj, topic, data) {
+      Services.obs.removeObserver(observeOnce, "webapprt-test-did-install");
+      gAppBrowser.webProgress.
+        addProgressListener(progressListener,Ci.nsIWebProgress.NOTIFY_LOCATION);
+    }, "webapprt-test-did-install", false);
+
+    // This observer is present for the lifetime of the runtime.
     Services.obs.addObserver(function observe(subj, topic, data) {
-      // The observer is present for the lifetime of the runtime.
       initWindow(false);
     }, "webapprt-test-did-install", false);
+
     let testURL = cmdLineArgs.get("test-mode");
     if (testURL) {
-      document.getElementById("content").loadURI(testURL);
+      gAppBrowser.loadURI(testURL);
     }
+
     return;
   }
 
+  gAppBrowser.webProgress.
+    addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_LOCATION);
+
   initWindow(!!cmdLineArgs);
 }
-
 window.addEventListener("load", onLoad, false);
 
+function onUnload() {
+  gAppBrowser.removeProgressListener(progressListener);
+}
+window.addEventListener("unload", onUnload, false);
+
 function initWindow(isMainWindow) {
-  // Set the title of the window to the name of the webapp
   let manifest = WebappRT.config.app.manifest;
-  document.documentElement.setAttribute("title", manifest.name);
 
   updateMenuItems();
 
   // Listen for clicks to redirect <a target="_blank"> to the browser.
   // This doesn't capture clicks so content can capture them itself and do
   // something different if it doesn't want the default behavior.
-  document.getElementById("content").addEventListener("click", onContentClick,
-                                                      false, true);
+  gAppBrowser.addEventListener("click", onContentClick, false, true);
 
   // Only load the webapp on the initially launched main window
   if (isMainWindow) {
     // Load the webapp's launch URL
     let installRecord = WebappRT.config.app;
     let url = Services.io.newURI(installRecord.origin, null, null);
     if (manifest.launch_path)
       url = Services.io.newURI(manifest.launch_path, null, url);
-    document.getElementById("content").setAttribute("src", url.spec);
+    gAppBrowser.setAttribute("src", url.spec);
   }
 }
 
 /**
  * Direct a click on <a target="_blank"> to the user's default browser.
  *
  * In the long run, it might be cleaner to move this to an extension of
  * nsIWebBrowserChrome3::onBeforeLinkTraversal.
--- a/webapprt/test/chrome/Makefile.in
+++ b/webapprt/test/chrome/Makefile.in
@@ -11,11 +11,14 @@ relativesrcdir = webapprt/test/chrome
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_WEBAPPRT_CHROME_FILES = \
   head.js \
   install.html \
   browser_sample.js \
     sample.webapp \
     sample.html \
+  browser_window-title.js \
+    window-title.webapp \
+    window-title.html \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/webapprt/test/chrome/browser_window-title.js
@@ -0,0 +1,55 @@
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function test() {
+  waitForExplicitFinish();
+
+  installWebapp("window-title.webapp", undefined,
+                function onInstall(appConfig) {
+    is(document.documentElement.getAttribute("title"),
+       appConfig.app.manifest.name,
+       "initial window title should be webapp name");
+
+    let appBrowser = document.getElementById("content");
+
+    // Tests are triples of [URL to load, expected window title, test message].
+    let tests = [
+      ["http://example.com/webapprtChrome/webapprt/test/chrome/window-title.html",
+       "http://example.com" + " - " + appConfig.app.manifest.name,
+       "window title should show origin of page at different origin"],
+      ["http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/window-title.html",
+       appConfig.app.manifest.name,
+       "after returning to app origin, window title should no longer show origin"],
+    ];
+
+    let title, message;
+
+    let progressListener = {
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+                                             Ci.nsISupportsWeakReference]),
+      onLocationChange: function onLocationChange(progress, request, location,
+                                                  flags) {
+        // Do test in timeout to give runtime time to change title.
+        window.setTimeout(function() {
+          is(document.documentElement.getAttribute("title"), title, message);
+          testNext();
+        }, 0);
+      }
+    };
+
+    appBrowser.webProgress.
+      addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_LOCATION);
+
+    function testNext() {
+      if (!tests.length) {
+        appBrowser.removeProgressListener(progressListener);
+        appBrowser.stop();
+        finish();
+        return;
+      }
+
+      [appBrowser.contentDocument.location, title, message] = tests.shift();
+    }
+
+    testNext();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/webapprt/test/chrome/window-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <title>Window Title Test App</title>
+    <meta charset="utf-8">
+  </head>
+  <body>
+    <h1>Window Title Test App</h1>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/webapprt/test/chrome/window-title.webapp
@@ -0,0 +1,5 @@
+{
+  "name": "Window Title Test App",
+  "description": "an app for testing window titles",
+  "launch_path": "/webapprtChrome/webapprt/test/chrome/window-title.html"
+}