Bug 753546 Part 2 - Don't allow fullscreen approval decision to be remembered for document's whose URI doesn't have a host. r=dao
authorChris Pearce <cpearce@mozilla.com>
Tue, 22 May 2012 08:43:36 +1200
changeset 96786 90564ac34b0620516e857300e6b400ee449402d1
parent 96785 451145d2c3ff802105733587535458c3622f0e99
child 96787 67cd8131a3d577d8343d4459853096f2a6638247
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao
bugs753546
milestone15.0a1
Bug 753546 Part 2 - Don't allow fullscreen approval decision to be remembered for document's whose URI doesn't have a host. r=dao
browser/base/content/browser.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4179,17 +4179,17 @@ var FullScreen = {
     clearTimeout(this._animationTimeout);
     this._isAnimating = false;
     this._shouldAnimate = false;
   },
 
   cancelWarning: function(event) {
     if (!this.warningBox)
       return;
-    this.fullscreenDocUri = null;
+    this.fullscreenDoc = null;
     this.warningBox.removeEventListener("transitionend", this);
     if (this.warningFadeOutTimeout) {
       clearTimeout(this.warningFadeOutTimeout);
       this.warningFadeOutTimeout = null;
     }
 
     // Ensure focus switches away from the (now hidden) warning box. If the user
     // clicked buttons in the fullscreen key authorization UI, it would have been
@@ -4199,86 +4199,120 @@ var FullScreen = {
 
     this.warningBox.setAttribute("hidden", true);
     this.warningBox.removeAttribute("fade-warning-out");
     this.warningBox.removeAttribute("obscure-browser");
     this.warningBox = null;
   },
 
   setFullscreenAllowed: function(isApproved) {
-    let remember = document.getElementById("full-screen-remember-decision").checked;
-    if (remember)
-      Services.perms.add(this.fullscreenDocUri,
-                         "fullscreen",
-                         isApproved ? Services.perms.ALLOW_ACTION : Services.perms.DENY_ACTION,
-                         Services.perms.EXPIRE_NEVER);
-    else if (isApproved) {
-      // The user has only temporarily approved fullscren for this domain.
-      // Add the permission (so Gecko knows fullscreen is approved) but add a
-      // listener to remove the permission when the chrome document exits fullscreen.
-      Services.perms.add(this.fullscreenDocUri,
-                         "fullscreen",
-                         Services.perms.ALLOW_ACTION,
-                         Services.perms.EXPIRE_SESSION);
-      let host = this.fullscreenDocUri.host;
-      function onFullscreenchange(event) {
-        if (event.target == document && document.mozFullScreenElement == null) {
-          // The chrome document has left fullscreen. Remove the temporary permission grant.
-          Services.perms.remove(host, "fullscreen");
-          document.removeEventListener("mozfullscreenchange", onFullscreenchange);
+    // The "remember decision" checkbox is hidden when showing for documents that
+    // the permission manager can't handle (documents with URIs without a host).
+    // We simply require those to be approved every time instead.
+    let rememberCheckbox = document.getElementById("full-screen-remember-decision");
+    let uri = this.fullscreenDoc.nodePrincipal.URI;
+    if (!rememberCheckbox.hidden) {
+      if (rememberCheckbox.checked)
+        Services.perms.add(uri,
+                           "fullscreen",
+                           isApproved ? Services.perms.ALLOW_ACTION : Services.perms.DENY_ACTION,
+                           Services.perms.EXPIRE_NEVER);
+      else if (isApproved) {
+        // The user has only temporarily approved fullscren for this fullscreen
+        // session only. Add the permission (so Gecko knows to approve any further
+        // fullscreen requests for this host in this fullscreen session) but add
+        // a listener to revoke the permission when the chrome document exits
+        // fullscreen.
+        Services.perms.add(uri,
+                           "fullscreen",
+                           Services.perms.ALLOW_ACTION,
+                           Services.perms.EXPIRE_SESSION);
+        let host = uri.host;
+        function onFullscreenchange(event) {
+          if (event.target == document && document.mozFullScreenElement == null) {
+            // The chrome document has left fullscreen. Remove the temporary permission grant.
+            Services.perms.remove(host, "fullscreen");
+            document.removeEventListener("mozfullscreenchange", onFullscreenchange);
+          }
         }
+        document.addEventListener("mozfullscreenchange", onFullscreenchange);
       }
-      document.addEventListener("mozfullscreenchange", onFullscreenchange);
     }
     if (this.warningBox)
       this.warningBox.setAttribute("fade-warning-out", "true");
-    if (!isApproved)
+    // If the document has been granted fullscreen, notify Gecko so it can resume
+    // any pending pointer lock requests, otherwise exit fullscreen; the user denied
+    // the fullscreen request.
+    if (isApproved)
+      Services.obs.notifyObservers(this.fullscreenDoc, "fullscreen-approved", "");
+    else
       document.mozCancelFullScreen();
   },
 
   warningBox: null,
   warningFadeOutTimeout: null,
-  fullscreenDocUri: null,
+  fullscreenDoc: null,
 
   // Shows the fullscreen approval UI, or if the domain has already been approved
   // for fullscreen, shows a warning that the site has entered fullscreen for a short
   // duration.
   showWarning: function(targetDoc) {
     if (!document.mozFullScreen ||
         !gPrefService.getBoolPref("full-screen-api.approval-required"))
       return;
 
     // Set the strings on the fullscreen approval UI.
-    this.fullscreenDocUri = targetDoc.nodePrincipal.URI;
-    let utils = {};
-    Cu.import("resource://gre/modules/DownloadUtils.jsm", utils);
-    let [displayHost, fullHost] = utils.DownloadUtils.getURIHost(this.fullscreenDocUri.spec);
-    let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
-    let domainText = bundle.formatStringFromName("fullscreen.entered", [displayHost], 1);
-    document.getElementById("full-screen-domain-text").textContent = domainText;
-    let rememberText = bundle.formatStringFromName("fullscreen.rememberDecision", [displayHost], 1);
-    document.getElementById("full-screen-remember-decision").label = rememberText;
+    this.fullscreenDoc = targetDoc;
+    let uri = this.fullscreenDoc.nodePrincipal.URI;
+    let host = null;
+    try {
+      host = uri.host;
+    } catch (e) { }
+    let hostLabel = document.getElementById("full-screen-domain-text");
+    let rememberCheckbox = document.getElementById("full-screen-remember-decision");
+    let isApproved = false;
+    if (host) {
+      // Document's principal's URI has a host. Display a warning including the hostname and
+      // show UI to enable the user to permanently grant this host permission to enter fullscreen.
+      let utils = {};
+      Cu.import("resource://gre/modules/DownloadUtils.jsm", utils);
+      let displayHost = utils.DownloadUtils.getURIHost(uri.spec)[0];
+      let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+
+      hostLabel.textContent = bundle.formatStringFromName("fullscreen.entered", [displayHost], 1);
+      hostLabel.removeAttribute("hidden");
+
+      rememberCheckbox.label = bundle.formatStringFromName("fullscreen.rememberDecision", [displayHost], 1);
+      rememberCheckbox.checked = false;
+      rememberCheckbox.removeAttribute("hidden");
+
+      // Note we only allow documents whose principal's URI has a host to
+      // store permission grants.
+      isApproved = Services.perms.testPermission(uri, "fullscreen") == Services.perms.ALLOW_ACTION;
+    } else {
+      hostLabel.setAttribute("hidden", "true");
+      rememberCheckbox.setAttribute("hidden", "true");
+    }
 
     // Note: the warning box can be non-null if the warning box from the previous request
     // wasn't hidden before another request was made.
     if (!this.warningBox) {
       this.warningBox = document.getElementById("full-screen-warning-container");
       // Add a listener to clean up state after the warning is hidden.
       this.warningBox.addEventListener("transitionend", this);
       this.warningBox.removeAttribute("hidden");
     }
 
     // If fullscreen mode has not yet been approved for the fullscreen
     // document's domain, show the approval UI and don't auto fade out the
     // fullscreen warning box. Otherwise, we're just notifying of entry into
-    // fullscreen mode.
-    let isApproved =
-      Services.perms.testPermission(this.fullscreenDocUri, "fullscreen") == Services.perms.ALLOW_ACTION;
+    // fullscreen mode. Note if the resource's host is null, we must be
+    // showing a local file or a local data URI, and we require explicit
+    // approval every time.
     let authUI = document.getElementById("full-screen-approval-pane");
-    document.getElementById("full-screen-remember-decision").checked = false;
     if (isApproved)
       authUI.setAttribute("hidden", "true");
     else {
       // Partially obscure the <browser> element underneath the approval UI.
       this.warningBox.setAttribute("obscure-browser", "true");
       authUI.removeAttribute("hidden");
     }
 
@@ -4466,17 +4500,17 @@ var XULBrowserWindow = {
   status: "",
   defaultStatus: "",
   jsStatus: "",
   jsDefaultStatus: "",
   overLink: "",
   startTime: 0,
   statusText: "",
   isBusy: false,
-  inContentWhitelist: ["about:addons", "about:permissions", 
+  inContentWhitelist: ["about:addons", "about:permissions",
                        "about:sync-progress", "about:preferences"],
 
   QueryInterface: function (aIID) {
     if (aIID.equals(Ci.nsIWebProgressListener) ||
         aIID.equals(Ci.nsIWebProgressListener2) ||
         aIID.equals(Ci.nsISupportsWeakReference) ||
         aIID.equals(Ci.nsIXULBrowserWindow) ||
         aIID.equals(Ci.nsISupports))