Bug 1493766 - part1 : notify when temporary permission changed. r=johannh
authoralwu <alwu@mozilla.com>
Thu, 15 Nov 2018 19:51:26 +0000
changeset 503241 0e0a171941b2169accb5f5af19b9094623666954
parent 503240 113e5589cea7f811d1aa3e3ef5164a09f5177089
child 503242 41fe6af27564c37af484fdad90833a065e30c314
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohannh
bugs1493766
milestone65.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 1493766 - part1 : notify when temporary permission changed. r=johannh Since temporary permissions are only stored in the front-end side, we can't know whether we have allowed page to autoplay or not without sending a request. Therefore, we want to notify the back-end side when the temporary permissions changed. Differential Revision: https://phabricator.services.mozilla.com/D7011
browser/modules/SitePermissions.jsm
toolkit/actors/AudioPlaybackChild.jsm
toolkit/modules/ActorManagerParent.jsm
--- a/browser/modules/SitePermissions.jsm
+++ b/browser/modules/SitePermissions.jsm
@@ -59,27 +59,29 @@ const TemporaryPermissions = {
       this._stateByBrowser.set(browser, {});
     }
     let entry = this._stateByBrowser.get(browser);
     let prePath = browser.currentURI.prePath;
     if (!entry[prePath]) {
       entry[prePath] = {};
     }
     entry[prePath][id] = {timeStamp: Date.now(), state};
+    this.notifyWhenTemporaryPermissionChanged(browser, id, prePath, state);
   },
 
   // Removes a permission with the specified id for the specified browser.
   remove(browser, id) {
     if (!browser) {
       return;
     }
     let entry = this._stateByBrowser.get(browser);
     let prePath = browser.currentURI.prePath;
     if (entry && entry[prePath]) {
       delete entry[prePath][id];
+      this.notifyWhenTemporaryPermissionChanged(browser, id, prePath, SitePermissions.UNKNOWN);
     }
   },
 
   // Gets a permission with the specified id for the specified browser.
   get(browser, id) {
     if (!browser || !browser.currentURI) {
       return null;
     }
@@ -107,31 +109,63 @@ const TemporaryPermissions = {
         if (permission) {
           permissions.push(permission);
         }
       }
     }
     return permissions;
   },
 
+  // Gets all permissions ID for the specified browser, this method will return
+  // all permissions ID stored in browser without checking current URI.
+  getAllPermissionIds(browser) {
+    let permissions = new Set();
+    let entry = this._stateByBrowser.get(browser);
+    for (let prePath in entry) {
+      for (let id in entry[prePath]) {
+        permissions.add(id);
+      }
+    }
+    return permissions;
+  },
+
   // Clears all permissions for the specified browser.
   // Unlike other methods, this does NOT clear only for
   // the currentURI but the whole browser state.
   clear(browser) {
+    let permissions = this.getAllPermissionIds(browser);
     this._stateByBrowser.delete(browser);
+    for (let permission of permissions) {
+      this.notifyWhenTemporaryPermissionChanged(browser, permission, null,
+                                                SitePermissions.UNKNOWN);
+    }
   },
 
   // Copies the temporary permission state of one browser
   // into a new entry for the other browser.
   copy(browser, newBrowser) {
     let entry = this._stateByBrowser.get(browser);
     if (entry) {
       this._stateByBrowser.set(newBrowser, entry);
     }
   },
+
+  // If permission has property 'notifyWhenTemporaryPermissionChanged', then
+  // notify browser when the temporary permission changed.
+  notifyWhenTemporaryPermissionChanged(browser, id, prePath, state) {
+    if (!(id in gPermissionObject) ||
+        !gPermissionObject[id].notifyWhenTemporaryPermissionChanged) {
+      return;
+    }
+    browser.messageManager
+           .sendAsyncMessage("TemporaryPermissionChanged",
+                             { permission: id,
+                               prePath,
+                               state });
+  },
 };
 
 // This hold a flag per browser to indicate whether we should show the
 // user a notification as a permission has been requested that has been
 // blocked globally. We only want to notify the user in the case that
 // they actually requested the permission within the current page load
 // so will clear the flag on navigation.
 const GloballyBlockedPermissions = {
@@ -717,16 +751,17 @@ var gPermissionObject = {
    *    The PROMPT_HIDE state is deliberately excluded from "plugin:flash" since we
    *    don't want to expose a "Hide Prompt" button to the user through pageinfo.
    */
 
   "autoplay-media": {
     exactHostMatch: true,
     showGloballyBlocked: true,
     permitTemporaryAllow: true,
+    notifyWhenTemporaryPermissionChanged: true,
     getDefault() {
       let state = Services.prefs.getIntPref("media.autoplay.default",
                                             Ci.nsIAutoplay.PROMPT);
       if (state == Ci.nsIAutoplay.ALLOWED) {
         return SitePermissions.ALLOW;
       } if (state == Ci.nsIAutoplay.BLOCKED) {
         return SitePermissions.BLOCK;
       }
--- a/toolkit/actors/AudioPlaybackChild.jsm
+++ b/toolkit/actors/AudioPlaybackChild.jsm
@@ -60,13 +60,22 @@ class AudioPlaybackChild extends ActorCh
           name += (data === "active") ? "Start" : "Stop";
         }
         this.mm.sendAsyncMessage(name);
       }
     }
   }
 
   receiveMessage(msg) {
-    if (msg.name == "AudioPlayback") {
-      this.handleMediaControlMessage(msg.data.type);
+    switch (msg.name) {
+      case "AudioPlayback":
+        this.handleMediaControlMessage(msg.data.type);
+        break;
+      case "TemporaryPermissionChanged":
+        if (msg.data.permission !== "autoplay-media") {
+          return;
+        }
+
+        // TODO : update permission in content side.
+        break;
     }
   }
 }
--- a/toolkit/modules/ActorManagerParent.jsm
+++ b/toolkit/modules/ActorManagerParent.jsm
@@ -110,16 +110,17 @@ let ACTORS = {
     },
   },
 
   AudioPlayback: {
     child: {
       module: "resource://gre/actors/AudioPlaybackChild.jsm",
       messages: [
         "AudioPlayback",
+        "TemporaryPermissionChanged",
       ],
       observers: [
         "audio-playback",
       ],
     },
   },
 
   Browser: {