Bug 770731 - Expose JS API for modifying app permissions. r=sicking
authorGregor Wagner <anygregor@gmail.com>
Tue, 18 Sep 2012 14:52:39 -0700
changeset 114304 5f3887536eef97feed9a8724d86489aa69704bb2
parent 114303 7e4a6bba7ce557aee006d24974d4ba721b47c1cd
child 114305 6be84c0e0f0e7584e6ea19bde12a3561974bbcc4
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs770731
milestone18.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 770731 - Expose JS API for modifying app permissions. r=sicking
b2g/app/b2g.js
b2g/chrome/content/shell.js
b2g/installer/package-manifest.in
browser/installer/package-manifest.in
dom/Makefile.in
dom/interfaces/permission/Makefile.in
dom/interfaces/permission/nsIDOMPermissionSettings.idl
dom/permission/Makefile.in
dom/permission/PermissionSettings.js
dom/permission/PermissionSettings.jsm
dom/permission/PermissionSettings.manifest
dom/permission/tests/Makefile.in
dom/permission/tests/test_permission_basics.html
modules/libpref/src/init/all.js
netwerk/base/public/nsIPermissionManager.idl
testing/mochitest/android.json
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -382,16 +382,17 @@ pref("dom.sms.enabled", true);
 // Temporary permission hack for WebContacts
 pref("dom.mozContacts.enabled", true);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", true);
 
 // WebSettings
 pref("dom.mozSettings.enabled", true);
+pref("dom.mozPermissionSettings.enabled", true);
 
 // controls if we want camera support
 pref("device.camera.enabled", true);
 pref("media.realtime_decoder.enabled", true);
 
 // TCPSocket
 pref("dom.mozTCPSocket.enabled", true);
 
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -12,16 +12,17 @@ const Cr = Components.results;
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/ContactService.jsm');
 Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/Webapps.jsm');
 Cu.import('resource://gre/modules/AlarmService.jsm');
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
 Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
