Bug 1330467 - part 9. Use principal with mobile permissions; r=johannh,snorp
authorLiang-Heng Chen <xeonchen@gmail.com>
Tue, 07 May 2019 22:20:46 +0000
changeset 473399 2648f5bb180463e213b55a0f1434c51c9853f213
parent 473398 4686eebd8962db7d03d7fbca124cca28069f4a72
child 473400 2cd09bae2bdf579412d83e7a5c11381de18f9e48
push id35996
push userdvarga@mozilla.com
push dateFri, 10 May 2019 21:46:48 +0000
treeherdermozilla-central@362df4629f8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohannh, snorp
bugs1330467
milestone68.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 1330467 - part 9. Use principal with mobile permissions; r=johannh,snorp Differential Revision: https://phabricator.services.mozilla.com/D19930
mobile/android/chrome/content/OfflineApps.js
mobile/android/chrome/content/PermissionsHelper.js
mobile/android/chrome/content/browser.js
mobile/android/components/geckoview/GeckoViewPermission.js
mobile/android/modules/WebrtcUI.jsm
--- a/mobile/android/chrome/content/OfflineApps.js
+++ b/mobile/android/chrome/content/OfflineApps.js
@@ -4,20 +4,21 @@
 "use strict";
 
 var OfflineApps = {
   offlineAppRequested: function(aContentWindow) {
     if (!Services.prefs.getBoolPref("browser.offline-apps.notify"))
       return;
 
     let tab = BrowserApp.getTabForWindow(aContentWindow);
+    let principal = aContentWindow.document.nodePrincipal;
     let currentURI = aContentWindow.document.documentURIObject;
 
     // Don't bother showing UI if the user has already made a decision
-    if (Services.perms.testExactPermission(currentURI, "offline-app") != Services.perms.UNKNOWN_ACTION)
+    if (Services.perms.testExactPermissionFromPrincipal(principal, "offline-app") != Services.perms.UNKNOWN_ACTION)
       return;
 
     try {
       if (Services.prefs.getBoolPref("offline-apps.allow_by_default")) {
         // All pages can use offline capabilities, no need to ask the user
         return;
       }
     } catch (e) {
@@ -45,26 +46,26 @@ var OfflineApps = {
 
     let requestor = BrowserApp.manifest ? "'" + BrowserApp.manifest.name + "'" : host;
     let message = strings.formatStringFromName("offlineApps.ask", [requestor], 1);
     let options = { checkbox: Strings.browser.GetStringFromName("offlineApps.dontAskAgain") };
     NativeWindow.doorhanger.show(message, notificationID, buttons, tab.id, options);
   },
 
   allowSite: function(aDocument) {
-    Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.ALLOW_ACTION);
+    Services.perms.addFromPrincipal(aDocument.nodePrincipal, "offline-app", Services.perms.ALLOW_ACTION);
 
     // When a site is enabled while loading, manifest resources will
     // start fetching immediately.  This one time we need to do it
     // ourselves.
     this._startFetching(aDocument);
   },
 
   disallowSite: function(aDocument) {
-    Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.DENY_ACTION);
+    Services.perms.addFromPrincipal(aDocument.nodePrincipal, "offline-app", Services.perms.DENY_ACTION);
   },
 
   _startFetching: function(aDocument) {
     if (!aDocument.documentElement)
       return;
 
     let manifest = aDocument.documentElement.getAttribute("manifest");
     if (!manifest)
--- a/mobile/android/chrome/content/PermissionsHelper.js
+++ b/mobile/android/chrome/content/PermissionsHelper.js
@@ -45,29 +45,29 @@ var PermissionsHelper = {
     "native-intent": {
       label: "helperapps.openWithList2",
       allowed: "helperapps.always",
       denied: "helperapps.never",
     },
   },
 
   onEvent: function onEvent(event, data, callback) {
-    let uri = BrowserApp.selectedBrowser.currentURI;
+    let principal = BrowserApp.selectedBrowser.contentPrincipal;
     let check = false;
 
     switch (event) {
       case "Permissions:Check":
         check = true;
         // fall-through
 
       case "Permissions:Get":
         let permissions = [];
         for (let i = 0; i < this._permissonTypes.length; i++) {
           let type = this._permissonTypes[i];
-          let value = this.getPermission(uri, type);
+          let value = this.getPermission(principal, type);
 
           // Only add the permission if it was set by the user
           if (value == Services.perms.UNKNOWN_ACTION)
             continue;
 
           if (check) {
             GlobalEventDispatcher.sendRequest({
               type: "Permissions:CheckResult",
@@ -127,58 +127,58 @@ var PermissionsHelper = {
    * Gets the permission value stored for a specified permission type.
    *
    * @param aType
    *        The permission type string stored in permission manager.
    *        e.g. "geolocation", "indexedDB", "popup"
    *
    * @return A permission value defined in nsIPermissionManager.
    */
-  getPermission: function getPermission(aURI, aType) {
+  getPermission: function getPermission(aPrincipal, aType) {
     // Password saving isn't a nsIPermissionManager permission type, so handle
     // it seperately.
     if (aType == "password") {
       // By default, login saving is enabled, so if it is disabled, the
       // user selected the never remember option
       if (!Services.logins.getLoginSavingEnabled(aURI.displayPrePath))
         return Services.perms.DENY_ACTION;
 
       // Check to see if the user ever actually saved a login
       if (Services.logins.countLogins(aURI.displayPrePath, "", ""))
         return Services.perms.ALLOW_ACTION;
 
       return Services.perms.UNKNOWN_ACTION;
     }
 
-    // Geolocation consumers use testExactPermission
+    // Geolocation consumers use testExactPermissionForPrincipal
     if (aType == "geolocation")
-      return Services.perms.testExactPermission(aURI, aType);
+      return Services.perms.testExactPermissionForPrincipal(aPrincipal, aType);
 
-    return Services.perms.testPermission(aURI, aType);
+    return Services.perms.testPermissionForPrincipal(aPrincipal, aType);
   },
 
   /**
    * Clears a user-set permission value for the site given a permission type.
    *
    * @param aType
    *        The permission type string stored in permission manager.
    *        e.g. "geolocation", "indexedDB", "popup"
    */
-  clearPermission: function clearPermission(aURI, aType, aContext) {
+  clearPermission: function clearPermission(aPrincipal, aType, aContext) {
     // Password saving isn't a nsIPermissionManager permission type, so handle
     // it seperately.
     if (aType == "password") {
       // Get rid of exisiting stored logings
       let logins = Services.logins.findLogins({}, aURI.displayPrePath, "", "");
       for (let i = 0; i < logins.length; i++) {
         Services.logins.removeLogin(logins[i]);
       }
       // Re-set login saving to enabled
       Services.logins.setLoginSavingEnabled(aURI.displayPrePath, true);
     } else {
-      Services.perms.remove(aURI, aType);
+      Services.perms.removeFromPrincipal(aPrincipal, aType);
       // Clear content prefs set in ContentPermissionPrompt.js
       Cc["@mozilla.org/content-pref/service;1"]
         .getService(Ci.nsIContentPrefService2)
         .removeByDomainAndName(aURI.spec, aType + ".request.remember", aContext);
     }
   },
 };
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1873,28 +1873,28 @@ var BrowserApp = {
             let normalizedUrl = Services.io.newURI("https://" + browser.currentURI.hostPort);
             if (data.allowContent) {
               // Add the current host in the 'trackingprotection' consumer of
               // the permission manager using a normalized URI. This effectively
               // places this host on the tracking protection white list.
               if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
                 PrivateBrowsingUtils.addToTrackingAllowlist(normalizedUrl);
               } else {
-                Services.perms.add(normalizedUrl, "trackingprotection", Services.perms.ALLOW_ACTION);
+                Services.perms.addFromPrincipal(browser.contentPrincipal, "trackingprotection", Services.perms.ALLOW_ACTION);
                 Telemetry.addData("TRACKING_PROTECTION_EVENTS", 1);
               }
             } else {
               // Remove the current host from the 'trackingprotection' consumer
               // of the permission manager. This effectively removes this host
               // from the tracking protection white list (any list actually).
               // eslint-disable-next-line no-lonely-if
               if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
                 PrivateBrowsingUtils.removeFromTrackingAllowlist(normalizedUrl);
               } else {
-                Services.perms.remove(normalizedUrl, "trackingprotection");
+                Services.perms.removeFromPrincipal(browser.contentPrincipal, "trackingprotection");
                 Telemetry.addData("TRACKING_PROTECTION_EVENTS", 2);
               }
             }
           }
         }
 
         // Try to use the session history to reload so that framesets are
         // handled properly. If the window has no session history, fall back
@@ -5322,17 +5322,17 @@ var PopupBlockerObserver = {
   onUpdateBlockedPopups: function onUpdateBlockedPopups(aEvent) {
     let browser = BrowserApp.selectedBrowser;
     if (aEvent.originalTarget != browser)
       return;
 
     if (!browser.blockedPopups)
       return;
 
-    let result = Services.perms.testExactPermission(BrowserApp.selectedBrowser.currentURI, "popup");
+    let result = Services.perms.testExactPermissionFromPrincipal(BrowserApp.selectedBrowser.contentPrincipal, "popup");
     if (result == Ci.nsIPermissionManager.DENY_ACTION)
       return;
 
     // Only show the notification again if we've not already shown it. Since
     // notifications are per-browser, we don't need to worry about re-adding
     // it.
     if (!browser.blockedPopups.reported) {
       if (Services.prefs.getBoolPref("privacy.popups.showBrowserMessage")) {
@@ -5370,18 +5370,18 @@ var PopupBlockerObserver = {
       }
       // Record the fact that we've reported this blocked popup, so we don't
       // show it again.
       browser.blockedPopups.reported = true;
     }
   },
 
   allowPopupsForSite: function allowPopupsForSite(aAllow) {
-    let currentURI = BrowserApp.selectedBrowser.currentURI;
-    Services.perms.add(currentURI, "popup", aAllow
+    let principal = BrowserApp.selectedBrowser.contentPrincipal;
+    Services.perms.addFromPrincipal(principal, "popup", aAllow
                        ? Ci.nsIPermissionManager.ALLOW_ACTION
                        : Ci.nsIPermissionManager.DENY_ACTION);
     dump("Allowing popups for: " + currentURI);
   },
 
   showPopupsForSite: function showPopupsForSite() {
     let uri = BrowserApp.selectedBrowser.currentURI;
     let {blockedPopups} = BrowserApp.selectedBrowser;
--- a/mobile/android/components/geckoview/GeckoViewPermission.js
+++ b/mobile/android/components/geckoview/GeckoViewPermission.js
@@ -44,28 +44,29 @@ GeckoViewPermission.prototype = {
         break;
       }
     }
   },
 
   receiveMessage(aMsg) {
     switch (aMsg.name) {
       case "GeckoView:AddCameraPermission": {
-        let uri;
+        let principal;
         try {
           // This fails for principals that serialize to "null", e.g. file URIs.
-          uri = Services.io.newURI(aMsg.data.origin);
+          principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(aMsg.data.origin);
         } catch (e) {
-          uri = Services.io.newURI(aMsg.data.documentURI);
+          principal = Services.scriptSecurityManager.createCodebasePrincipal(
+            Services.io.newURI(aMsg.data.documentURI), {});
         }
         // Although the lifetime is "session" it will be removed upon
         // use so it's more of a one-shot.
-        Services.perms.add(uri, "MediaManagerVideo",
-                           Services.perms.ALLOW_ACTION,
-                           Services.perms.EXPIRE_SESSION);
+        Services.perms.addFromPrincipal(principal, "MediaManagerVideo",
+                                        Services.perms.ALLOW_ACTION,
+                                        Services.perms.EXPIRE_SESSION);
         break;
       }
     }
   },
 
   handleMediaAskDevicePermission: function(aType, aCallback) {
     let perms = [];
     if (aType === "video" || aType === "all") {
--- a/mobile/android/modules/WebrtcUI.jsm
+++ b/mobile/android/modules/WebrtcUI.jsm
@@ -156,17 +156,17 @@ var WebrtcUI = {
       },
       function(error) {
         Cu.reportError(error);
       },
       aSubject.innerWindowID,
       aSubject.callID);
   },
 
-  getDeviceButtons: function(audioDevices, videoDevices, aCallID, aUri) {
+  getDeviceButtons: function(audioDevices, videoDevices, aCallID, aPrincipal) {
     return [{
       label: Strings.browser.GetStringFromName("getUserMedia.denyRequest.label"),
       callback: function() {
         Services.obs.notifyObservers(null, "getUserMedia:response:deny", aCallID);
       },
     },
     {
       label: Strings.browser.GetStringFromName("getUserMedia.shareRequest.label"),
@@ -182,17 +182,17 @@ var WebrtcUI = {
         let videoId = 0;
         if (inputs && inputs.videoSource != undefined)
           videoId = inputs.videoSource;
         if (videoDevices[videoId]) {
           allowedDevices.appendElement(videoDevices[videoId]);
           let perms = Services.perms;
           // Although the lifetime is "session" it will be removed upon
           // use so it's more of a one-shot.
-          perms.add(aUri, "MediaManagerVideo", perms.ALLOW_ACTION, perms.EXPIRE_SESSION);
+          perms.addFromPrincipal(aPrincipal, "MediaManagerVideo", perms.ALLOW_ACTION, perms.EXPIRE_SESSION);
         }
 
         Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
       },
       positive: true,
     }];
   },
 
@@ -310,29 +310,29 @@ var WebrtcUI = {
     else if (audioDevices.length)
       requestType = "Microphone";
     else if (videoDevices.length)
       requestType = "Camera";
     else
       return;
 
     let chromeWin = this.getChromeWindow(aContentWindow);
-    let uri = aContentWindow.document.documentURIObject;
-    let host = uri.host;
+    let principal = aContentWindow.document.nodePrincipal;
+    let host = principal.URI.host;
     let requestor = (chromeWin.BrowserApp && chromeWin.BrowserApp.manifest) ?
           "'" + chromeWin.BrowserApp.manifest.name + "'" : host;
     let message = Strings.browser.formatStringFromName("getUserMedia.share" + requestType + ".message", [ requestor ], 1);
 
     let options = { inputs: [] };
     if (videoDevices.length > 1 || audioDevices.length > 0) {
       // videoSource is both the string used for l10n lookup and the object that will be returned
       this._addDevicesToOptions(videoDevices, "videoSource", options);
     }
 
     if (audioDevices.length > 1 || videoDevices.length > 0) {
       this._addDevicesToOptions(audioDevices, "audioDevice", options);
     }
 
-    let buttons = this.getDeviceButtons(audioDevices, videoDevices, aCallID, uri);
+    let buttons = this.getDeviceButtons(audioDevices, videoDevices, aCallID, principal);
 
     DoorHanger.show(aContentWindow, message, "webrtc-request", buttons, options, "WEBRTC");
   },
 };