|
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
7 |
|
8 var gPrivacyPane = { |
|
9 |
|
10 /** |
|
11 * Whether the use has selected the auto-start private browsing mode in the UI. |
|
12 */ |
|
13 _autoStartPrivateBrowsing: false, |
|
14 |
|
15 /** |
|
16 * Whether the prompt to restart Firefox should appear when changing the autostart pref. |
|
17 */ |
|
18 _shouldPromptForRestart: true, |
|
19 |
|
20 /** |
|
21 * Sets up the UI for the number of days of history to keep, and updates the |
|
22 * label of the "Clear Now..." button. |
|
23 */ |
|
24 init: function () |
|
25 { |
|
26 this._updateSanitizeSettingsButton(); |
|
27 this.initializeHistoryMode(); |
|
28 this.updateHistoryModePane(); |
|
29 this.updatePrivacyMicroControls(); |
|
30 this.initAutoStartPrivateBrowsingReverter(); |
|
31 }, |
|
32 |
|
33 // HISTORY MODE |
|
34 |
|
35 /** |
|
36 * The list of preferences which affect the initial history mode settings. |
|
37 * If the auto start private browsing mode pref is active, the initial |
|
38 * history mode would be set to "Don't remember anything". |
|
39 * If all of these preferences have their default values, and the auto-start |
|
40 * private browsing mode is not active, the initial history mode would be |
|
41 * set to "Remember everything". |
|
42 * Otherwise, the initial history mode would be set to "Custom". |
|
43 * |
|
44 * Extensions adding their own preferences can append their IDs to this array if needed. |
|
45 */ |
|
46 prefsForDefault: [ |
|
47 "places.history.enabled", |
|
48 "browser.formfill.enable", |
|
49 "network.cookie.cookieBehavior", |
|
50 "network.cookie.lifetimePolicy", |
|
51 "privacy.sanitize.sanitizeOnShutdown" |
|
52 ], |
|
53 |
|
54 /** |
|
55 * The list of control IDs which are dependent on the auto-start private |
|
56 * browsing setting, such that in "Custom" mode they would be disabled if |
|
57 * the auto-start private browsing checkbox is checked, and enabled otherwise. |
|
58 * |
|
59 * Extensions adding their own controls can append their IDs to this array if needed. |
|
60 */ |
|
61 dependentControls: [ |
|
62 "rememberHistory", |
|
63 "rememberForms", |
|
64 "keepUntil", |
|
65 "keepCookiesUntil", |
|
66 "alwaysClear", |
|
67 "clearDataSettings" |
|
68 ], |
|
69 |
|
70 /** |
|
71 * Check whether all the preferences values are set to their default values |
|
72 * |
|
73 * @param aPrefs an array of pref names to check for |
|
74 * @returns boolean true if all of the prefs are set to their default values, |
|
75 * false otherwise |
|
76 */ |
|
77 _checkDefaultValues: function(aPrefs) { |
|
78 for (let i = 0; i < aPrefs.length; ++i) { |
|
79 let pref = document.getElementById(aPrefs[i]); |
|
80 if (pref.value != pref.defaultValue) |
|
81 return false; |
|
82 } |
|
83 return true; |
|
84 }, |
|
85 |
|
86 /** |
|
87 * Initialize the history mode menulist based on the privacy preferences |
|
88 */ |
|
89 initializeHistoryMode: function PPP_initializeHistoryMode() |
|
90 { |
|
91 let mode; |
|
92 let getVal = function (aPref) |
|
93 document.getElementById(aPref).value; |
|
94 |
|
95 if (this._checkDefaultValues(this.prefsForDefault)) { |
|
96 if (getVal("browser.privatebrowsing.autostart")) |
|
97 mode = "dontremember"; |
|
98 else |
|
99 mode = "remember"; |
|
100 } |
|
101 else |
|
102 mode = "custom"; |
|
103 |
|
104 document.getElementById("historyMode").value = mode; |
|
105 }, |
|
106 |
|
107 /** |
|
108 * Update the selected pane based on the history mode menulist |
|
109 */ |
|
110 updateHistoryModePane: function PPP_updateHistoryModePane() |
|
111 { |
|
112 let selectedIndex = -1; |
|
113 switch (document.getElementById("historyMode").value) { |
|
114 case "remember": |
|
115 selectedIndex = 0; |
|
116 break; |
|
117 case "dontremember": |
|
118 selectedIndex = 1; |
|
119 break; |
|
120 case "custom": |
|
121 selectedIndex = 2; |
|
122 break; |
|
123 } |
|
124 document.getElementById("historyPane").selectedIndex = selectedIndex; |
|
125 }, |
|
126 |
|
127 /** |
|
128 * Update the Tracking preferences based on controls. |
|
129 */ |
|
130 setTrackingPrefs: function PPP_setTrackingPrefs() |
|
131 { |
|
132 let dntRadioGroup = document.getElementById("doNotTrackSelection"), |
|
133 dntValuePref = document.getElementById("privacy.donottrackheader.value"), |
|
134 dntEnabledPref = document.getElementById("privacy.donottrackheader.enabled"); |
|
135 |
|
136 // if the selected radio button says "no preference", set on/off pref to |
|
137 // false and don't change the value pref. |
|
138 if (dntRadioGroup.selectedItem.value == -1) { |
|
139 dntEnabledPref.value = false; |
|
140 return dntValuePref.value; |
|
141 } |
|
142 |
|
143 dntEnabledPref.value = true; |
|
144 return dntRadioGroup.selectedItem.value; |
|
145 }, |
|
146 |
|
147 /** |
|
148 * Obtain the tracking preference value and reflect it in the UI. |
|
149 */ |
|
150 getTrackingPrefs: function PPP_getTrackingPrefs() |
|
151 { |
|
152 let dntValuePref = document.getElementById("privacy.donottrackheader.value"), |
|
153 dntEnabledPref = document.getElementById("privacy.donottrackheader.enabled"); |
|
154 |
|
155 // if DNT is enbaled, select the value from the selected radio |
|
156 // button, otherwise choose the "no preference" radio button |
|
157 if (dntEnabledPref.value) |
|
158 return dntValuePref.value; |
|
159 |
|
160 return document.getElementById("dntnopref").value; |
|
161 }, |
|
162 |
|
163 /** |
|
164 * Update the private browsing auto-start pref and the history mode |
|
165 * micro-management prefs based on the history mode menulist |
|
166 */ |
|
167 updateHistoryModePrefs: function PPP_updateHistoryModePrefs() |
|
168 { |
|
169 let pref = document.getElementById("browser.privatebrowsing.autostart"); |
|
170 switch (document.getElementById("historyMode").value) { |
|
171 case "remember": |
|
172 if (pref.value) |
|
173 pref.value = false; |
|
174 |
|
175 // select the remember history option if needed |
|
176 let rememberHistoryCheckbox = document.getElementById("rememberHistory"); |
|
177 if (!rememberHistoryCheckbox.checked) |
|
178 rememberHistoryCheckbox.checked = true; |
|
179 |
|
180 // select the remember forms history option |
|
181 document.getElementById("browser.formfill.enable").value = true; |
|
182 |
|
183 #ifdef RELEASE_BUILD |
|
184 // select the accept cookies option |
|
185 document.getElementById("network.cookie.cookieBehavior").value = 0; |
|
186 #else |
|
187 // select the limit cookies option |
|
188 document.getElementById("network.cookie.cookieBehavior").value = 3; |
|
189 #endif |
|
190 // select the cookie lifetime policy option |
|
191 document.getElementById("network.cookie.lifetimePolicy").value = 0; |
|
192 |
|
193 // select the clear on close option |
|
194 document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false; |
|
195 break; |
|
196 case "dontremember": |
|
197 if (!pref.value) |
|
198 pref.value = true; |
|
199 break; |
|
200 } |
|
201 }, |
|
202 |
|
203 /** |
|
204 * Update the privacy micro-management controls based on the |
|
205 * value of the private browsing auto-start checkbox. |
|
206 */ |
|
207 updatePrivacyMicroControls: function PPP_updatePrivacyMicroControls() |
|
208 { |
|
209 if (document.getElementById("historyMode").value == "custom") { |
|
210 let disabled = this._autoStartPrivateBrowsing = |
|
211 document.getElementById("privateBrowsingAutoStart").checked; |
|
212 this.dependentControls |
|
213 .forEach(function (aElement) |
|
214 document.getElementById(aElement).disabled = disabled); |
|
215 |
|
216 // adjust the cookie controls status |
|
217 this.readAcceptCookies(); |
|
218 document.getElementById("keepCookiesUntil").value = disabled ? 2 : |
|
219 document.getElementById("network.cookie.lifetimePolicy").value; |
|
220 |
|
221 // adjust the checked state of the sanitizeOnShutdown checkbox |
|
222 document.getElementById("alwaysClear").checked = disabled ? false : |
|
223 document.getElementById("privacy.sanitize.sanitizeOnShutdown").value; |
|
224 |
|
225 // adjust the checked state of the remember history checkboxes |
|
226 document.getElementById("rememberHistory").checked = disabled ? false : |
|
227 document.getElementById("places.history.enabled").value; |
|
228 document.getElementById("rememberForms").checked = disabled ? false : |
|
229 document.getElementById("browser.formfill.enable").value; |
|
230 |
|
231 if (!disabled) { |
|
232 // adjust the Settings button for sanitizeOnShutdown |
|
233 this._updateSanitizeSettingsButton(); |
|
234 } |
|
235 } |
|
236 }, |
|
237 |
|
238 // PRIVATE BROWSING |
|
239 |
|
240 /** |
|
241 * Initialize the starting state for the auto-start private browsing mode pref reverter. |
|
242 */ |
|
243 initAutoStartPrivateBrowsingReverter: function PPP_initAutoStartPrivateBrowsingReverter() |
|
244 { |
|
245 let mode = document.getElementById("historyMode"); |
|
246 let autoStart = document.getElementById("privateBrowsingAutoStart"); |
|
247 this._lastMode = mode.selectedIndex; |
|
248 this._lastCheckState = autoStart.hasAttribute('checked'); |
|
249 }, |
|
250 |
|
251 _lastMode: null, |
|
252 _lastCheckState: null, |
|
253 updateAutostart: function PPP_updateAutostart() { |
|
254 let mode = document.getElementById("historyMode"); |
|
255 let autoStart = document.getElementById("privateBrowsingAutoStart"); |
|
256 let pref = document.getElementById("browser.privatebrowsing.autostart"); |
|
257 if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) || |
|
258 (mode.value == "remember" && !this._lastCheckState) || |
|
259 (mode.value == "dontremember" && this._lastCheckState)) { |
|
260 // These are all no-op changes, so we don't need to prompt. |
|
261 this._lastMode = mode.selectedIndex; |
|
262 this._lastCheckState = autoStart.hasAttribute('checked'); |
|
263 return; |
|
264 } |
|
265 |
|
266 if (!this._shouldPromptForRestart) { |
|
267 // We're performing a revert. Just let it happen. |
|
268 return; |
|
269 } |
|
270 |
|
271 const Cc = Components.classes, Ci = Components.interfaces; |
|
272 let brandName = document.getElementById("bundleBrand").getString("brandShortName"); |
|
273 let bundle = document.getElementById("bundlePreferences"); |
|
274 let msg = bundle.getFormattedString(autoStart.checked ? |
|
275 "featureEnableRequiresRestart" : "featureDisableRequiresRestart", |
|
276 [brandName]); |
|
277 let title = bundle.getFormattedString("shouldRestartTitle", [brandName]); |
|
278 let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService); |
|
279 let shouldProceed = prompts.confirm(window, title, msg) |
|
280 if (shouldProceed) { |
|
281 let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"] |
|
282 .createInstance(Ci.nsISupportsPRBool); |
|
283 Services.obs.notifyObservers(cancelQuit, "quit-application-requested", |
|
284 "restart"); |
|
285 shouldProceed = !cancelQuit.data; |
|
286 |
|
287 if (shouldProceed) { |
|
288 pref.value = autoStart.hasAttribute('checked'); |
|
289 document.documentElement.acceptDialog(); |
|
290 let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"] |
|
291 .getService(Ci.nsIAppStartup); |
|
292 appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); |
|
293 return; |
|
294 } |
|
295 } |
|
296 |
|
297 this._shouldPromptForRestart = false; |
|
298 |
|
299 if (this._lastCheckState) { |
|
300 autoStart.checked = "checked"; |
|
301 } else { |
|
302 autoStart.removeAttribute('checked'); |
|
303 } |
|
304 pref.value = autoStart.hasAttribute('checked'); |
|
305 mode.selectedIndex = this._lastMode; |
|
306 mode.doCommand(); |
|
307 |
|
308 this._shouldPromptForRestart = true; |
|
309 }, |
|
310 |
|
311 // HISTORY |
|
312 |
|
313 /** |
|
314 * Read the location bar enabled and suggestion prefs |
|
315 * @return Int value for suggestion menulist |
|
316 */ |
|
317 readSuggestionPref: function PPP_readSuggestionPref() |
|
318 { |
|
319 let getVal = function(aPref) |
|
320 document.getElementById("browser.urlbar." + aPref).value; |
|
321 |
|
322 // Suggest nothing if autocomplete is not enabled |
|
323 if (!getVal("autocomplete.enabled")) |
|
324 return -1; |
|
325 |
|
326 // Bottom 2 bits of default.behavior specify history/bookmark |
|
327 return getVal("default.behavior") & 3; |
|
328 }, |
|
329 |
|
330 /** |
|
331 * Write the location bar enabled and suggestion prefs when necessary |
|
332 * @return Bool value for enabled pref |
|
333 */ |
|
334 writeSuggestionPref: function PPP_writeSuggestionPref() |
|
335 { |
|
336 let menuVal = document.getElementById("locationBarSuggestion").value; |
|
337 let enabled = menuVal != -1; |
|
338 |
|
339 // Only update default.behavior if we're giving suggestions |
|
340 if (enabled) { |
|
341 // Put the selected menu item's value directly into the bottom 2 bits |
|
342 let behavior = document.getElementById("browser.urlbar.default.behavior"); |
|
343 behavior.value = behavior.value >> 2 << 2 | menuVal; |
|
344 } |
|
345 |
|
346 // Always update the enabled pref |
|
347 return enabled; |
|
348 }, |
|
349 |
|
350 /* |
|
351 * Preferences: |
|
352 * |
|
353 * places.history.enabled |
|
354 * - whether history is enabled or not |
|
355 * browser.formfill.enable |
|
356 * - true if entries in forms and the search bar should be saved, false |
|
357 * otherwise |
|
358 */ |
|
359 |
|
360 // COOKIES |
|
361 |
|
362 /* |
|
363 * Preferences: |
|
364 * |
|
365 * network.cookie.cookieBehavior |
|
366 * - determines how the browser should handle cookies: |
|
367 * 0 means enable all cookies |
|
368 * 1 means reject all third party cookies |
|
369 * 2 means disable all cookies |
|
370 * 3 means reject third party cookies unless at least one is already set for the eTLD |
|
371 * see netwerk/cookie/src/nsCookieService.cpp for details |
|
372 * network.cookie.lifetimePolicy |
|
373 * - determines how long cookies are stored: |
|
374 * 0 means keep cookies until they expire |
|
375 * 1 means ask how long to keep each cookie |
|
376 * 2 means keep cookies until the browser is closed |
|
377 */ |
|
378 |
|
379 /** |
|
380 * Reads the network.cookie.cookieBehavior preference value and |
|
381 * enables/disables the rest of the cookie UI accordingly, returning true |
|
382 * if cookies are enabled. |
|
383 */ |
|
384 readAcceptCookies: function () |
|
385 { |
|
386 var pref = document.getElementById("network.cookie.cookieBehavior"); |
|
387 var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel"); |
|
388 var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu"); |
|
389 var keepUntil = document.getElementById("keepUntil"); |
|
390 var menu = document.getElementById("keepCookiesUntil"); |
|
391 |
|
392 // enable the rest of the UI for anything other than "disable all cookies" |
|
393 var acceptCookies = (pref.value != 2); |
|
394 |
|
395 acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies; |
|
396 keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies; |
|
397 |
|
398 return acceptCookies; |
|
399 }, |
|
400 |
|
401 /** |
|
402 * Enables/disables the "keep until" label and menulist in response to the |
|
403 * "accept cookies" checkbox being checked or unchecked. |
|
404 */ |
|
405 writeAcceptCookies: function () |
|
406 { |
|
407 var accept = document.getElementById("acceptCookies"); |
|
408 var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu"); |
|
409 |
|
410 #ifdef RELEASE_BUILD |
|
411 // if we're enabling cookies, automatically select 'accept third party always' |
|
412 if (accept.checked) |
|
413 acceptThirdPartyMenu.selectedIndex = 0; |
|
414 |
|
415 return accept.checked ? 0 : 2; |
|
416 #else |
|
417 // if we're enabling cookies, automatically select 'accept third party from visited' |
|
418 if (accept.checked) |
|
419 acceptThirdPartyMenu.selectedIndex = 1; |
|
420 |
|
421 return accept.checked ? 3 : 2; |
|
422 #endif |
|
423 }, |
|
424 |
|
425 /** |
|
426 * Converts between network.cookie.cookieBehavior and the third-party cookie UI |
|
427 */ |
|
428 readAcceptThirdPartyCookies: function () |
|
429 { |
|
430 var pref = document.getElementById("network.cookie.cookieBehavior"); |
|
431 switch (pref.value) |
|
432 { |
|
433 case 0: |
|
434 return "always"; |
|
435 case 1: |
|
436 return "never"; |
|
437 case 2: |
|
438 return "never"; |
|
439 case 3: |
|
440 return "visited"; |
|
441 default: |
|
442 return undefined; |
|
443 } |
|
444 }, |
|
445 |
|
446 writeAcceptThirdPartyCookies: function () |
|
447 { |
|
448 var accept = document.getElementById("acceptThirdPartyMenu").selectedItem; |
|
449 switch (accept.value) |
|
450 { |
|
451 case "always": |
|
452 return 0; |
|
453 case "visited": |
|
454 return 3; |
|
455 case "never": |
|
456 return 1; |
|
457 default: |
|
458 return undefined; |
|
459 } |
|
460 }, |
|
461 |
|
462 /** |
|
463 * Displays fine-grained, per-site preferences for cookies. |
|
464 */ |
|
465 showCookieExceptions: function () |
|
466 { |
|
467 var bundlePreferences = document.getElementById("bundlePreferences"); |
|
468 var params = { blockVisible : true, |
|
469 sessionVisible : true, |
|
470 allowVisible : true, |
|
471 prefilledHost : "", |
|
472 permissionType : "cookie", |
|
473 windowTitle : bundlePreferences.getString("cookiepermissionstitle"), |
|
474 introText : bundlePreferences.getString("cookiepermissionstext") }; |
|
475 document.documentElement.openWindow("Browser:Permissions", |
|
476 "chrome://browser/content/preferences/permissions.xul", |
|
477 "", params); |
|
478 }, |
|
479 |
|
480 /** |
|
481 * Displays all the user's cookies in a dialog. |
|
482 */ |
|
483 showCookies: function (aCategory) |
|
484 { |
|
485 document.documentElement.openWindow("Browser:Cookies", |
|
486 "chrome://browser/content/preferences/cookies.xul", |
|
487 "", null); |
|
488 }, |
|
489 |
|
490 // CLEAR PRIVATE DATA |
|
491 |
|
492 /* |
|
493 * Preferences: |
|
494 * |
|
495 * privacy.sanitize.sanitizeOnShutdown |
|
496 * - true if the user's private data is cleared on startup according to the |
|
497 * Clear Private Data settings, false otherwise |
|
498 */ |
|
499 |
|
500 /** |
|
501 * Displays the Clear Private Data settings dialog. |
|
502 */ |
|
503 showClearPrivateDataSettings: function () |
|
504 { |
|
505 document.documentElement.openSubDialog("chrome://browser/content/preferences/sanitize.xul", |
|
506 "", null); |
|
507 }, |
|
508 |
|
509 |
|
510 /** |
|
511 * Displays a dialog from which individual parts of private data may be |
|
512 * cleared. |
|
513 */ |
|
514 clearPrivateDataNow: function (aClearEverything) |
|
515 { |
|
516 var ts = document.getElementById("privacy.sanitize.timeSpan"); |
|
517 var timeSpanOrig = ts.value; |
|
518 if (aClearEverything) |
|
519 ts.value = 0; |
|
520 |
|
521 const Cc = Components.classes, Ci = Components.interfaces; |
|
522 var glue = Cc["@mozilla.org/browser/browserglue;1"] |
|
523 .getService(Ci.nsIBrowserGlue); |
|
524 glue.sanitize(window); |
|
525 |
|
526 // reset the timeSpan pref |
|
527 if (aClearEverything) |
|
528 ts.value = timeSpanOrig; |
|
529 }, |
|
530 |
|
531 /** |
|
532 * Enables or disables the "Settings..." button depending |
|
533 * on the privacy.sanitize.sanitizeOnShutdown preference value |
|
534 */ |
|
535 _updateSanitizeSettingsButton: function () { |
|
536 var settingsButton = document.getElementById("clearDataSettings"); |
|
537 var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown"); |
|
538 |
|
539 settingsButton.disabled = !sanitizeOnShutdownPref.value; |
|
540 } |
|
541 |
|
542 }; |