michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: michael@0: const UNKNOWN_FAIL = ["geolocation", "desktop-notification"]; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://webapprt/modules/WebappRT.jsm"); michael@0: michael@0: function ContentPermission() {} michael@0: michael@0: ContentPermission.prototype = { michael@0: classID: Components.ID("{07ef5b2e-88fb-47bd-8cec-d3b0bef11ac4}"), michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]), michael@0: michael@0: _getChromeWindow: function(aWindow) { michael@0: return aWindow michael@0: .QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIWebNavigation) michael@0: .QueryInterface(Ci.nsIDocShellTreeItem) michael@0: .rootTreeItem michael@0: .QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIDOMWindow) michael@0: .QueryInterface(Ci.nsIDOMChromeWindow); michael@0: }, michael@0: michael@0: prompt: function(request) { michael@0: // Only allow exactly one permission request here. michael@0: let types = request.types.QueryInterface(Ci.nsIArray); michael@0: if (types.length != 1) { michael@0: request.cancel(); michael@0: return; michael@0: } michael@0: let perm = types.queryElementAt(0, Ci.nsIContentPermissionType); michael@0: michael@0: // Reuse any remembered permission preferences michael@0: let result = michael@0: Services.perms.testExactPermissionFromPrincipal(request.principal, michael@0: perm.type); michael@0: michael@0: // We used to use the name "geo" for the geolocation permission, now we're michael@0: // using "geolocation". We need to check both to support existing michael@0: // installations. michael@0: if ((result == Ci.nsIPermissionManager.UNKNOWN_ACTION || michael@0: result == Ci.nsIPermissionManager.PROMPT_ACTION) && michael@0: perm.type == "geolocation") { michael@0: let geoResult = Services.perms.testExactPermission(request.principal.URI, michael@0: "geo"); michael@0: // We override the result only if the "geo" permission was allowed or michael@0: // denied. michael@0: if (geoResult == Ci.nsIPermissionManager.ALLOW_ACTION || michael@0: geoResult == Ci.nsIPermissionManager.DENY_ACTION) { michael@0: result = geoResult; michael@0: } michael@0: } michael@0: michael@0: if (result == Ci.nsIPermissionManager.ALLOW_ACTION) { michael@0: request.allow(); michael@0: return; michael@0: } else if (result == Ci.nsIPermissionManager.DENY_ACTION || michael@0: (result == Ci.nsIPermissionManager.UNKNOWN_ACTION && michael@0: UNKNOWN_FAIL.indexOf(perm.type) >= 0)) { michael@0: request.cancel(); michael@0: return; michael@0: } michael@0: michael@0: // Display a prompt at the top level michael@0: let {name} = WebappRT.localeManifest; michael@0: let requestingWindow = request.window.top; michael@0: let chromeWin = this._getChromeWindow(requestingWindow); michael@0: let bundle = Services.strings.createBundle("chrome://webapprt/locale/webapp.properties"); michael@0: michael@0: // Construct a prompt with share/don't and remember checkbox michael@0: let remember = {value: false}; michael@0: let choice = Services.prompt.confirmEx( michael@0: chromeWin, michael@0: bundle.formatStringFromName(perm.type + ".title", [name], 1), michael@0: bundle.GetStringFromName(perm.type + ".description"), michael@0: // Set both buttons to strings with the cancel button being default michael@0: Ci.nsIPromptService.BUTTON_POS_1_DEFAULT | michael@0: Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0 | michael@0: Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_1, michael@0: bundle.GetStringFromName(perm.type + ".allow"), michael@0: bundle.GetStringFromName(perm.type + ".deny"), michael@0: null, michael@0: bundle.GetStringFromName(perm.type + ".remember"), michael@0: remember); michael@0: michael@0: let action = Ci.nsIPermissionManager.ALLOW_ACTION; michael@0: if (choice != 0) { michael@0: action = Ci.nsIPermissionManager.DENY_ACTION; michael@0: } michael@0: michael@0: if (remember.value) { michael@0: // Persist the choice if the user wants to remember michael@0: Services.perms.addFromPrincipal(request.principal, perm.type, action); michael@0: } else { michael@0: // Otherwise allow the permission for the current session michael@0: Services.perms.addFromPrincipal(request.principal, perm.type, action, michael@0: Ci.nsIPermissionManager.EXPIRE_SESSION); michael@0: } michael@0: michael@0: // Trigger the selected choice michael@0: if (choice == 0) { michael@0: request.allow(); michael@0: } michael@0: else { michael@0: request.cancel(); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermission]);