|
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 |
|
9 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
10 Cu.import("resource://gre/modules/Services.jsm"); |
|
11 |
|
12 const kCountBeforeWeRemember = 5; |
|
13 |
|
14 const kEntities = { |
|
15 "geolocation": "geolocation2", |
|
16 "indexedDB": "offlineApps", |
|
17 "indexedDBQuota": "indexedDBQuota" |
|
18 }; |
|
19 |
|
20 const kIcons = { |
|
21 geolocation: "chrome://browser/skin/images/infobar-geolocation.png" |
|
22 }; |
|
23 |
|
24 function ContentPermissionPrompt() {} |
|
25 |
|
26 ContentPermissionPrompt.prototype = { |
|
27 classID: Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"), |
|
28 |
|
29 QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]), |
|
30 |
|
31 getChromeWindow: function getChromeWindow(aWindow) { |
|
32 let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) |
|
33 .getInterface(Ci.nsIWebNavigation) |
|
34 .QueryInterface(Ci.nsIDocShellTreeItem) |
|
35 .rootTreeItem |
|
36 .QueryInterface(Ci.nsIInterfaceRequestor) |
|
37 .getInterface(Ci.nsIDOMWindow) |
|
38 .QueryInterface(Ci.nsIDOMChromeWindow); |
|
39 return chromeWin; |
|
40 }, |
|
41 |
|
42 getChromeWindowForRequest: function getChromeWindowForRequest(aRequest) { |
|
43 if (aRequest.window) |
|
44 return this.getChromeWindow(aRequest.window.top).wrappedJSObject; |
|
45 return aRequest.element.ownerDocument.defaultView; |
|
46 }, |
|
47 |
|
48 getNotificationBoxForRequest: function getNotificationBoxForRequest(request) { |
|
49 let chromeWin = this.getChromeWindowForRequest(request); |
|
50 if (request.window) { |
|
51 let requestingWindow = request.window.top; |
|
52 let windowID = request.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; |
|
53 let browser = chromeWin.Browser.getBrowserForWindowId(windowID); |
|
54 return chromeWin.getNotificationBox(browser); |
|
55 } |
|
56 return chromeWin.Browser.getNotificationBox(request.element); |
|
57 }, |
|
58 |
|
59 handleExistingPermission: function handleExistingPermission(request, type) { |
|
60 let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type); |
|
61 if (result == Ci.nsIPermissionManager.ALLOW_ACTION) { |
|
62 request.allow(); |
|
63 return true; |
|
64 } |
|
65 if (result == Ci.nsIPermissionManager.DENY_ACTION) { |
|
66 request.cancel(); |
|
67 return true; |
|
68 } |
|
69 return false; |
|
70 }, |
|
71 |
|
72 prompt: function(request) { |
|
73 // Only allow exactly one permission rquest here. |
|
74 let types = request.types.QueryInterface(Ci.nsIArray); |
|
75 if (types.length != 1) { |
|
76 request.cancel(); |
|
77 return; |
|
78 } |
|
79 let perm = types.queryElementAt(0, Ci.nsIContentPermissionType); |
|
80 |
|
81 // returns true if the request was handled |
|
82 if (this.handleExistingPermission(request, perm.type)) |
|
83 return; |
|
84 |
|
85 let pm = Services.perms; |
|
86 let notificationBox = this.getNotificationBoxForRequest(request); |
|
87 let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); |
|
88 |
|
89 let notification = notificationBox.getNotificationWithValue(perm.type); |
|
90 if (notification) |
|
91 return; |
|
92 |
|
93 let entityName = kEntities[perm.type]; |
|
94 let icon = kIcons[perm.type] || ""; |
|
95 |
|
96 let buttons = [{ |
|
97 label: browserBundle.GetStringFromName(entityName + ".allow"), |
|
98 accessKey: "", |
|
99 callback: function(notification) { |
|
100 request.allow(); |
|
101 } |
|
102 }, |
|
103 { |
|
104 label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"), |
|
105 accessKey: "", |
|
106 callback: function(notification) { |
|
107 Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION); |
|
108 request.allow(); |
|
109 } |
|
110 }, |
|
111 { |
|
112 label: browserBundle.GetStringFromName("contentPermissions.neverForSite"), |
|
113 accessKey: "", |
|
114 callback: function(notification) { |
|
115 Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION); |
|
116 request.cancel(); |
|
117 } |
|
118 }]; |
|
119 |
|
120 let message = browserBundle.formatStringFromName(entityName + ".wantsTo", |
|
121 [request.principal.URI.host], 1); |
|
122 let newBar = notificationBox.appendNotification(message, |
|
123 perm.type, |
|
124 icon, |
|
125 notificationBox.PRIORITY_WARNING_MEDIUM, |
|
126 buttons); |
|
127 |
|
128 if (perm.type == "geolocation") { |
|
129 // Add the "learn more" link. |
|
130 let link = newBar.ownerDocument.createElement("label"); |
|
131 link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore")); |
|
132 link.setAttribute("class", "text-link notification-link"); |
|
133 newBar.insertBefore(link, newBar.firstChild); |
|
134 |
|
135 let win = this.getChromeWindowForRequest(request); |
|
136 link.addEventListener("click", function() { |
|
137 let url = Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL"); |
|
138 win.BrowserUI.addAndShowTab(url, win.Browser.selectedTab); |
|
139 }); |
|
140 } |
|
141 } |
|
142 }; |
|
143 |
|
144 |
|
145 //module initialization |
|
146 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]); |