+Cu.import('resource://gre/modules/PermissionSettings.jsm');
 Cu.import('resource://gre/modules/ObjectWrapper.jsm');
 Cu.import('resource://gre/modules/accessibility/AccessFu.jsm');
 Cu.import('resource://gre/modules/Payment.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -187,16 +187,17 @@
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_mms.xpt
 #endif
 @BINPATH@/components/dom_browserelement.xpt
 @BINPATH@/components/dom_messages.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_settings.xpt
+@BINPATH@/components/dom_permissionsettings.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_views.xpt
 @BINPATH@/components/dom_xbl.xpt
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -194,16 +194,17 @@
 @BINPATH@/components/dom_json.xpt
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/dom_mms.xpt
 #endif
 @BINPATH@/components/dom_browserelement.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_settings.xpt
+@BINPATH@/components/dom_permissionsettings.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_xbl.xpt
 @BINPATH@/components/dom_xpath.xpt
 @BINPATH@/components/dom_xul.xpt
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -30,16 +30,17 @@ PARALLEL_DIRS = \
   interfaces/xpath \
   interfaces/load-save \
   interfaces/xul \
   interfaces/storage \
   interfaces/json \
   interfaces/offline \
   interfaces/geolocation \
   interfaces/notification \
+  interfaces/permission \
   interfaces/svg \
   interfaces/smil \
   interfaces/apps \
   $(NULL)
 
 PARALLEL_DIRS += \
   apps \
   base \
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/permission/Makefile.in
@@ -0,0 +1,20 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH          = ../../..
+topsrcdir      = @top_srcdir@
+srcdir         = @srcdir@
+VPATH          = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE         = dom
+XPIDL_MODULE   = dom_permissionsettings
+GRE_MODULE     = 1
+
+XPIDLSRCS =                             \
+            nsIDOMPermissionSettings.idl    \
+            $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/permission/nsIDOMPermissionSettings.idl
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "domstubs.idl"
+
+interface nsIDOMDOMRequest;
+
+[scriptable, uuid(36e73ef0-c6f4-11e1-9b21-0800200c9a66)]
+interface nsIDOMPermissionSettings : nsISupports
+{
+  DOMString get(in DOMString permission, in DOMString access, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
+
+  void set(in DOMString permission, in DOMString access, in DOMString manifestURI, in DOMString origin, in DOMString value, in bool browserFlag);
+};
--- a/dom/permission/Makefile.in
+++ b/dom/permission/Makefile.in
@@ -10,17 +10,25 @@ VPATH = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         = dom
 LIBRARY_NAME   = jsdompermission_s
 
 XPIDL_MODULE   = dom_permission
 GRE_MODULE     = 1
 
+EXTRA_COMPONENTS =        \
+  PermissionSettings.js       \
+  PermissionSettings.manifest \
+  $(NULL)
+
 EXTRA_JS_MODULES =   \
   PermissionPromptHelper.jsm \
+  PermissionSettings.jsm \
   $(NULL)
 
+TEST_DIRS += tests
+
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -D_IMPL_NS_LAYOUT
new file mode 100644
--- /dev/null
+++ b/dom/permission/PermissionSettings.js
@@ -0,0 +1,97 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+let DEBUG = 0;
+if (DEBUG)
+  debug = function (s) { dump("-*- PermissionSettings: " + s + "\n"); }
+else
+  debug = function (s) {}
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/PermissionSettings.jsm");
+
+var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"].getService(Components.interfaces.nsISyncMessageSender);
+
+// PermissionSettings
+
+const PERMISSIONSETTINGS_CONTRACTID = "@mozilla.org/permissionSettings;1";
+const PERMISSIONSETTINGS_CID        = Components.ID("{36e73ef0-c6f4-11e1-9b21-0800200c9a66}");
+const nsIDOMPermissionSettings      = Components.interfaces.nsIDOMPermissionSettings;
+
+function PermissionSettings()
+{
+  debug("Constructor");
+}
+
+var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
+var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"].getService(Components.interfaces.nsIScriptSecurityManager);
+var appsService = Components.classes["@mozilla.org/AppsService;1"].getService(Components.interfaces.nsIAppsService);
+
+PermissionSettings.prototype = {
+  get: function get(aPermission, aAccess, aManifestURL, aOrigin, aBrowserFlag) {
+    debug("Get called with: " + aPermission + ", " + aAccess + ", " + aManifestURL + ", " + aOrigin + ", " + aBrowserFlag);
+    let uri = Services.io.newURI(aOrigin, null, null);
+    let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
+    let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
+    let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
+
+    switch (result)
+    {
+      case Ci.nsIPermissionManager.UNKNOWN_ACTION:
+        return "unknown"
+      case Ci.nsIPermissionManager.ALLOW_ACTION:
+        return "allow";
+      case Ci.nsIPermissionManager.DENY_ACTION:
+        return "deny";
+      case Ci.nsIPermissionManager.PROMPT_ACTION:
+        return "prompt";
+      default:
+        dump("Unsupported PermissionSettings Action!\n");
+        return "unknown";
+    }
+  },
+
+  set: function set(aPermission, aAccess, aManifestURL, aOrigin, aValue, aBrowserFlag) {
+    debug("Set called with: " + aPermission + ", " + aAccess + ", " + aManifestURL + ", " + aOrigin + ",  " + aValue + ", " + aBrowserFlag);
+    let action;
+    cpm.sendSyncMessage("PermissionSettings:AddPermission", {
+      type: aPermission,
+      access: aAccess,
+      origin: aOrigin,
+      manifestURL: aManifestURL,
+      value: aValue,
+      browserFlag: aBrowserFlag
+    });
+  },
+
+  init: function(aWindow) {
+    debug("init");
+    // Set navigator.mozPermissionSettings to null.
+    if (!Services.prefs.getBoolPref("dom.mozPermissionSettings.enabled")
+        || Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "permissions")) {
+      debug("Permission to get/set permissions not granted!");
+      return null;
+    }
+
+    debug("Permission to get/set permissions granted!");
+  },
+
+  classID : PERMISSIONSETTINGS_CID,
+  QueryInterface : XPCOMUtils.generateQI([nsIDOMPermissionSettings, Ci.nsIDOMGlobalPropertyInitializer]),
+
+  classInfo : XPCOMUtils.generateCI({classID: PERMISSIONSETTINGS_CID,
+                                     contractID: PERMISSIONSETTINGS_CONTRACTID,
+                                     classDescription: "PermissionSettings",
+                                     interfaces: [nsIDOMPermissionSettings],
+                                     flags: Ci.nsIClassInfo.DOM_OBJECT})
+}
+
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([PermissionSettings])
new file mode 100644
--- /dev/null
+++ b/dom/permission/PermissionSettings.jsm
@@ -0,0 +1,83 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+let DEBUG = 0;
+if (DEBUG)
+  debug = function (s) { dump("-*- PermissionSettings Module: " + s + "\n"); }
+else
+  debug = function (s) {}
+
+const Cu = Components.utils; 
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+let EXPORTED_SYMBOLS = ["PermissionSettingsModule"];
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
+
+var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
+var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
+var appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
+
+let PermissionSettingsModule = {
+  init: function() {
+    debug("Init");
+    ppmm.addMessageListener("PermissionSettings:AddPermission", this);
+    Services.obs.addObserver(this, "profile-before-change", false);
+  },
+
+  addPermission: function(aData, aCallbacks) {
+    let uri = Services.io.newURI(aData.origin, null, null);
+    let appID = appsService.getAppLocalIdByManifestURL(aData.manifestURL);
+    let principal = secMan.getAppCodebasePrincipal(uri, appID, aData.browserFlag);
+
+    let action;
+    switch (aData.value)
+    {
+      case "unknonwn":
+        action = Ci.nsIPermissionManager.UNKNOWN_ACTION;
+        break;
+      case "allow":
+        action = Ci.nsIPermissionManager.ALLOW_ACTION;
+        break;
+      case "deny":
+        action = Ci.nsIPermissionManager.DENY_ACTION;
+        break;
+      case "prompt":
+        action = Ci.nsIPermissionManager.PROMPT_ACTION;
+        break;
+      default:
+        dump("Unsupported PermisionSettings Action: " + aData.value +"\n");
+        action = Ci.nsIPermissionManager.UNKNOWN_ACTION;
+    }
+    debug("add: " + aData.origin + " " + appID + " " + action);
+    permissionManager.addFromPrincipal(principal, aData.type, action);
+  },
+
+  observe: function(aSubject, aTopic, aData) {
+    ppmm.removeMessageListener("PermissionSettings:AddPermission", this);
+    Services.obs.removeObserver(this, "profile-before-change");
+    ppmm = null;
+  },
+
+  receiveMessage: function(aMessage) {
+    debug("PermissionSettings::receiveMessage " + aMessage.name);
+    let mm = aMessage.target;
+    let msg = aMessage.data;
+
+    let result;
+    if (aMessage.name == "PermissionSettings:AddPermission") {
+      this.addPermission(msg);
+    }
+  }
+}
+
+PermissionSettingsModule.init();
new file mode 100644
--- /dev/null
+++ b/dom/permission/PermissionSettings.manifest
@@ -0,0 +1,3 @@
+component {36e73ef0-c6f4-11e1-9b21-0800200c9a66} PermissionSettings.js
+contract @mozilla.org/permissionSettings;1 {36e73ef0-c6f4-11e1-9b21-0800200c9a66}
+category JavaScript-navigator-property mozPermissionSettings @mozilla.org/permissionSettings;1
new file mode 100644
--- /dev/null
+++ b/dom/permission/tests/Makefile.in
@@ -0,0 +1,27 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH            = ../../..
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
+
+relativesrcdir   = dom/permission/tests
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+  test_permission_basics.html \
+  $(NULL)
+
+_CHROME_TEST_FILES = \
+  $(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/permission/tests/test_permission_basics.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id={770731}
+-->
+<head>
+  <title>Test for Bug {770731} Permissions</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={770731}">Mozilla Bug {674720}</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+"use strict";
+
+var comp = SpecialPowers.wrap(Components);
+SpecialPowers.pushPrefEnv({ "set": [["dom.mozPermissionSettings.enabled", true]] }, 
+                          function() {
+                            SpecialPowers.addPermission("permissions", true, document);
+                          });
+
+comp.utils.import("resource://gre/modules/PermissionSettings.jsm");
+var mozPermissions = window.navigator.mozPermissionSettings;
+
+function permissionTest() {
+  if (gPermissionssEnabled) {
+    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "unknown", true);
+    var result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    is(result, "unknown", "same result");
+    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "allow", true);
+    result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    is(result, "allow", "same result");
+    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "deny", true);
+    result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    is(result, "deny", "same result");
+    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "prompt", true);
+    result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    is(result, "prompt", "same result");
+    SimpleTest.finish();
+  } else {
+    is(mozPermissions, null, "mozPermissionSettings is null when not enabled.");
+    SimpleTest.finish();
+  }
+}
+
+var gPermissionssEnabled = SpecialPowers.getBoolPref("dom.mozPermissionSettings.enabled");
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(permissionTest);
+
+ok(true, "test passed");
+</script>
+</pre>
+</body>
+</html>
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3671,16 +3671,17 @@ pref("dom.sms.enabled", false);
 // WebContacts
 pref("dom.mozContacts.enabled", false);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", false);
 
 // WebSettings
 pref("dom.mozSettings.enabled", false);
