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 michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Ci = Components.interfaces; michael@0: const Cr = Components.results; michael@0: const Cu = Components.utils; michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: const kCountBeforeWeRemember = 5; michael@0: michael@0: const kEntities = { michael@0: "geolocation": "geolocation2", michael@0: "indexedDB": "offlineApps", michael@0: "indexedDBQuota": "indexedDBQuota" michael@0: }; michael@0: michael@0: const kIcons = { michael@0: geolocation: "chrome://browser/skin/images/infobar-geolocation.png" michael@0: }; michael@0: michael@0: function ContentPermissionPrompt() {} michael@0: michael@0: ContentPermissionPrompt.prototype = { michael@0: classID: Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"), michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]), michael@0: michael@0: getChromeWindow: function getChromeWindow(aWindow) { michael@0: let chromeWin = aWindow.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: return chromeWin; michael@0: }, michael@0: michael@0: getChromeWindowForRequest: function getChromeWindowForRequest(aRequest) { michael@0: if (aRequest.window) michael@0: return this.getChromeWindow(aRequest.window.top).wrappedJSObject; michael@0: return aRequest.element.ownerDocument.defaultView; michael@0: }, michael@0: michael@0: getNotificationBoxForRequest: function getNotificationBoxForRequest(request) { michael@0: let chromeWin = this.getChromeWindowForRequest(request); michael@0: if (request.window) { michael@0: let requestingWindow = request.window.top; michael@0: let windowID = request.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; michael@0: let browser = chromeWin.Browser.getBrowserForWindowId(windowID); michael@0: return chromeWin.getNotificationBox(browser); michael@0: } michael@0: return chromeWin.Browser.getNotificationBox(request.element); michael@0: }, michael@0: michael@0: handleExistingPermission: function handleExistingPermission(request, type) { michael@0: let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type); michael@0: if (result == Ci.nsIPermissionManager.ALLOW_ACTION) { michael@0: request.allow(); michael@0: return true; michael@0: } michael@0: if (result == Ci.nsIPermissionManager.DENY_ACTION) { michael@0: request.cancel(); michael@0: return true; michael@0: } michael@0: return false; michael@0: }, michael@0: michael@0: prompt: function(request) { michael@0: // Only allow exactly one permission rquest 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: // returns true if the request was handled michael@0: if (this.handleExistingPermission(request, perm.type)) michael@0: return; michael@0: michael@0: let pm = Services.perms; michael@0: let notificationBox = this.getNotificationBoxForRequest(request); michael@0: let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); michael@0: michael@0: let notification = notificationBox.getNotificationWithValue(perm.type); michael@0: if (notification) michael@0: return; michael@0: michael@0: let entityName = kEntities[perm.type]; michael@0: let icon = kIcons[perm.type] || ""; michael@0: michael@0: let buttons = [{ michael@0: label: browserBundle.GetStringFromName(entityName + ".allow"), michael@0: accessKey: "", michael@0: callback: function(notification) { michael@0: request.allow(); michael@0: } michael@0: }, michael@0: { michael@0: label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"), michael@0: accessKey: "", michael@0: callback: function(notification) { michael@0: Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION); michael@0: request.allow(); michael@0: } michael@0: }, michael@0: { michael@0: label: browserBundle.GetStringFromName("contentPermissions.neverForSite"), michael@0: accessKey: "", michael@0: callback: function(notification) { michael@0: Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION); michael@0: request.cancel(); michael@0: } michael@0: }]; michael@0: michael@0: let message = browserBundle.formatStringFromName(entityName + ".wantsTo", michael@0: [request.principal.URI.host], 1); michael@0: let newBar = notificationBox.appendNotification(message, michael@0: perm.type, michael@0: icon, michael@0: notificationBox.PRIORITY_WARNING_MEDIUM, michael@0: buttons); michael@0: michael@0: if (perm.type == "geolocation") { michael@0: // Add the "learn more" link. michael@0: let link = newBar.ownerDocument.createElement("label"); michael@0: link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore")); michael@0: link.setAttribute("class", "text-link notification-link"); michael@0: newBar.insertBefore(link, newBar.firstChild); michael@0: michael@0: let win = this.getChromeWindowForRequest(request); michael@0: link.addEventListener("click", function() { michael@0: let url = Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL"); michael@0: win.BrowserUI.addAndShowTab(url, win.Browser.selectedTab); michael@0: }); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: michael@0: //module initialization michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);