|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 const Ci = Components.interfaces; |
|
6 const Cr = Components.results; |
|
7 const Cu = Components.utils; |
|
8 const Cc = Components.classes; |
|
9 |
|
10 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
11 Cu.import("resource://gre/modules/Services.jsm"); |
|
12 |
|
13 const kEntities = { "geolocation": "geolocation", |
|
14 "desktop-notification": "desktopNotification", |
|
15 "contacts": "contacts" }; |
|
16 |
|
17 function ContentPermissionPrompt() {} |
|
18 |
|
19 ContentPermissionPrompt.prototype = { |
|
20 classID: Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"), |
|
21 |
|
22 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]), |
|
23 |
|
24 handleExistingPermission: function handleExistingPermission(request, type, isApp) { |
|
25 let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type); |
|
26 if (result == Ci.nsIPermissionManager.ALLOW_ACTION) { |
|
27 request.allow(); |
|
28 return true; |
|
29 } |
|
30 if (result == Ci.nsIPermissionManager.DENY_ACTION) { |
|
31 request.cancel(); |
|
32 return true; |
|
33 } |
|
34 |
|
35 if (isApp && (result == Ci.nsIPermissionManager.UNKNOWN_ACTION && !!kEntities[type])) { |
|
36 request.cancel(); |
|
37 return true; |
|
38 } |
|
39 |
|
40 return false; |
|
41 }, |
|
42 |
|
43 getChromeWindow: function getChromeWindow(aWindow) { |
|
44 let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) |
|
45 .getInterface(Ci.nsIWebNavigation) |
|
46 .QueryInterface(Ci.nsIDocShellTreeItem) |
|
47 .rootTreeItem |
|
48 .QueryInterface(Ci.nsIInterfaceRequestor) |
|
49 .getInterface(Ci.nsIDOMWindow) |
|
50 .QueryInterface(Ci.nsIDOMChromeWindow); |
|
51 return chromeWin; |
|
52 }, |
|
53 |
|
54 getChromeForRequest: function getChromeForRequest(request) { |
|
55 if (request.window) { |
|
56 let requestingWindow = request.window.top; |
|
57 return this.getChromeWindow(requestingWindow).wrappedJSObject; |
|
58 } |
|
59 return request.element.ownerDocument.defaultView; |
|
60 }, |
|
61 |
|
62 prompt: function(request) { |
|
63 let isApp = request.principal.appId !== Ci.nsIScriptSecurityManager.NO_APP_ID && request.principal.appId !== Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID; |
|
64 |
|
65 // Only allow exactly one permission rquest here. |
|
66 let types = request.types.QueryInterface(Ci.nsIArray); |
|
67 if (types.length != 1) { |
|
68 request.cancel(); |
|
69 return; |
|
70 } |
|
71 let perm = types.queryElementAt(0, Ci.nsIContentPermissionType); |
|
72 |
|
73 // Returns true if the request was handled |
|
74 if (this.handleExistingPermission(request, perm.type, isApp)) |
|
75 return; |
|
76 |
|
77 let chromeWin = this.getChromeForRequest(request); |
|
78 let tab = chromeWin.BrowserApp.getTabForWindow(request.window.top); |
|
79 if (!tab) |
|
80 return; |
|
81 |
|
82 let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); |
|
83 let entityName = kEntities[perm.type]; |
|
84 |
|
85 let buttons = [{ |
|
86 label: browserBundle.GetStringFromName(entityName + ".allow"), |
|
87 callback: function(aChecked) { |
|
88 // If the user checked "Don't ask again", make a permanent exception |
|
89 if (aChecked) { |
|
90 Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION); |
|
91 } else if (isApp || entityName == "desktopNotification") { |
|
92 // Otherwise allow the permission for the current session (if the request comes from an app or if it's a desktop-notification request) |
|
93 Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION); |
|
94 } |
|
95 |
|
96 request.allow(); |
|
97 } |
|
98 }, |
|
99 { |
|
100 label: browserBundle.GetStringFromName(entityName + ".dontAllow"), |
|
101 callback: function(aChecked) { |
|
102 // If the user checked "Don't ask again", make a permanent exception |
|
103 if (aChecked) |
|
104 Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION); |
|
105 |
|
106 request.cancel(); |
|
107 } |
|
108 }]; |
|
109 |
|
110 let requestor = chromeWin.BrowserApp.manifest ? "'" + chromeWin.BrowserApp.manifest.name + "'" : request.principal.URI.host; |
|
111 let message = browserBundle.formatStringFromName(entityName + ".ask", [requestor], 1); |
|
112 let options = { checkbox: browserBundle.GetStringFromName(entityName + ".dontAskAgain") }; |
|
113 |
|
114 chromeWin.NativeWindow.doorhanger.show(message, entityName + request.principal.URI.host, buttons, tab.id, options); |
|
115 } |
|
116 }; |
|
117 |
|
118 |
|
119 //module initialization |
|
120 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]); |