Bug 1031527 - Remove dup fd from ParamTraits<MagicGrallocBufferHandle>::Read(). r...
[gecko.git] / browser / components / preferences / advanced.js
blob100d8cd8b20f2f6eb95f66e8b8be6fc639821746
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/.
6 // Load DownloadUtils module for convertByteUnits
7 Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
8 Components.utils.import("resource://gre/modules/ctypes.jsm");
9 Components.utils.import("resource://gre/modules/Services.jsm");
10 Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
11 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
13 var gAdvancedPane = {
14   _inited: false,
16   /**
17    * Brings the appropriate tab to the front and initializes various bits of UI.
18    */
19   init: function ()
20   {
21     this._inited = true;
22     var advancedPrefs = document.getElementById("advancedPrefs");
24     var extraArgs = window.arguments[1];
25     if (extraArgs && extraArgs["advancedTab"]){
26       advancedPrefs.selectedTab = document.getElementById(extraArgs["advancedTab"]);
27     } else {
28       var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
29       if (preference.value !== null)
30         advancedPrefs.selectedIndex = preference.value;
31     }
33 #ifdef HAVE_SHELL_SERVICE
34     this.updateSetDefaultBrowser();
35 #ifdef XP_WIN
36     // In Windows 8 we launch the control panel since it's the only
37     // way to get all file type association prefs. So we don't know
38     // when the user will select the default.  We refresh here periodically
39     // in case the default changes.  On other Windows OS's defaults can also
40     // be set while the prefs are open.
41     window.setInterval(this.updateSetDefaultBrowser, 1000);
43 #ifdef MOZ_METRO
44     // Pre Windows 8, we should hide the update related settings
45     // for the Metro browser
46     let version = Components.classes["@mozilla.org/system-info;1"].
47                   getService(Components.interfaces.nsIPropertyBag2).
48                   getProperty("version");
49     let preWin8 = parseFloat(version) < 6.2;
50     this._showingWin8Prefs = !preWin8;
51     if (preWin8) {
52       ["autoMetro", "autoMetroIndent"].forEach(
53         function(id) document.getElementById(id).collapsed = true
54       );
55     } else {
56       let brandShortName =
57         document.getElementById("bundleBrand").getString("brandShortName");
58       let bundlePrefs = document.getElementById("bundlePreferences");
59       let autoDesktop = document.getElementById("autoDesktop");
60       autoDesktop.label =
61         bundlePrefs.getFormattedString("updateAutoDesktop.label",
62                                        [brandShortName]);
63       autoDesktop.accessKey =
64         bundlePrefs.getString("updateAutoDesktop.accessKey");
65     }
66 #endif
67 #endif
68 #endif
70 #ifdef MOZ_UPDATER
71     this.updateReadPrefs();
72 #endif
73     this.updateOfflineApps();
74 #ifdef MOZ_CRASHREPORTER
75     this.initSubmitCrashes();
76 #endif
77     this.initTelemetry();
78 #ifdef MOZ_SERVICES_HEALTHREPORT
79     this.initSubmitHealthReport();
80 #endif
82     this.updateActualCacheSize();
83     this.updateActualAppCacheSize();
85     // Notify observers that the UI is now ready
86     Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
87   },
89   /**
90    * Stores the identity of the current tab in preferences so that the selected
91    * tab can be persisted between openings of the preferences window.
92    */
93   tabSelectionChanged: function ()
94   {
95     if (!this._inited)
96       return;
97     var advancedPrefs = document.getElementById("advancedPrefs");
98     var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
99     preference.valueFromPreferences = advancedPrefs.selectedIndex;
100   },
102   // GENERAL TAB
104   /*
105    * Preferences:
106    *
107    * accessibility.browsewithcaret
108    * - true enables keyboard navigation and selection within web pages using a
109    *   visible caret, false uses normal keyboard navigation with no caret
110    * accessibility.typeaheadfind
111    * - when set to true, typing outside text areas and input boxes will
112    *   automatically start searching for what's typed within the current
113    *   document; when set to false, no search action happens
114    * general.autoScroll
115    * - when set to true, clicking the scroll wheel on the mouse activates a
116    *   mouse mode where moving the mouse down scrolls the document downward with
117    *   speed correlated with the distance of the cursor from the original
118    *   position at which the click occurred (and likewise with movement upward);
119    *   if false, this behavior is disabled
120    * general.smoothScroll
121    * - set to true to enable finer page scrolling than line-by-line on page-up,
122    *   page-down, and other such page movements
123    * layout.spellcheckDefault
124    * - an integer:
125    *     0  disables spellchecking
126    *     1  enables spellchecking, but only for multiline text fields
127    *     2  enables spellchecking for all text fields
128    */
130   /**
131    * Stores the original value of the spellchecking preference to enable proper
132    * restoration if unchanged (since we're mapping a tristate onto a checkbox).
133    */
134   _storedSpellCheck: 0,
136   /**
137    * Returns true if any spellchecking is enabled and false otherwise, caching
138    * the current value to enable proper pref restoration if the checkbox is
139    * never changed.
140    */
141   readCheckSpelling: function ()
142   {
143     var pref = document.getElementById("layout.spellcheckDefault");
144     this._storedSpellCheck = pref.value;
146     return (pref.value != 0);
147   },
149   /**
150    * Returns the value of the spellchecking preference represented by UI,
151    * preserving the preference's "hidden" value if the preference is
152    * unchanged and represents a value not strictly allowed in UI.
153    */
154   writeCheckSpelling: function ()
155   {
156     var checkbox = document.getElementById("checkSpelling");
157     return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0;
158   },
160   /**
161    * When the user toggles the layers.acceleration.disabled pref,
162    * sync its new value to the gfx.direct2d.disabled pref too.
163    */
164   updateHardwareAcceleration: function()
165   {
166 #ifdef XP_WIN
167     var fromPref = document.getElementById("layers.acceleration.disabled");
168     var toPref = document.getElementById("gfx.direct2d.disabled");
169     toPref.value = fromPref.value;
170 #endif
171   },
173   // DATA CHOICES TAB
175   /**
176    * opening links behind a modal dialog is poor form. Work around flawed text-link handling here.
177    */
178   openTextLink: function (evt) {
179     let where = Services.prefs.getBoolPref("browser.preferences.instantApply") ? "tab" : "window";
180     openUILinkIn(evt.target.getAttribute("href"), where);
181     evt.preventDefault();
182   },
184   /**
185    * Set up or hide the Learn More links for various data collection options
186    */
187   _setupLearnMoreLink: function (pref, element) {
188     // set up the Learn More link with the correct URL
189     let url = Services.prefs.getCharPref(pref);
190     let el = document.getElementById(element);
192     if (url) {
193       el.setAttribute("href", url);
194     } else {
195       el.setAttribute("hidden", "true");
196     }
197   },
199   /**
200    *
201    */
202   initSubmitCrashes: function ()
203   {
204     var checkbox = document.getElementById("submitCrashesBox");
205     try {
206       var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
207                getService(Components.interfaces.nsICrashReporter);
208       checkbox.checked = cr.submitReports;
209     } catch (e) {
210       checkbox.style.display = "none";
211     }
212     this._setupLearnMoreLink("toolkit.crashreporter.infoURL", "crashReporterLearnMore");
213   },
215   /**
216    *
217    */
218   updateSubmitCrashes: function ()
219   {
220     var checkbox = document.getElementById("submitCrashesBox");
221     try {
222       var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
223                getService(Components.interfaces.nsICrashReporter);
224       cr.submitReports = checkbox.checked;
225     } catch (e) { }
226   },
229   /**
230    * The preference/checkbox is configured in XUL.
231    *
232    * In all cases, set up the Learn More link sanely
233    */
234   initTelemetry: function ()
235   {
236 #ifdef MOZ_TELEMETRY_REPORTING
237     this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
238 #endif
239   },
241 #ifdef MOZ_SERVICES_HEALTHREPORT
242   /**
243    * Initialize the health report service reference and checkbox.
244    */
245   initSubmitHealthReport: function () {
246     this._setupLearnMoreLink("datareporting.healthreport.infoURL", "FHRLearnMore");
248     let policy = Components.classes["@mozilla.org/datareporting/service;1"]
249                                    .getService(Components.interfaces.nsISupports)
250                                    .wrappedJSObject
251                                    .policy;
253     let checkbox = document.getElementById("submitHealthReportBox");
255     if (!policy || policy.healthReportUploadLocked) {
256       checkbox.setAttribute("disabled", "true");
257       return;
258     }
260     checkbox.checked = policy.healthReportUploadEnabled;
261   },
263   /**
264    * Update the health report policy acceptance with state from checkbox.
265    */
266   updateSubmitHealthReport: function () {
267     let policy = Components.classes["@mozilla.org/datareporting/service;1"]
268                                    .getService(Components.interfaces.nsISupports)
269                                    .wrappedJSObject
270                                    .policy;
272     if (!policy) {
273       return;
274     }
276     let checkbox = document.getElementById("submitHealthReportBox");
277     policy.recordHealthReportUploadEnabled(checkbox.checked,
278                                            "Checkbox from preferences pane");
279   },
280 #endif
282   // NETWORK TAB
284   /*
285    * Preferences:
286    *
287    * browser.cache.disk.capacity
288    * - the size of the browser cache in KB
289    * - Only used if browser.cache.disk.smart_size.enabled is disabled
290    */
292   /**
293    * Displays a dialog in which proxy settings may be changed.
294    */
295   showConnections: function ()
296   {
297     document.documentElement.openSubDialog("chrome://browser/content/preferences/connection.xul",
298                                            "", null);
299   },
301   // Retrieves the amount of space currently used by disk cache
302   updateActualCacheSize: function ()
303   {
304     var actualSizeLabel = document.getElementById("actualDiskCacheSize");
305     var prefStrBundle = document.getElementById("bundlePreferences");
307     // Needs to root the observer since cache service keeps only a weak reference.
308     this.observer = {
309       onNetworkCacheDiskConsumption: function(consumption) {
310         var size = DownloadUtils.convertByteUnits(consumption);
311         actualSizeLabel.value = prefStrBundle.getFormattedString("actualDiskCacheSize", size);
312       },
314       QueryInterface: XPCOMUtils.generateQI([
315         Components.interfaces.nsICacheStorageConsumptionObserver,
316         Components.interfaces.nsISupportsWeakReference
317       ])
318     };
320     actualSizeLabel.value = prefStrBundle.getString("actualDiskCacheSizeCalculated");
322     var cacheService =
323       Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
324                 .getService(Components.interfaces.nsICacheStorageService);
325     cacheService.asyncGetDiskConsumption(this.observer);
326   },
328   // Retrieves the amount of space currently used by offline cache
329   updateActualAppCacheSize: function ()
330   {
331     var visitor = {
332       onCacheStorageInfo: function (aEntryCount, aConsumption, aCapacity, aDiskDirectory)
333       {
334         var actualSizeLabel = document.getElementById("actualAppCacheSize");
335         var sizeStrings = DownloadUtils.convertByteUnits(aConsumption);
336         var prefStrBundle = document.getElementById("bundlePreferences");
337         var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
338         actualSizeLabel.value = sizeStr;
339       }
340     };
342     var cacheService =
343       Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
344                 .getService(Components.interfaces.nsICacheStorageService);
345     var storage = cacheService.appCacheStorage(LoadContextInfo.default, null);
346     storage.asyncVisitStorage(visitor, false);
347   },
349   updateCacheSizeUI: function (smartSizeEnabled)
350   {
351     document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
352     document.getElementById("cacheSize").disabled = smartSizeEnabled;
353     document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
354   },
356   readSmartSizeEnabled: function ()
357   {
358     // The smart_size.enabled preference element is inverted="true", so its
359     // value is the opposite of the actual pref value
360     var disabled = document.getElementById("browser.cache.disk.smart_size.enabled").value;
361     this.updateCacheSizeUI(!disabled);
362   },
364   /**
365    * Converts the cache size from units of KB to units of MB and returns that
366    * value.
367    */
368   readCacheSize: function ()
369   {
370     var preference = document.getElementById("browser.cache.disk.capacity");
371     return preference.value / 1024;
372   },
374   /**
375    * Converts the cache size as specified in UI (in MB) to KB and returns that
376    * value.
377    */
378   writeCacheSize: function ()
379   {
380     var cacheSize = document.getElementById("cacheSize");
381     var intValue = parseInt(cacheSize.value, 10);
382     return isNaN(intValue) ? 0 : intValue * 1024;
383   },
385   /**
386    * Clears the cache.
387    */
388   clearCache: function ()
389   {
390     var cache = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
391                                  .getService(Components.interfaces.nsICacheStorageService);
392     try {
393       cache.clear();
394     } catch(ex) {}
395     this.updateActualCacheSize();
396   },
398   /**
399    * Clears the application cache.
400    */
401   clearOfflineAppCache: function ()
402   {
403     Components.utils.import("resource:///modules/offlineAppCache.jsm");
404     OfflineAppCacheHelper.clear();
406     this.updateActualAppCacheSize();
407     this.updateOfflineApps();
408   },
410   readOfflineNotify: function()
411   {
412     var pref = document.getElementById("browser.offline-apps.notify");
413     var button = document.getElementById("offlineNotifyExceptions");
414     button.disabled = !pref.value;
415     return pref.value;
416   },
418   showOfflineExceptions: function()
419   {
420     var bundlePreferences = document.getElementById("bundlePreferences");
421     var params = { blockVisible     : false,
422                    sessionVisible   : false,
423                    allowVisible     : false,
424                    prefilledHost    : "",
425                    permissionType   : "offline-app",
426                    manageCapability : Components.interfaces.nsIPermissionManager.DENY_ACTION,
427                    windowTitle      : bundlePreferences.getString("offlinepermissionstitle"),
428                    introText        : bundlePreferences.getString("offlinepermissionstext") };
429     document.documentElement.openWindow("Browser:Permissions",
430                                         "chrome://browser/content/preferences/permissions.xul",
431                                         "", params);
432   },
434   // XXX: duplicated in browser.js
435   _getOfflineAppUsage: function (host, groups)
436   {
437     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
438                        getService(Components.interfaces.nsIApplicationCacheService);
439     if (!groups)
440       groups = cacheService.getGroups();
442     var ios = Components.classes["@mozilla.org/network/io-service;1"].
443               getService(Components.interfaces.nsIIOService);
445     var usage = 0;
446     for (var i = 0; i < groups.length; i++) {
447       var uri = ios.newURI(groups[i], null, null);
448       if (uri.asciiHost == host) {
449         var cache = cacheService.getActiveCache(groups[i]);
450         usage += cache.usage;
451       }
452     }
454     return usage;
455   },
457   /**
458    * Updates the list of offline applications
459    */
460   updateOfflineApps: function ()
461   {
462     var pm = Components.classes["@mozilla.org/permissionmanager;1"]
463                        .getService(Components.interfaces.nsIPermissionManager);
465     var list = document.getElementById("offlineAppsList");
466     while (list.firstChild) {
467       list.removeChild(list.firstChild);
468     }
470     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
471                        getService(Components.interfaces.nsIApplicationCacheService);
472     var groups = cacheService.getGroups();
474     var bundle = document.getElementById("bundlePreferences");
476     var enumerator = pm.enumerator;
477     while (enumerator.hasMoreElements()) {
478       var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
479       if (perm.type == "offline-app" &&
480           perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION &&
481           perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
482         var row = document.createElement("listitem");
483         row.id = "";
484         row.className = "offlineapp";
485         row.setAttribute("host", perm.host);
486         var converted = DownloadUtils.
487                         convertByteUnits(this._getOfflineAppUsage(perm.host, groups));
488         row.setAttribute("usage",
489                          bundle.getFormattedString("offlineAppUsage",
490                                                    converted));
491         list.appendChild(row);
492       }
493     }
494   },
496   offlineAppSelected: function()
497   {
498     var removeButton = document.getElementById("offlineAppsListRemove");
499     var list = document.getElementById("offlineAppsList");
500     if (list.selectedItem) {
501       removeButton.setAttribute("disabled", "false");
502     } else {
503       removeButton.setAttribute("disabled", "true");
504     }
505   },
507   removeOfflineApp: function()
508   {
509     var list = document.getElementById("offlineAppsList");
510     var item = list.selectedItem;
511     var host = item.getAttribute("host");
513     var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
514                             .getService(Components.interfaces.nsIPromptService);
515     var flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 +
516                 prompts.BUTTON_TITLE_CANCEL * prompts.BUTTON_POS_1;
518     var bundle = document.getElementById("bundlePreferences");
519     var title = bundle.getString("offlineAppRemoveTitle");
520     var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]);
521     var confirm = bundle.getString("offlineAppRemoveConfirm");
522     var result = prompts.confirmEx(window, title, prompt, flags, confirm,
523                                    null, null, null, {});
524     if (result != 0)
525       return;
527     // clear offline cache entries
528     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
529                        getService(Components.interfaces.nsIApplicationCacheService);
530     var ios = Components.classes["@mozilla.org/network/io-service;1"].
531               getService(Components.interfaces.nsIIOService);
532     var groups = cacheService.getGroups();
533     for (var i = 0; i < groups.length; i++) {
534         var uri = ios.newURI(groups[i], null, null);
535         if (uri.asciiHost == host) {
536             var cache = cacheService.getActiveCache(groups[i]);
537             cache.discard();
538         }
539     }
541     // remove the permission
542     var pm = Components.classes["@mozilla.org/permissionmanager;1"]
543                        .getService(Components.interfaces.nsIPermissionManager);
544     pm.remove(host, "offline-app",
545               Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
546     pm.remove(host, "offline-app",
547               Components.interfaces.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
549     list.removeChild(item);
550     gAdvancedPane.offlineAppSelected();
551     this.updateActualAppCacheSize();
552   },
554   // UPDATE TAB
556   /*
557    * Preferences:
558    *
559    * app.update.enabled
560    * - true if updates to the application are enabled, false otherwise
561    * extensions.update.enabled
562    * - true if updates to extensions and themes are enabled, false otherwise
563    * browser.search.update
564    * - true if updates to search engines are enabled, false otherwise
565    * app.update.auto
566    * - true if updates should be automatically downloaded and installed,
567    *   possibly with a warning if incompatible extensions are installed (see
568    *   app.update.mode); false if the user should be asked what he wants to do
569    *   when an update is available
570    * app.update.mode
571    * - an integer:
572    *     0    do not warn if an update will disable extensions or themes
573    *     1    warn if an update will disable extensions or themes
574    *     2    warn if an update will disable extensions or themes *or* if the
575    *          update is a major update
576    */
578 #ifdef MOZ_UPDATER
579   /**
580    * Selects the item of the radiogroup, and sets the warnIncompatible checkbox
581    * based on the pref values and locked states.
582    *
583    * UI state matrix for update preference conditions
584    *
585    * UI Components:                              Preferences
586    * Radiogroup                                  i   = app.update.enabled
587    * Warn before disabling extensions checkbox   ii  = app.update.auto
588    *                                             iii = app.update.mode
589    *
590    * Disabled states:
591    * Element           pref  value  locked  disabled
592    * radiogroup        i     t/f    f       false
593    *                   i     t/f    *t*     *true*
594    *                   ii    t/f    f       false
595    *                   ii    t/f    *t*     *true*
596    *                   iii   0/1/2  t/f     false
597    * warnIncompatible  i     t      f       false
598    *                   i     t      *t*     *true*
599    *                   i     *f*    t/f     *true*
600    *                   ii    t      f       false
601    *                   ii    t      *t*     *true*
602    *                   ii    *f*    t/f     *true*
603    *                   iii   0/1/2  f       false
604    *                   iii   0/1/2  *t*     *true*
605    */
606   updateReadPrefs: function ()
607   {
608     var enabledPref = document.getElementById("app.update.enabled");
609     var autoPref = document.getElementById("app.update.auto");
610 #ifdef XP_WIN
611 #ifdef MOZ_METRO
612     var metroEnabledPref = document.getElementById("app.update.metro.enabled");
613 #endif
614 #endif
615     var radiogroup = document.getElementById("updateRadioGroup");
617     if (!enabledPref.value)   // Don't care for autoPref.value in this case.
618       radiogroup.value="manual";    // 3. Never check for updates.
619 #ifdef XP_WIN
620 #ifdef MOZ_METRO
621     // enabledPref.value && autoPref.value && metroEnabledPref.value
622     else if (metroEnabledPref.value && this._showingWin8Prefs)
623       radiogroup.value="autoMetro"; // 0. Automatically install updates for both Metro and Desktop
624 #endif
625 #endif
626     else if (autoPref.value)  // enabledPref.value && autoPref.value
627       radiogroup.value="auto";      // 1. Automatically install updates for Desktop only
628     else                      // enabledPref.value && !autoPref.value
629       radiogroup.value="checkOnly"; // 2. Check, but let me choose
631     var canCheck = Components.classes["@mozilla.org/updates/update-service;1"].
632                      getService(Components.interfaces.nsIApplicationUpdateService).
633                      canCheckForUpdates;
634     // canCheck is false if the enabledPref is false and locked,
635     // or the binary platform or OS version is not known.
636     // A locked pref is sufficient to disable the radiogroup.
637     radiogroup.disabled = !canCheck || enabledPref.locked || autoPref.locked;
639     var modePref = document.getElementById("app.update.mode");
640     var warnIncompatible = document.getElementById("warnIncompatible");
641     // the warnIncompatible checkbox value is set by readAddonWarn
642     warnIncompatible.disabled = radiogroup.disabled || modePref.locked ||
643                                 !enabledPref.value || !autoPref.value;
644 #ifdef XP_WIN
645 #ifdef MOZ_METRO
646     if (this._showingWin8Prefs) {
647       warnIncompatible.disabled |= metroEnabledPref.value;
648       warnIncompatible.checked |= metroEnabledPref.value;
649     }
650 #endif
651 #endif
653 #ifdef MOZ_MAINTENANCE_SERVICE
654     // Check to see if the maintenance service is installed.
655     // If it is don't show the preference at all.
656     var installed;
657     try {
658       var wrk = Components.classes["@mozilla.org/windows-registry-key;1"]
659                 .createInstance(Components.interfaces.nsIWindowsRegKey);
660       wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
661                "SOFTWARE\\Mozilla\\MaintenanceService",
662                wrk.ACCESS_READ | wrk.WOW64_64);
663       installed = wrk.readIntValue("Installed");
664       wrk.close();
665     } catch(e) {
666     }
667     if (installed != 1) {
668       document.getElementById("useService").hidden = true;
669     }
670     try {
671       const DRIVE_FIXED = 3;
672       const LPCWSTR = ctypes.jschar.ptr;
673       const UINT = ctypes.uint32_t;
674       let kernel32 = ctypes.open("kernel32");
675       let GetDriveType = kernel32.declare("GetDriveTypeW", ctypes.default_abi, UINT, LPCWSTR);
676       var UpdatesDir = Components.classes["@mozilla.org/updates/update-service;1"].
677                        getService(Components.interfaces.nsIApplicationUpdateService);
678       let rootPath = UpdatesDir.getUpdatesDirectory();
679       while (rootPath.parent != null) {
680         rootPath = rootPath.parent;
681       }
682       if (GetDriveType(rootPath.path) != DRIVE_FIXED) {
683         document.getElementById("useService").hidden = true;
684       }
685       kernel32.close();
686     } catch(e) {
687     }
688 #endif
689   },
691   /**
692    * Sets the pref values based on the selected item of the radiogroup,
693    * and sets the disabled state of the warnIncompatible checkbox accordingly.
694    */
695   updateWritePrefs: function ()
696   {
697     var enabledPref = document.getElementById("app.update.enabled");
698     var autoPref = document.getElementById("app.update.auto");
699     var modePref = document.getElementById("app.update.mode");
700 #ifdef XP_WIN
701 #ifdef MOZ_METRO
702     var metroEnabledPref = document.getElementById("app.update.metro.enabled");
703     // Initialize the pref to false only if we're showing the option
704     if (this._showingWin8Prefs) {
705       metroEnabledPref.value = false;
706     }
707 #endif
708 #endif
709     var radiogroup = document.getElementById("updateRadioGroup");
710     switch (radiogroup.value) {
711       case "auto":      // 1. Automatically install updates for Desktop only
712         enabledPref.value = true;
713         autoPref.value = true;
714         break;
715 #ifdef XP_WIN
716 #ifdef MOZ_METRO
717       case "autoMetro": // 0. Automatically install updates for both Metro and Desktop
718         enabledPref.value = true;
719         autoPref.value = true;
720         metroEnabledPref.value = true;
721         modePref.value = 1;
722         break;
723 #endif
724 #endif
725       case "checkOnly": // 2. Check, but let me choose
726         enabledPref.value = true;
727         autoPref.value = false;
728         break;
729       case "manual":    // 3. Never check for updates.
730         enabledPref.value = false;
731         autoPref.value = false;
732     }
734     var warnIncompatible = document.getElementById("warnIncompatible");
735     warnIncompatible.disabled = enabledPref.locked || !enabledPref.value ||
736                                 autoPref.locked || !autoPref.value ||
737                                 modePref.locked;
739 #ifdef XP_WIN
740 #ifdef MOZ_METRO
741     if (this._showingWin8Prefs) {
742       warnIncompatible.disabled |= metroEnabledPref.value;
743       warnIncompatible.checked |= metroEnabledPref.value;
744     }
745 #endif
746 #endif
747   },
749   /**
750    * Stores the value of the app.update.mode preference, which is a tristate
751    * integer preference.  We store the value here so that we can properly
752    * restore the preference value if the UI reflecting the preference value
753    * is in a state which can represent either of two integer values (as
754    * opposed to only one possible value in the other UI state).
755    */
756   _modePreference: -1,
758   /**
759    * Reads the app.update.mode preference and converts its value into a
760    * true/false value for use in determining whether the "Warn me if this will
761    * disable extensions or themes" checkbox is checked.  We also save the value
762    * of the preference so that the preference value can be properly restored if
763    * the user's preferences cannot adequately be expressed by a single checkbox.
764    *
765    * app.update.mode          Checkbox State    Meaning
766    * 0                        Unchecked         Do not warn
767    * 1                        Checked           Warn if there are incompatibilities
768    * 2                        Checked           Warn if there are incompatibilities,
769    *                                            or the update is major.
770    */
771   readAddonWarn: function ()
772   {
773     var preference = document.getElementById("app.update.mode");
774     var warn = preference.value != 0;
775     gAdvancedPane._modePreference = warn ? preference.value : 1;
776     return warn;
777   },
779   /**
780    * Converts the state of the "Warn me if this will disable extensions or
781    * themes" checkbox into the integer preference which represents it,
782    * returning that value.
783    */
784   writeAddonWarn: function ()
785   {
786     var warnIncompatible = document.getElementById("warnIncompatible");
787     return !warnIncompatible.checked ? 0 : gAdvancedPane._modePreference;
788   },
790   /**
791    * Displays the history of installed updates.
792    */
793   showUpdates: function ()
794   {
795     var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"]
796                              .createInstance(Components.interfaces.nsIUpdatePrompt);
797     prompter.showUpdateHistory(window);
798   },
799 #endif
801   // ENCRYPTION TAB
803   /*
804    * Preferences:
805    *
806    * security.default_personal_cert
807    * - a string:
808    *     "Select Automatically"   select a certificate automatically when a site
809    *                              requests one
810    *     "Ask Every Time"         present a dialog to the user so he can select
811    *                              the certificate to use on a site which
812    *                              requests one
813    */
815   /**
816    * Displays the user's certificates and associated options.
817    */
818   showCertificates: function ()
819   {
820     document.documentElement.openWindow("mozilla:certmanager",
821                                         "chrome://pippki/content/certManager.xul",
822                                         "", null);
823   },
825   /**
826    * Displays a dialog in which OCSP preferences can be configured.
827    */
828   showOCSP: function ()
829   {
830     document.documentElement.openSubDialog("chrome://mozapps/content/preferences/ocsp.xul",
831                                            "", null);
832   },
834   /**
835    * Displays a dialog from which the user can manage his security devices.
836    */
837   showSecurityDevices: function ()
838   {
839     document.documentElement.openWindow("mozilla:devicemanager",
840                                         "chrome://pippki/content/device_manager.xul",
841                                         "", null);
842   }
843 #ifdef HAVE_SHELL_SERVICE
844   ,
846   // SYSTEM DEFAULTS
848   /*
849    * Preferences:
850    *
851    * browser.shell.checkDefault
852    * - true if a default-browser check (and prompt to make it so if necessary)
853    *   occurs at startup, false otherwise
854    */
856   /**
857    * Show button for setting browser as default browser or information that
858    * browser is already the default browser.
859    */
860   updateSetDefaultBrowser: function()
861   {
862     let shellSvc = getShellService();
863     let setDefaultPane = document.getElementById("setDefaultPane");
864     if (!shellSvc) {
865       setDefaultPane.hidden = true;
866       document.getElementById("alwaysCheckDefault").disabled = true;
867       return;
868     }
869     let selectedIndex =
870       shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
871     setDefaultPane.selectedIndex = selectedIndex;
872   },
874   /**
875    * Set browser as the operating system default browser.
876    */
877   setDefaultBrowser: function()
878   {
879     let shellSvc = getShellService();
880     if (!shellSvc)
881       return;
882     shellSvc.setDefaultBrowser(true, false);
883     let selectedIndex =
884       shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
885     document.getElementById("setDefaultPane").selectedIndex = selectedIndex;
886   }
887 #endif