Bug 1203233 implement geolocation permission, r?aswan,florian
MozReview-Commit-ID: 8V7bNyeGZNh
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -78,16 +78,17 @@ webextPerms.updateMenuItem=%S requires n
# Note, this string will be used as raw markup. Avoid characters like <, >, &
webextPerms.updateText=%S has been updated. You must approve new permissions before the updated version will install. Choosing “Cancel” will maintain your current add-on version.
webextPerms.updateAccept.label=Update
webextPerms.updateAccept.accessKey=U
webextPerms.description.bookmarks=Read and modify bookmarks
webextPerms.description.downloads=Download files and read and modify the browser’s download history
+webextPerms.description.geolocation=Access your location
webextPerms.description.history=Access browsing history
# LOCALIZATION NOTE (webextPerms.description.nativeMessaging)
# %S will be replaced with the name of the application
webextPerms.description.nativeMessaging=Exchange messages with programs other than %S
webextPerms.description.notifications=Display notifications to you
webextPerms.description.sessions=Access recently closed tabs
webextPerms.description.tabs=Access browser tabs
webextPerms.description.topSites=Access browsing history
--- a/browser/modules/PermissionUI.jsm
+++ b/browser/modules/PermissionUI.jsm
@@ -241,26 +241,21 @@ this.PermissionPromptPrototype = {
/**
* Will determine if a prompt should be shown to the user, and if so,
* will show it.
*
* If a permissionKey is defined prompt() might automatically
* allow or cancel itself based on the user's current
* permission settings without displaying the prompt.
*
- * If the <xul:browser> that the request is associated with
- * does not belong to a browser window with the PopupNotifications
- * global set, the prompt request is ignored.
+ * If the permission is not already set and the <xul:browser> that the request
+ * is associated with does not belong to a browser window with the
+ * PopupNotifications global set, the prompt request is ignored.
*/
prompt() {
- let chromeWin = this.browser.ownerGlobal;
- if (!chromeWin.PopupNotifications) {
- return;
- }
-
// We ignore requests from non-nsIStandardURLs
let requestingURI = this.principal.URI;
if (!(requestingURI instanceof Ci.nsIStandardURL)) {
return;
}
if (this.permissionKey) {
// If we're reading and setting permissions, then we need
@@ -281,16 +276,22 @@ this.PermissionPromptPrototype = {
}
// Tell the browser to refresh the identity block display in case there
// are expired permission states.
this.browser.dispatchEvent(new this.browser.ownerGlobal
.CustomEvent("PermissionStateChange"));
}
+ let chromeWin = this.browser.ownerGlobal;
+ if (!chromeWin.PopupNotifications) {
+ this.cancel();
+ return;
+ }
+
// Transform the PermissionPrompt actions into PopupNotification actions.
let popupNotificationActions = [];
for (let promptAction of this.promptActions) {
let action = {
label: promptAction.label,
accessKey: promptAction.accessKey,
callback: state => {
if (promptAction.callback) {
--- a/browser/modules/SitePermissions.jsm
+++ b/browser/modules/SitePermissions.jsm
@@ -247,17 +247,17 @@ this.SitePermissions = {
* even though nsIPermissionManager can still handle them.
*
* @param {nsIURI} uri
* The URI to check.
*
* @return {boolean} if the URI is supported.
*/
isSupportedURI(uri) {
- return uri && (uri.schemeIs("http") || uri.schemeIs("https"));
+ return uri && ["http", "https", "moz-extension"].includes(uri.scheme);
},
/**
* Gets an array of all permission IDs.
*
* @return {Array<String>} an array of all permission IDs.
*/
listPermissions() {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/ext-geolocation.js
@@ -0,0 +1,28 @@
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+XPCOMUtils.defineLazyModuleGetter(this, "Services",
+ "resource://gre/modules/Services.jsm");
+
+// If the user has changed the permission on the addon to something other than
+// always allow, then we want to preserve that choice. We only set the
+// permission if it is not set (unknown_action), and we only remove the
+// permission on shutdown if it is always allow.
+
+/* eslint-disable mozilla/balanced-listeners */
+extensions.on("startup", (type, extension) => {
+ if (extension.hasPermission("geolocation") &&
+ Services.perms.testPermission(extension.principal.URI, "geo") == Services.perms.UNKNOWN_ACTION) {
+ Services.perms.add(extension.principal.URI, "geo",
+ Services.perms.ALLOW_ACTION,
+ Services.perms.EXPIRE_SESSION);
+ }
+});
+
+extensions.on("shutdown", (type, extension) => {
+ if (extension.hasPermission("geolocation") &&
+ Services.perms.testPermission(extension.principal.URI, "geo") == Services.perms.ALLOW_ACTION) {
+ Services.perms.remove(extension.principal.URI, "geo");
+ }
+});
--- a/toolkit/components/extensions/extensions-toolkit.manifest
+++ b/toolkit/components/extensions/extensions-toolkit.manifest
@@ -1,14 +1,15 @@
# scripts
category webextension-scripts alarms chrome://extensions/content/ext-alarms.js
category webextension-scripts backgroundPage chrome://extensions/content/ext-backgroundPage.js
category webextension-scripts contextualIdentities chrome://extensions/content/ext-contextualIdentities.js
category webextension-scripts cookies chrome://extensions/content/ext-cookies.js
category webextension-scripts downloads chrome://extensions/content/ext-downloads.js
+category webextension-scripts geolocation chrome://extensions/content/ext-geolocation.js
category webextension-scripts management chrome://extensions/content/ext-management.js
category webextension-scripts notifications chrome://extensions/content/ext-notifications.js
category webextension-scripts i18n chrome://extensions/content/ext-i18n.js
category webextension-scripts idle chrome://extensions/content/ext-idle.js
category webextension-scripts webRequest chrome://extensions/content/ext-webRequest.js
category webextension-scripts webNavigation chrome://extensions/content/ext-webNavigation.js
category webextension-scripts runtime chrome://extensions/content/ext-runtime.js
category webextension-scripts extension chrome://extensions/content/ext-extension.js
--- a/toolkit/components/extensions/jar.mn
+++ b/toolkit/components/extensions/jar.mn
@@ -5,16 +5,17 @@
toolkit.jar:
% content extensions %content/extensions/
content/extensions/ext-alarms.js
content/extensions/ext-backgroundPage.js
content/extensions/ext-browser-content.js
content/extensions/ext-contextualIdentities.js
content/extensions/ext-cookies.js
content/extensions/ext-downloads.js
+ content/extensions/ext-geolocation.js
content/extensions/ext-management.js
content/extensions/ext-notifications.js
content/extensions/ext-i18n.js
content/extensions/ext-idle.js
content/extensions/ext-webRequest.js
content/extensions/ext-webNavigation.js
content/extensions/ext-runtime.js
content/extensions/ext-extension.js
--- a/toolkit/components/extensions/schemas/manifest.json
+++ b/toolkit/components/extensions/schemas/manifest.json
@@ -207,16 +207,17 @@
{
"id": "Permission",
"choices": [
{
"type": "string",
"enum": [
"alarms",
"clipboardWrite",
+ "geolocation",
"idle",
"notifications",
"storage"
]
},
{ "$ref": "MatchPattern" }
]
},
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
@@ -35,16 +35,17 @@ support-files =
redirection.sjs
file_privilege_escalation.html
file_ext_test_api_injection.js
file_permission_xhr.html
file_teardown_test.js
return_headers.sjs
webrequest_worker.js
!/toolkit/components/passwordmgr/test/authenticate.sjs
+ !/dom/tests/mochitest/geolocation/network_geolocation.sjs
[test_clipboard.html]
# skip-if = # disabled test case with_permission_allow_copy, see inline comment.
[test_ext_inIncognitoContext_window.html]
skip-if = os == 'android' # Android does not support multiple windows.
[test_ext_geturl.html]
[test_ext_background_canvas.html]
[test_ext_content_security_policy.html]
@@ -59,16 +60,18 @@ skip-if = os == 'android' # Android does
skip-if = os == 'android' # Android does not support multiple windows.
[test_ext_contentscript_css.html]
[test_ext_contentscript_about_blank.html]
[test_ext_contentscript_permission.html]
[test_ext_contentscript_teardown.html]
[test_ext_exclude_include_globs.html]
[test_ext_i18n_css.html]
[test_ext_generate.html]
+[test_ext_geolocation.html]
+skip-if = os == 'android' # Android support Bug 1336194
[test_ext_notifications.html]
[test_ext_permission_xhr.html]
[test_ext_runtime_connect.html]
[test_ext_runtime_connect_twoway.html]
[test_ext_runtime_connect2.html]
[test_ext_runtime_disconnect.html]
[test_ext_runtime_id.html]
[test_ext_sandbox_var.html]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_geolocation.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML>
+
+<html>
+<head>
+<meta charset="utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <script type="text/javascript" src="head.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<script>
+"use strict";
+
+add_task(function* test_geolocation_nopermission() {
+ let GEO_URL = "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs";
+ yield SpecialPowers.pushPrefEnv({"set": [["geo.wifi.uri", GEO_URL]]});
+});
+
+add_task(function* test_geolocation() {
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ permissions: [
+ "geolocation",
+ ],
+ },
+ background() {
+ navigator.geolocation.getCurrentPosition(() => {
+ browser.test.notifyPass("success geolocation call");
+ }, (error) => {
+ browser.test.notifyFail(`geolocation call ${error}`);
+ });
+ },
+ });
+
+ yield extension.startup();
+ yield extension.awaitFinish();
+ yield extension.unload();
+});
+
+add_task(function* test_geolocation_nopermission() {
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ navigator.geolocation.getCurrentPosition(() => {
+ browser.test.notifyFail("success geolocation call");
+ }, (error) => {
+ browser.test.notifyPass(`geolocation call ${error}`);
+ });
+ },
+ });
+
+ yield extension.startup();
+ yield extension.awaitFinish();
+ yield extension.unload();
+});
+
+add_task(function* test_geolocation_prompt() {
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ browser.tabs.create({url: "tab.html"});
+ },
+ files: {
+ "tab.html": `<html><head>
+ <meta charset="utf-8">
+ <script src="tab.js"><\/script>
+ </head></html>`,
+ "tab.js": () => {
+ navigator.geolocation.getCurrentPosition(() => {
+ browser.test.notifyPass("success geolocation call");
+ }, (error) => {
+ browser.test.notifyFail(`geolocation call ${error}`);
+ });
+ },
+ },
+ });
+
+ // Bypass the actual prompt, but the prompt result is to allow access.
+ yield SpecialPowers.pushPrefEnv({"set": [["geo.prompt.testing", true], ["geo.prompt.testing.allow", true]]});
+ yield extension.startup();
+ yield extension.awaitFinish();
+ yield extension.unload();
+});
+</script>
+</head>
+<body>
+
+</body>
+</html>