+pref("dom.mozPermissionSettings.enabled", false);
 
 // enable JS dump() function.
 pref("browser.dom.window.dump.enabled", false);
 
 // SPS Profiler
 pref("profiler.enabled", false);
 pref("profiler.interval", 10);
 pref("profiler.entries", 100000);
--- a/netwerk/base/public/nsIPermissionManager.idl
+++ b/netwerk/base/public/nsIPermissionManager.idl
@@ -43,16 +43,17 @@ interface nsIPermissionManager : nsISupp
    * the permission param of the add method
    * NOTE: UNKNOWN_ACTION (0) is reserved to represent the
    * default permission when no entry is found for a host, and
    * should not be used by consumers to indicate otherwise.
    */
   const uint32_t UNKNOWN_ACTION = 0;
   const uint32_t ALLOW_ACTION = 1;
   const uint32_t DENY_ACTION = 2;
+  const uint32_t PROMPT_ACTION = 3;
 
   /**
    * Predefined expiration types for permissions.  Permissions can be permanent
    * (never expire), expire at the end of the session, or expire at a specified
    * time.
    */
   const uint32_t EXPIRE_NEVER = 0;
   const uint32_t EXPIRE_SESSION = 1;
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -151,16 +151,17 @@
  "dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT",
  "dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT",
  "dom/network/tests/test_network_basics.html": "",
  "dom/settings/tests/test_settings_events.html": "",
  "dom/settings/tests/test_settings_basics.html": "",
  "dom/contacts/tests/test_contacts_blobs.html": "",
  "dom/contacts/tests/test_contacts_basics.html": "",
  "dom/contacts/tests/test_contacts_events.html": "",
+ "dom/permission/tests/test_permission_basics.html": "",
  "dom/sms/tests/test_sms_basics.html": "",
  "dom/tests/mochitest/ajax/jquery/test_jQuery.html": "bug 775227",
  "dom/tests/mochitest/ajax/offline/test_simpleManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_updatingManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml": "TIMED_OUT",
  "dom/tests/mochitest/ajax/prototype/test_Prototype.html": "",
  "dom/tests/mochitest/ajax/scriptaculous/test_Scriptaculous.html": "",
  "dom/tests/mochitest/browser-frame/test_browserFrame1.html": "TIMED_OUT",