mirror of https://github.com/roytam1/kmeleon.git
13 changed files with 4626 additions and 16 deletions
@ -0,0 +1,7 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
||||
|
||||
.site { |
||||
-moz-binding: url("chrome://browser/content/preferences/aboutPermissions.xml#site"); |
||||
} |
@ -0,0 +1,895 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict"; |
||||
|
||||
let Ci = Components.interfaces; |
||||
let Cc = Components.classes; |
||||
let Cu = Components.utils; |
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
Cu.import("resource://gre/modules/Services.jsm"); |
||||
Cu.import("resource://gre/modules/DownloadUtils.jsm"); |
||||
Cu.import("resource://gre/modules/NetUtil.jsm"); |
||||
Cu.import("resource://gre/modules/ForgetAboutSite.jsm"); |
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", |
||||
"resource://gre/modules/PluralForm.jsm"); |
||||
|
||||
let gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"]. |
||||
getService(Ci.nsIFaviconService); |
||||
|
||||
let gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"]. |
||||
getService(Ci.nsPIPlacesDatabase). |
||||
DBConnection. |
||||
clone(true); |
||||
|
||||
let gSitesStmt = gPlacesDatabase.createAsyncStatement( |
||||
"SELECT get_unreversed_host(rev_host) AS host " + |
||||
"FROM moz_places " + |
||||
"WHERE rev_host > '.' " + |
||||
"AND visit_count > 0 " + |
||||
"GROUP BY rev_host " + |
||||
"ORDER BY MAX(frecency) DESC " + |
||||
"LIMIT :limit"); |
||||
|
||||
let gVisitStmt = gPlacesDatabase.createAsyncStatement( |
||||
"SELECT SUM(visit_count) AS count " + |
||||
"FROM moz_places " + |
||||
"WHERE rev_host = :rev_host"); |
||||
|
||||
/** |
||||
* Permission types that should be tested with testExactPermission, as opposed |
||||
* to testPermission. This is based on what consumers use to test these permissions. |
||||
*/ |
||||
let TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone"]; |
||||
|
||||
/** |
||||
* Site object represents a single site, uniquely identified by a host. |
||||
*/ |
||||
function Site(host) { |
||||
this.host = host; |
||||
this.listitem = null; |
||||
|
||||
this.httpURI = NetUtil.newURI("http://" + this.host); |
||||
this.httpsURI = NetUtil.newURI("https://" + this.host); |
||||
} |
||||
|
||||
Site.prototype = { |
||||
/** |
||||
* Gets the favicon to use for the site. The callback only gets called if |
||||
* a favicon is found for either the http URI or the https URI. |
||||
* |
||||
* @param aCallback |
||||
* A callback function that takes a favicon image URL as a parameter. |
||||
*/ |
||||
getFavicon: function Site_getFavicon(aCallback) { |
||||
function invokeCallback(aFaviconURI) { |
||||
try { |
||||
// Use getFaviconLinkForIcon to get image data from the database instead
|
||||
// of using the favicon URI to fetch image data over the network.
|
||||
aCallback(gFaviconService.getFaviconLinkForIcon(aFaviconURI).spec); |
||||
} catch (e) { |
||||
Cu.reportError("AboutPermissions: " + e); |
||||
} |
||||
} |
||||
|
||||
// Try to find favicon for both URIs, but always prefer the https favicon.
|
||||
gFaviconService.getFaviconURLForPage(this.httpsURI, function (aURI) { |
||||
if (aURI) { |
||||
invokeCallback(aURI); |
||||
} else { |
||||
gFaviconService.getFaviconURLForPage(this.httpURI, function (aURI) { |
||||
if (aURI) { |
||||
invokeCallback(aURI); |
||||
} |
||||
}); |
||||
} |
||||
}.bind(this)); |
||||
}, |
||||
|
||||
/** |
||||
* Gets the number of history visits for the site. |
||||
* |
||||
* @param aCallback |
||||
* A function that takes the visit count (a number) as a parameter. |
||||
*/ |
||||
getVisitCount: function Site_getVisitCount(aCallback) { |
||||
let rev_host = this.host.split("").reverse().join("") + "."; |
||||
gVisitStmt.params.rev_host = rev_host; |
||||
gVisitStmt.executeAsync({ |
||||
handleResult: function(aResults) { |
||||
let row = aResults.getNextRow(); |
||||
let count = row.getResultByName("count") || 0; |
||||
try { |
||||
aCallback(count); |
||||
} catch (e) { |
||||
Cu.reportError("AboutPermissions: " + e); |
||||
} |
||||
}, |
||||
handleError: function(aError) { |
||||
Cu.reportError("AboutPermissions: " + aError); |
||||
}, |
||||
handleCompletion: function(aReason) { |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* Gets the permission value stored for a specified permission type. |
||||
* |
||||
* @param aType |
||||
* The permission type string stored in permission manager. |
||||
* e.g. "cookie", "geo", "indexedDB", "popup", "image" |
||||
* @param aResultObj |
||||
* An object that stores the permission value set for aType. |
||||
* |
||||
* @return A boolean indicating whether or not a permission is set. |
||||
*/ |
||||
getPermission: function Site_getPermission(aType, aResultObj) { |
||||
// Password saving isn't a nsIPermissionManager permission type, so handle
|
||||
// it seperately.
|
||||
if (aType == "password") { |
||||
aResultObj.value = this.loginSavingEnabled ? |
||||
Ci.nsIPermissionManager.ALLOW_ACTION : |
||||
Ci.nsIPermissionManager.DENY_ACTION; |
||||
return true; |
||||
} |
||||
|
||||
let permissionValue; |
||||
if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) { |
||||
permissionValue = Services.perms.testPermission(this.httpURI, aType); |
||||
} else { |
||||
permissionValue = Services.perms.testExactPermission(this.httpURI, aType); |
||||
} |
||||
aResultObj.value = permissionValue; |
||||
|
||||
return permissionValue != Ci.nsIPermissionManager.UNKNOWN_ACTION; |
||||
}, |
||||
|
||||
/** |
||||
* Sets a permission for the site given a permission type and value. |
||||
* |
||||
* @param aType |
||||
* The permission type string stored in permission manager. |
||||
* e.g. "cookie", "geo", "indexedDB", "popup", "image" |
||||
* @param aPerm |
||||
* The permission value to set for the permission type. This should |
||||
* be one of the constants defined in nsIPermissionManager. |
||||
*/ |
||||
setPermission: function Site_setPermission(aType, aPerm) { |
||||
// Password saving isn't a nsIPermissionManager permission type, so handle
|
||||
// it seperately.
|
||||
if (aType == "password") { |
||||
this.loginSavingEnabled = aPerm == Ci.nsIPermissionManager.ALLOW_ACTION; |
||||
return; |
||||
} |
||||
|
||||
// Using httpURI is kind of bogus, but the permission manager stores the
|
||||
// permission for the host, so the right thing happens in the end.
|
||||
Services.perms.add(this.httpURI, aType, aPerm); |
||||
}, |
||||
|
||||
/** |
||||
* Clears a user-set permission value for the site given a permission type. |
||||
* |
||||
* @param aType |
||||
* The permission type string stored in permission manager. |
||||
* e.g. "cookie", "geo", "indexedDB", "popup", "image" |
||||
*/ |
||||
clearPermission: function Site_clearPermission(aType) { |
||||
Services.perms.remove(this.host, aType); |
||||
}, |
||||
|
||||
/** |
||||
* Gets cookies stored for the site. This does not return cookies stored |
||||
* for the base domain, only the exact hostname stored for the site. |
||||
* |
||||
* @return An array of the cookies set for the site. |
||||
*/ |
||||
get cookies() { |
||||
let cookies = []; |
||||
let enumerator = Services.cookies.getCookiesFromHost(this.host); |
||||
while (enumerator.hasMoreElements()) { |
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); |
||||
// getCookiesFromHost returns cookies for base domain, but we only want
|
||||
// the cookies for the exact domain.
|
||||
if (cookie.rawHost == this.host) { |
||||
cookies.push(cookie); |
||||
} |
||||
} |
||||
return cookies; |
||||
}, |
||||
|
||||
/** |
||||
* Removes a set of specific cookies from the browser. |
||||
*/ |
||||
clearCookies: function Site_clearCookies() { |
||||
this.cookies.forEach(function(aCookie) { |
||||
Services.cookies.remove(aCookie.host, aCookie.name, aCookie.path, false); |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* Gets logins stored for the site. |
||||
* |
||||
* @return An array of the logins stored for the site. |
||||
*/ |
||||
get logins() { |
||||
let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", ""); |
||||
let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", ""); |
||||
return httpLogins.concat(httpsLogins); |
||||
}, |
||||
|
||||
get loginSavingEnabled() { |
||||
// Only say that login saving is blocked if it is blocked for both http and https.
|
||||
return Services.logins.getLoginSavingEnabled(this.httpURI.prePath) && |
||||
Services.logins.getLoginSavingEnabled(this.httpsURI.prePath); |
||||
}, |
||||
|
||||
set loginSavingEnabled(isEnabled) { |
||||
Services.logins.setLoginSavingEnabled(this.httpURI.prePath, isEnabled); |
||||
Services.logins.setLoginSavingEnabled(this.httpsURI.prePath, isEnabled); |
||||
}, |
||||
|
||||
/** |
||||
* Removes all data from the browser corresponding to the site. |
||||
*/ |
||||
forgetSite: function Site_forgetSite() { |
||||
ForgetAboutSite.removeDataFromDomain(this.host); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* PermissionDefaults object keeps track of default permissions for sites based |
||||
* on global preferences. |
||||
* |
||||
* Inspired by pageinfo/permissions.js |
||||
*/ |
||||
let PermissionDefaults = { |
||||
UNKNOWN: Ci.nsIPermissionManager.UNKNOWN_ACTION, // 0
|
||||
ALLOW: Ci.nsIPermissionManager.ALLOW_ACTION, // 1
|
||||
DENY: Ci.nsIPermissionManager.DENY_ACTION, // 2
|
||||
SESSION: Ci.nsICookiePermission.ACCESS_SESSION, // 8
|
||||
|
||||
get password() { |
||||
if (Services.prefs.getBoolPref("signon.rememberSignons")) { |
||||
return this.ALLOW; |
||||
} |
||||
return this.DENY; |
||||
}, |
||||
set password(aValue) { |
||||
let value = (aValue != this.DENY); |
||||
Services.prefs.setBoolPref("signon.rememberSignons", value); |
||||
}, |
||||
|
||||
// For use with network.cookie.* prefs.
|
||||
COOKIE_ACCEPT: 0, |
||||
COOKIE_DENY: 2, |
||||
COOKIE_NORMAL: 0, |
||||
COOKIE_SESSION: 2, |
||||
|
||||
get cookie() { |
||||
if (Services.prefs.getIntPref("network.cookie.cookieBehavior") == this.COOKIE_DENY) { |
||||
return this.DENY; |
||||
} |
||||
|
||||
if (Services.prefs.getIntPref("network.cookie.lifetimePolicy") == this.COOKIE_SESSION) { |
||||
return this.SESSION; |
||||
} |
||||
return this.ALLOW; |
||||
}, |
||||
set cookie(aValue) { |
||||
let value = (aValue == this.DENY) ? this.COOKIE_DENY : this.COOKIE_ACCEPT; |
||||
Services.prefs.setIntPref("network.cookie.cookieBehavior", value); |
||||
|
||||
let lifetimeValue = aValue == this.SESSION ? this.COOKIE_SESSION : |
||||
this.COOKIE_NORMAL; |
||||
Services.prefs.setIntPref("network.cookie.lifetimePolicy", lifetimeValue); |
||||
}, |
||||
|
||||
get geo() { |
||||
if (!Services.prefs.getBoolPref("geo.enabled")) { |
||||
return this.DENY; |
||||
} |
||||
// We always ask for permission to share location with a specific site, so
|
||||
// there is no global ALLOW.
|
||||
return this.UNKNOWN; |
||||
}, |
||||
set geo(aValue) { |
||||
let value = (aValue != this.DENY); |
||||
Services.prefs.setBoolPref("geo.enabled", value); |
||||
}, |
||||
|
||||
get indexedDB() { |
||||
if (!Services.prefs.getBoolPref("dom.indexedDB.enabled")) { |
||||
return this.DENY; |
||||
} |
||||
// We always ask for permission to enable indexedDB storage for a specific
|
||||
// site, so there is no global ALLOW.
|
||||
return this.UNKNOWN; |
||||
}, |
||||
set indexedDB(aValue) { |
||||
let value = (aValue != this.DENY); |
||||
Services.prefs.setBoolPref("dom.indexedDB.enabled", value); |
||||
}, |
||||
|
||||
get popup() { |
||||
if (Services.prefs.getBoolPref("dom.disable_open_during_load")) { |
||||
return this.DENY; |
||||
} |
||||
return this.ALLOW; |
||||
}, |
||||
set popup(aValue) { |
||||
let value = (aValue == this.DENY); |
||||
Services.prefs.setBoolPref("dom.disable_open_during_load", value); |
||||
}, |
||||
|
||||
get fullscreen() { |
||||
if (!Services.prefs.getBoolPref("full-screen-api.enabled")) { |
||||
return this.DENY; |
||||
} |
||||
return this.UNKNOWN; |
||||
}, |
||||
set fullscreen(aValue) { |
||||
let value = (aValue != this.DENY); |
||||
Services.prefs.setBoolPref("full-screen-api.enabled", value); |
||||
}, |
||||
|
||||
get camera() this.UNKNOWN, |
||||
get microphone() this.UNKNOWN |
||||
}; |
||||
|
||||
/** |
||||
* AboutPermissions manages the about:permissions page. |
||||
*/ |
||||
let AboutPermissions = { |
||||
/** |
||||
* Number of sites to return from the places database. |
||||
*/ |
||||
PLACES_SITES_LIMIT: 50, |
||||
|
||||
/** |
||||
* When adding sites to the dom sites-list, divide workload into intervals. |
||||
*/ |
||||
LIST_BUILD_CHUNK: 5, // interval size
|
||||
LIST_BUILD_DELAY: 100, // delay between intervals
|
||||
|
||||
/** |
||||
* Stores a mapping of host strings to Site objects. |
||||
*/ |
||||
_sites: {}, |
||||
|
||||
sitesList: null, |
||||
_selectedSite: null, |
||||
|
||||
/** |
||||
* For testing, track initializations so we can send notifications |
||||
*/ |
||||
_initPlacesDone: false, |
||||
_initServicesDone: false, |
||||
|
||||
/** |
||||
* This reflects the permissions that we expose in the UI. These correspond |
||||
* to permission type strings in the permission manager, PermissionDefaults, |
||||
* and element ids in aboutPermissions.xul. |
||||
* |
||||
* Potential future additions: "sts/use", "sts/subd" |
||||
*/ |
||||
_supportedPermissions: ["password", "cookie", "geo", "indexedDB", "popup", |
||||
"fullscreen", "camera", "microphone"], |
||||
|
||||
/** |
||||
* Permissions that don't have a global "Allow" option. |
||||
*/ |
||||
_noGlobalAllow: ["geo", "indexedDB", "fullscreen", "camera", "microphone"], |
||||
|
||||
/** |
||||
* Permissions that don't have a global "Deny" option. |
||||
*/ |
||||
_noGlobalDeny: ["camera", "microphone"], |
||||
|
||||
_stringBundle: Services.strings. |
||||
createBundle("chrome://browser/locale/preferences/aboutPermissions.properties"), |
||||
|
||||
/** |
||||
* Called on page load. |
||||
*/ |
||||
init: function() { |
||||
this.sitesList = document.getElementById("sites-list"); |
||||
|
||||
this.getSitesFromPlaces(); |
||||
|
||||
this.enumerateServicesGenerator = this.getEnumerateServicesGenerator(); |
||||
setTimeout(this.enumerateServicesDriver.bind(this), this.LIST_BUILD_DELAY); |
||||
|
||||
// Attach observers in case data changes while the page is open.
|
||||
Services.prefs.addObserver("signon.rememberSignons", this, false); |
||||
Services.prefs.addObserver("network.cookie.", this, false); |
||||
Services.prefs.addObserver("geo.enabled", this, false); |
||||
Services.prefs.addObserver("dom.indexedDB.enabled", this, false); |
||||
Services.prefs.addObserver("dom.disable_open_during_load", this, false); |
||||
Services.prefs.addObserver("full-screen-api.enabled", this, false); |
||||
|
||||
Services.obs.addObserver(this, "perm-changed", false); |
||||
Services.obs.addObserver(this, "passwordmgr-storage-changed", false); |
||||
Services.obs.addObserver(this, "cookie-changed", false); |
||||
Services.obs.addObserver(this, "browser:purge-domain-data", false); |
||||
|
||||
this._observersInitialized = true; |
||||
Services.obs.notifyObservers(null, "browser-permissions-preinit", null); |
||||
}, |
||||
|
||||
/** |
||||
* Called on page unload. |
||||
*/ |
||||
cleanUp: function() { |
||||
if (this._observersInitialized) { |
||||
Services.prefs.removeObserver("signon.rememberSignons", this, false); |
||||
Services.prefs.removeObserver("network.cookie.", this, false); |
||||
Services.prefs.removeObserver("geo.enabled", this, false); |
||||
Services.prefs.removeObserver("dom.indexedDB.enabled", this, false); |
||||
Services.prefs.removeObserver("dom.disable_open_during_load", this, false); |
||||
Services.prefs.removeObserver("full-screen-api.enabled", this, false); |
||||
|
||||
Services.obs.removeObserver(this, "perm-changed"); |
||||
Services.obs.removeObserver(this, "passwordmgr-storage-changed"); |
||||
Services.obs.removeObserver(this, "cookie-changed"); |
||||
Services.obs.removeObserver(this, "browser:purge-domain-data"); |
||||
} |
||||
|
||||
gSitesStmt.finalize(); |
||||
gVisitStmt.finalize(); |
||||
gPlacesDatabase.asyncClose(null); |
||||
}, |
||||
|
||||
observe: function (aSubject, aTopic, aData) { |
||||
switch(aTopic) { |
||||
case "perm-changed": |
||||
// Permissions changes only affect individual sites.
|
||||
if (!this._selectedSite) { |
||||
break; |
||||
} |
||||
// aSubject is null when nsIPermisionManager::removeAll() is called.
|
||||
if (!aSubject) { |
||||
this._supportedPermissions.forEach(function(aType){ |
||||
this.updatePermission(aType); |
||||
}, this); |
||||
break; |
||||
} |
||||
let permission = aSubject.QueryInterface(Ci.nsIPermission); |
||||
// We can't compare selectedSite.host and permission.host here because
|
||||
// we need to handle the case where a parent domain was changed in a
|
||||
// way that affects the subdomain.
|
||||
if (this._supportedPermissions.indexOf(permission.type) != -1) { |
||||
this.updatePermission(permission.type); |
||||
} |
||||
break; |
||||
case "nsPref:changed": |
||||
this._supportedPermissions.forEach(function(aType){ |
||||
this.updatePermission(aType); |
||||
}, this); |
||||
break; |
||||
case "passwordmgr-storage-changed": |
||||
this.updatePermission("password"); |
||||
if (this._selectedSite) { |
||||
this.updatePasswordsCount(); |
||||
} |
||||
break; |
||||
case "cookie-changed": |
||||
if (this._selectedSite) { |
||||
this.updateCookiesCount(); |
||||
} |
||||
break; |
||||
case "browser:purge-domain-data": |
||||
this.deleteFromSitesList(aData); |
||||
break; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Creates Site objects for the top-frecency sites in the places database and stores |
||||
* them in _sites. The number of sites created is controlled by PLACES_SITES_LIMIT. |
||||
*/ |
||||
getSitesFromPlaces: function() { |
||||
gSitesStmt.params.limit = this.PLACES_SITES_LIMIT; |
||||
gSitesStmt.executeAsync({ |
||||
handleResult: function(aResults) { |
||||
AboutPermissions.startSitesListBatch(); |
||||
let row; |
||||
while (row = aResults.getNextRow()) { |
||||
let host = row.getResultByName("host"); |
||||
AboutPermissions.addHost(host); |
||||
} |
||||
AboutPermissions.endSitesListBatch(); |
||||
}, |
||||
handleError: function(aError) { |
||||
Cu.reportError("AboutPermissions: " + aError); |
||||
}, |
||||
handleCompletion: function(aReason) { |
||||
// Notify oberservers for testing purposes.
|
||||
AboutPermissions._initPlacesDone = true; |
||||
if (AboutPermissions._initServicesDone) { |
||||
Services.obs.notifyObservers(null, "browser-permissions-initialized", null); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* Drives getEnumerateServicesGenerator to work in intervals. |
||||
*/ |
||||
enumerateServicesDriver: function() { |
||||
if (this.enumerateServicesGenerator.next()) { |
||||
// Build top sitesList items faster so that the list never seems sparse
|
||||
let delay = Math.min(this.sitesList.itemCount * 5, this.LIST_BUILD_DELAY); |
||||
setTimeout(this.enumerateServicesDriver.bind(this), delay); |
||||
} else { |
||||
this.enumerateServicesGenerator.close(); |
||||
this._initServicesDone = true; |
||||
if (this._initPlacesDone) { |
||||
Services.obs.notifyObservers(null, "browser-permissions-initialized", null); |
||||
} |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Finds sites that have non-default permissions and creates Site objects for |
||||
* them if they are not already stored in _sites. |
||||
*/ |
||||
getEnumerateServicesGenerator: function() { |
||||
let itemCnt = 1; |
||||
|
||||
let logins = Services.logins.getAllLogins(); |
||||
logins.forEach(function(aLogin) { |
||||
if (itemCnt % this.LIST_BUILD_CHUNK == 0) { |
||||
yield true; |
||||
} |
||||
try { |
||||
// aLogin.hostname is a string in origin URL format (e.g. "http://foo.com")
|
||||
let uri = NetUtil.newURI(aLogin.hostname); |
||||
this.addHost(uri.host); |
||||
} catch (e) { |
||||
// newURI will throw for add-ons logins stored in chrome:// URIs
|
||||
} |
||||
itemCnt++; |
||||
}, this); |
||||
|
||||
let disabledHosts = Services.logins.getAllDisabledHosts(); |
||||
disabledHosts.forEach(function(aHostname) { |
||||
if (itemCnt % this.LIST_BUILD_CHUNK == 0) { |
||||
yield true; |
||||
} |
||||
try { |
||||
// aHostname is a string in origin URL format (e.g. "http://foo.com")
|
||||
let uri = NetUtil.newURI(aHostname); |
||||
this.addHost(uri.host); |
||||
} catch (e) { |
||||
// newURI will throw for add-ons logins stored in chrome:// URIs
|
||||
} |
||||
itemCnt++; |
||||
}, this); |
||||
|
||||
let enumerator = Services.perms.enumerator; |
||||
while (enumerator.hasMoreElements()) { |
||||
if (itemCnt % this.LIST_BUILD_CHUNK == 0) { |
||||
yield true; |
||||
} |
||||
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); |
||||
// Only include sites with exceptions set for supported permission types.
|
||||
if (this._supportedPermissions.indexOf(permission.type) != -1) { |
||||
this.addHost(permission.host); |
||||
} |
||||
itemCnt++; |
||||
} |
||||
|
||||
yield false; |
||||
}, |
||||
|
||||
/** |
||||
* Creates a new Site and adds it to _sites if it's not already there. |
||||
* |
||||
* @param aHost |
||||
* A host string. |
||||
*/ |
||||
addHost: function(aHost) { |
||||
if (aHost in this._sites) { |
||||
return; |
||||
} |
||||
let site = new Site(aHost); |
||||
this._sites[aHost] = site; |
||||
this.addToSitesList(site); |
||||
}, |
||||
|
||||
/** |
||||
* Populates sites-list richlistbox with data from Site object. |
||||
* |
||||
* @param aSite |
||||
* A Site object. |
||||
*/ |
||||
addToSitesList: function(aSite) { |
||||
let item = document.createElement("richlistitem"); |
||||
item.setAttribute("class", "site"); |
||||
item.setAttribute("value", aSite.host); |
||||
|
||||
aSite.getFavicon(function(aURL) { |
||||
item.setAttribute("favicon", aURL); |
||||
}); |
||||
aSite.listitem = item; |
||||
|
||||
// Make sure to only display relevant items when list is filtered
|
||||
let filterValue = document.getElementById("sites-filter").value.toLowerCase(); |
||||
item.collapsed = aSite.host.toLowerCase().indexOf(filterValue) == -1; |
||||
|
||||
(this._listFragment || this.sitesList).appendChild(item); |
||||
}, |
||||
|
||||
startSitesListBatch: function () { |
||||
if (!this._listFragment) |
||||
this._listFragment = document.createDocumentFragment(); |
||||
}, |
||||
|
||||
endSitesListBatch: function () { |
||||
if (this._listFragment) { |
||||
this.sitesList.appendChild(this._listFragment); |
||||
this._listFragment = null; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Hides sites in richlistbox based on search text in sites-filter textbox. |
||||
*/ |
||||
filterSitesList: function() { |
||||
let siteItems = this.sitesList.children; |
||||
let filterValue = document.getElementById("sites-filter").value.toLowerCase(); |
||||
|
||||
if (filterValue == "") { |
||||
for (let i = 0; i < siteItems.length; i++) { |
||||
siteItems[i].collapsed = false; |
||||
} |
||||
return; |
||||
} |
||||
|
||||
for (let i = 0; i < siteItems.length; i++) { |
||||
let siteValue = siteItems[i].value.toLowerCase(); |
||||
siteItems[i].collapsed = siteValue.indexOf(filterValue) == -1; |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Removes all evidence of the selected site. The "forget this site" observer |
||||
* will call deleteFromSitesList to update the UI. |
||||
*/ |
||||
forgetSite: function() { |
||||
this._selectedSite.forgetSite(); |
||||
}, |
||||
|
||||
/** |
||||
* Deletes sites for a host and all of its sub-domains. Removes these sites |
||||
* from _sites and removes their corresponding elements from the DOM. |
||||
* |
||||
* @param aHost |
||||
* The host string corresponding to the site to delete. |
||||
*/ |
||||
deleteFromSitesList: function(aHost) { |
||||
for (let host in this._sites) { |
||||
let site = this._sites[host]; |
||||
if (site.host.hasRootDomain(aHost)) { |
||||
if (site == this._selectedSite) { |
||||
// Replace site-specific interface with "All Sites" interface.
|
||||
this.sitesList.selectedItem = document.getElementById("all-sites-item"); |
||||
} |
||||
|
||||
this.sitesList.removeChild(site.listitem); |
||||
delete this._sites[site.host]; |
||||
} |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* Shows interface for managing site-specific permissions. |
||||
*/ |
||||
onSitesListSelect: function(event) { |
||||
if (event.target.selectedItem.id == "all-sites-item") { |
||||
// Clear the header label value from the previously selected site.
|
||||
document.getElementById("site-label").value = ""; |
||||
this.manageDefaultPermissions(); |
||||
return; |
||||
} |
||||
|
||||
let host = event.target.value; |
||||
let site = this._selectedSite = this._sites[host]; |
||||
document.getElementById("site-label").value = host; |
||||
document.getElementById("header-deck").selectedPanel = |
||||
document.getElementById("site-header"); |
||||
|
||||
this.updateVisitCount(); |
||||
this.updatePermissionsBox(); |
||||
}, |
||||
|
||||
/** |
||||
* Shows interface for managing default permissions. This corresponds to |
||||
* the "All Sites" list item. |
||||
*/ |
||||
manageDefaultPermissions: function() { |
||||
this._selectedSite = null; |
||||
|
||||
document.getElementById("header-deck").selectedPanel = |
||||
document.getElementById("defaults-header"); |
||||
|
||||
this.updatePermissionsBox(); |
||||
}, |
||||
|
||||
/** |
||||
* Updates permissions interface based on selected site. |
||||
*/ |
||||
updatePermissionsBox: function() { |
||||
this._supportedPermissions.forEach(function(aType){ |
||||
this.updatePermission(aType); |
||||
}, this); |
||||
|
||||
this.updatePasswordsCount(); |
||||
this.updateCookiesCount(); |
||||
}, |
||||
|
||||
/** |
||||
* Sets menulist for a given permission to the correct state, based on the |
||||
* stored permission. |
||||
* |
||||
* @param aType |
||||
* The permission type string stored in permission manager. |
||||
* e.g. "cookie", "geo", "indexedDB", "popup", "image" |
||||
*/ |
||||
updatePermission: function(aType) { |
||||
let allowItem = document.getElementById(aType + "-" + PermissionDefaults.ALLOW); |
||||
allowItem.hidden = !this._selectedSite && |
||||
this._noGlobalAllow.indexOf(aType) != -1; |
||||
let denyItem = document.getElementById(aType + "-" + PermissionDefaults.DENY); |
||||
denyItem.hidden = !this._selectedSite && |
||||
this._noGlobalDeny.indexOf(aType) != -1; |
||||
|
||||
let permissionMenulist = document.getElementById(aType + "-menulist"); |
||||
let permissionValue; |
||||
if (!this._selectedSite) { |
||||
// If there is no selected site, we are updating the default permissions interface.
|
||||
permissionValue = PermissionDefaults[aType]; |
||||
if (aType == "cookie") |
||||
// cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
|
||||
// for site-specific preferences only.
|
||||
document.getElementById("cookie-9").hidden = true; |
||||
} else { |
||||
if (aType == "cookie") |
||||
document.getElementById("cookie-9").hidden = false; |
||||
let result = {}; |
||||
permissionValue = this._selectedSite.getPermission(aType, result) ? |
||||
result.value : PermissionDefaults[aType]; |
||||
} |
||||
|
||||
permissionMenulist.selectedItem = document.getElementById(aType + "-" + permissionValue); |
||||
}, |
||||
|
||||
onPermissionCommand: function(event) { |
||||
let permissionType = event.currentTarget.getAttribute("type"); |
||||
let permissionValue = event.target.value; |
||||
|
||||
if (!this._selectedSite) { |
||||
// If there is no selected site, we are setting the default permission.
|
||||
PermissionDefaults[permissionType] = permissionValue; |
||||
} else { |
||||
this._selectedSite.setPermission(permissionType, permissionValue); |
||||
} |
||||
}, |
||||
|
||||
updateVisitCount: function() { |
||||
this._selectedSite.getVisitCount(function(aCount) { |
||||
let visitForm = AboutPermissions._stringBundle.GetStringFromName("visitCount"); |
||||
let visitLabel = PluralForm.get(aCount, visitForm) |
||||
.replace("#1", aCount); |
||||
document.getElementById("site-visit-count").value = visitLabel; |
||||
}); |
||||
}, |
||||
|
||||
updatePasswordsCount: function() { |
||||
if (!this._selectedSite) { |
||||
document.getElementById("passwords-count").hidden = true; |
||||
document.getElementById("passwords-manage-all-button").hidden = false; |
||||
return; |
||||
} |
||||
|
||||
let passwordsCount = this._selectedSite.logins.length; |
||||
let passwordsForm = this._stringBundle.GetStringFromName("passwordsCount"); |
||||
let passwordsLabel = PluralForm.get(passwordsCount, passwordsForm) |
||||
.replace("#1", passwordsCount); |
||||
|
||||
document.getElementById("passwords-label").value = passwordsLabel; |
||||
document.getElementById("passwords-manage-button").disabled = (passwordsCount < 1); |
||||
document.getElementById("passwords-manage-all-button").hidden = true; |
||||
document.getElementById("passwords-count").hidden = false; |
||||
}, |
||||
|
||||
/** |
||||
* Opens password manager dialog. |
||||
*/ |
||||
managePasswords: function() { |
||||
let selectedHost = ""; |
||||
if (this._selectedSite) { |
||||
selectedHost = this._selectedSite.host; |
||||
} |
||||
|
||||
let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager"); |
||||
if (win) { |
||||
win.setFilter(selectedHost); |
||||
win.focus(); |
||||
} else { |
||||
window.openDialog("chrome://passwordmgr/content/passwordManager.xul", |
||||
"Toolkit:PasswordManager", "", {filterString : selectedHost}); |
||||
} |
||||
}, |
||||
|
||||
updateCookiesCount: function() { |
||||
if (!this._selectedSite) { |
||||
document.getElementById("cookies-count").hidden = true; |
||||
document.getElementById("cookies-clear-all-button").hidden = false; |
||||
document.getElementById("cookies-manage-all-button").hidden = false; |
||||
return; |
||||
} |
||||
|
||||
let cookiesCount = this._selectedSite.cookies.length; |
||||
let cookiesForm = this._stringBundle.GetStringFromName("cookiesCount"); |
||||
let cookiesLabel = PluralForm.get(cookiesCount, cookiesForm) |
||||
.replace("#1", cookiesCount); |
||||
|
||||
document.getElementById("cookies-label").value = cookiesLabel; |
||||
document.getElementById("cookies-clear-button").disabled = (cookiesCount < 1); |
||||
document.getElementById("cookies-manage-button").disabled = (cookiesCount < 1); |
||||
document.getElementById("cookies-clear-all-button").hidden = true; |
||||
document.getElementById("cookies-manage-all-button").hidden = true; |
||||
document.getElementById("cookies-count").hidden = false; |
||||
}, |
||||
|
||||
/** |
||||
* Clears cookies for the selected site. |
||||
*/ |
||||
clearCookies: function() { |
||||
if (!this._selectedSite) { |
||||
return; |
||||
} |
||||
let site = this._selectedSite; |
||||
site.clearCookies(site.cookies); |
||||
this.updateCookiesCount(); |
||||
}, |
||||
|
||||
/** |
||||
* Opens cookie manager dialog. |
||||
*/ |
||||
manageCookies: function() { |
||||
let selectedHost = ""; |
||||
if (this._selectedSite) { |
||||
selectedHost = this._selectedSite.host; |
||||
} |
||||
|
||||
let win = Services.wm.getMostRecentWindow("Browser:Cookies"); |
||||
if (win) { |
||||
win.gCookiesWindow.setFilter(selectedHost); |
||||
win.focus(); |
||||
} else { |
||||
window.openDialog("chrome://browser/content/preferences/cookies.xul", |
||||
"Browser:Cookies", "", {filterString : selectedHost}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// See nsPrivateBrowsingService.js
|
||||
String.prototype.hasRootDomain = function hasRootDomain(aDomain) { |
||||
let index = this.indexOf(aDomain); |
||||
if (index == -1) |
||||
return false; |
||||
|
||||
if (this == aDomain) |
||||
return true; |
||||
|
||||
let prevChar = this[index - 1]; |
||||
return (index == (this.length - aDomain.length)) && |
||||
(prevChar == "." || prevChar == "/"); |
||||
} |
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?> |
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public |
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
||||
|
||||
<!DOCTYPE bindings> |
||||
<bindings xmlns="http://www.mozilla.org/xbl" |
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
||||
xmlns:xbl="http://www.mozilla.org/xbl"> |
||||
<binding id="site" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> |
||||
<content> |
||||
<xul:hbox class="site-container" align="center" flex="1"> |
||||
<xul:image xbl:inherits="src=favicon" class="site-favicon"/> |
||||
<xul:label xbl:inherits="value,selected" class="site-domain" crop="end" flex="1"/> |
||||
</xul:hbox> |
||||
</content> |
||||
</binding> |
||||
</bindings> |
@ -0,0 +1,260 @@
|
||||
<?xml version="1.0"?> |
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public |
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> |
||||
<?xml-stylesheet href="chrome://browser/content/preferences/aboutPermissions.css"?> |
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/aboutPermissions.css"?> |
||||
|
||||
<!DOCTYPE page [ |
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > |
||||
%brandDTD; |
||||
<!ENTITY % aboutPermissionsDTD SYSTEM "chrome://browser/locale/preferences/aboutPermissions.dtd" > |
||||
%aboutPermissionsDTD; |
||||
]> |
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml" |
||||
id="permissions-page" title="&permissionsManager.title;" |
||||
onload="AboutPermissions.init();" |
||||
onunload="AboutPermissions.cleanUp();" |
||||
disablefastfind="true" |
||||
role="application"> |
||||
|
||||
<script type="application/javascript" |
||||
src="chrome://browser/content/preferences/aboutPermissions.js"/> |
||||
|
||||
<hbox flex="1" id="permissions-content" class="main-content"> |
||||
|
||||
<vbox id="sites-box"> |
||||
<textbox id="sites-filter" |
||||
emptytext="&sites.search;" |
||||
oncommand="AboutPermissions.filterSitesList();" |
||||
type="search"/> |
||||
<richlistbox id="sites-list" |
||||
flex="1" |
||||
class="list" |
||||
onselect="AboutPermissions.onSitesListSelect(event);"> |
||||
<richlistitem id="all-sites-item" |
||||
class="site" |
||||
value="&sites.allSites;"/> |
||||
</richlistbox> |
||||
</vbox> |
||||
|
||||
<vbox id="permissions-box" flex="1"> |
||||
|
||||
<deck id="header-deck"> |
||||
<hbox id="site-header" class="pref-item" align="center"> |
||||
<description id="site-description"> |
||||
&header.site.start;<label id="site-label"/>&header.site.end; |
||||
</description> |
||||
<label id="site-visit-count"/> |
||||
<spacer flex="1"/> |
||||
<button id="forget-site-button" |
||||
label="&permissions.forgetSite;" |
||||
oncommand="AboutPermissions.forgetSite();"/> |
||||
</hbox> |
||||
|
||||
<hbox id="defaults-header" class="pref-item" align="center"> |
||||
<description id="defaults-description"> |
||||
&header.defaults; |
||||
</description> |
||||
</hbox> |
||||
</deck> |
||||
|
||||
<!-- Passwords --> |
||||
<hbox id="password-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="password"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&password.label;"/> |
||||
<hbox align="center"> |
||||
<menulist id="password-menulist" |
||||
class="pref-menulist" |
||||
type="password" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="password-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="password-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
<button id="passwords-manage-all-button" |
||||
label="&password.manage;" |
||||
oncommand="AboutPermissions.managePasswords();"/> |
||||
</hbox> |
||||
<hbox id="passwords-count" align="center"> |
||||
<label id="passwords-label"/> |
||||
<button id="passwords-manage-button" |
||||
label="&password.manage;" |
||||
oncommand="AboutPermissions.managePasswords();"/> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- Geolocation --> |
||||
<hbox id="geo-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="geo"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&geo.label;"/> |
||||
<hbox> |
||||
<menulist id="geo-menulist" |
||||
class="pref-menulist" |
||||
type="geo" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="geo-0" value="0" label="&permission.alwaysAsk;"/> |
||||
<menuitem id="geo-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="geo-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- Camera --> |
||||
<hbox id="camera-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="camera"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&camera.label;"/> |
||||
<hbox align="center"> |
||||
<menulist id="camera-menulist" |
||||
class="pref-menulist" |
||||
type="camera" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="camera-0" value="0" label="&permission.alwaysAsk;"/> |
||||
<menuitem id="camera-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="camera-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- Microphone --> |
||||
<hbox id="microphone-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="microphone"/> |
||||
<vbox> |
||||
<label class="pref-title" value="µphone.label;"/> |
||||
<hbox align="center"> |
||||
<menulist id="microphone-menulist" |
||||
class="pref-menulist" |
||||
type="microphone" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="microphone-0" value="0" label="&permission.alwaysAsk;"/> |
||||
<menuitem id="microphone-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="microphone-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- Cookies --> |
||||
<hbox id="cookie-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="cookie"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&cookie.label;"/> |
||||
<hbox align="center"> |
||||
<menulist id="cookie-menulist" |
||||
class="pref-menulist" |
||||
type="cookie" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="cookie-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="cookie-8" value="8" label="&permission.allowForSession;"/> |
||||
<menuitem id="cookie-9" value="9" label="&permission.allowFirstPartyOnly;"/> |
||||
<menuitem id="cookie-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
<button id="cookies-clear-all-button" |
||||
label="&cookie.removeAll;" |
||||
oncommand="Services.cookies.removeAll();"/> |
||||
<button id="cookies-manage-all-button" |
||||
label="&cookie.manage;" |
||||
oncommand="AboutPermissions.manageCookies();"/> |
||||
</hbox> |
||||
<hbox id="cookies-count" align="center"> |
||||
<label id="cookies-label"/> |
||||
<button id="cookies-clear-button" |
||||
label="&cookie.remove;" |
||||
oncommand="AboutPermissions.clearCookies();"/> |
||||
<button id="cookies-manage-button" |
||||
label="&cookie.manage;" |
||||
oncommand="AboutPermissions.manageCookies();"/> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- Pop-up Blocking --> |
||||
<hbox id="popup-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="popup"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&popup.label;"/> |
||||
<hbox> |
||||
<menulist id="popup-menulist" |
||||
class="pref-menulist" |
||||
type="popup" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="popup-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="popup-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- IndexedDB Storage --> |
||||
<hbox id="indexedDB-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="indexedDB"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&indexedDB.label;"/> |
||||
<hbox> |
||||
<menulist id="indexedDB-menulist" |
||||
class="pref-menulist" |
||||
type="indexedDB" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="indexedDB-0" value="0" label="&permission.alwaysAsk;"/> |
||||
<menuitem id="indexedDB-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="indexedDB-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
<!-- Fullscreen --> |
||||
<hbox id="fullscreen-pref-item" |
||||
class="pref-item" align="top"> |
||||
<image class="pref-icon" type="fullscreen"/> |
||||
<vbox> |
||||
<label class="pref-title" value="&fullscreen.label;"/> |
||||
<hbox align="center"> |
||||
<menulist id="fullscreen-menulist" |
||||
class="pref-menulist" |
||||
type="fullscreen" |
||||
oncommand="AboutPermissions.onPermissionCommand(event);"> |
||||
<menupopup> |
||||
<menuitem id="fullscreen-0" value="0" label="&permission.alwaysAsk;"/> |
||||
<menuitem id="fullscreen-1" value="1" label="&permission.allow;"/> |
||||
<menuitem id="fullscreen-2" value="2" label="&permission.block;"/> |
||||
</menupopup> |
||||
</menulist> |
||||
</hbox> |
||||
</vbox> |
||||
</hbox> |
||||
|
||||
</vbox> |
||||
</hbox> |
||||
|
||||
</page> |
@ -0,0 +1,818 @@
|
||||
//@line 5 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
|
||||
// Load DownloadUtils module for convertByteUnits
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); |
||||
Components.utils.import("resource://gre/modules/ctypes.jsm"); |
||||
Components.utils.import("resource://gre/modules/Services.jsm"); |
||||
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm"); |
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
||||
|
||||
var gAdvancedPane = { |
||||
_inited: false, |
||||
|
||||
/** |
||||
* Brings the appropriate tab to the front and initializes various bits of UI. |
||||
*/ |
||||
init: function () |
||||
{ |
||||
this._inited = true; |
||||
var advancedPrefs = document.getElementById("advancedPrefs"); |
||||
|
||||
var extraArgs = window.arguments[1]; |
||||
if (extraArgs && extraArgs["advancedTab"]){ |
||||
advancedPrefs.selectedTab = document.getElementById(extraArgs["advancedTab"]); |
||||
} else { |
||||
var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex"); |
||||
if (preference.value !== null) |
||||
advancedPrefs.selectedIndex = preference.value; |
||||
} |
||||
|
||||
//@line 34 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
let onUnload = function () { |
||||
window.removeEventListener("unload", onUnload, false); |
||||
Services.prefs.removeObserver("app.update.", this); |
||||
}.bind(this); |
||||
window.addEventListener("unload", onUnload, false); |
||||
Services.prefs.addObserver("app.update.", this, false); |
||||
this.updateReadPrefs(); |
||||
//@line 42 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
this.updateOfflineApps(); |
||||
//@line 44 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
this.initSubmitCrashes(); |
||||
//@line 46 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
this.initTelemetry(); |
||||
//@line 48 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
this.initSubmitHealthReport(); |
||||
//@line 50 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
|
||||
this.updateActualCacheSize(); |
||||
this.updateActualAppCacheSize(); |
||||
|
||||
let bundlePrefs = document.getElementById("bundlePreferences"); |
||||
document.getElementById("offlineAppsList") |
||||
.style.height = bundlePrefs.getString("offlineAppsList.height"); |
||||
|
||||
// Notify observers that the UI is now ready
|
||||
Services.obs.notifyObservers(window, "advanced-pane-loaded", null); |
||||
}, |
||||
|
||||
/** |
||||
* Stores the identity of the current tab in preferences so that the selected |
||||
* tab can be persisted between openings of the preferences window. |
||||
*/ |
||||
tabSelectionChanged: function () |
||||
{ |
||||
if (!this._inited) |
||||
return; |
||||
var advancedPrefs = document.getElementById("advancedPrefs"); |
||||
var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex"); |
||||
preference.valueFromPreferences = advancedPrefs.selectedIndex; |
||||
}, |
||||
|
||||
// GENERAL TAB
|
||||
|
||||
/* |
||||
* Preferences: |
||||
* |
||||
* accessibility.browsewithcaret |
||||
* - true enables keyboard navigation and selection within web pages using a |
||||
* visible caret, false uses normal keyboard navigation with no caret |
||||
* accessibility.typeaheadfind |
||||
* - when set to true, typing outside text areas and input boxes will |
||||
* automatically start searching for what's typed within the current |
||||
* document; when set to false, no search action happens |
||||
* general.autoScroll |
||||
* - when set to true, clicking the scroll wheel on the mouse activates a |
||||
* mouse mode where moving the mouse down scrolls the document downward with |
||||
* speed correlated with the distance of the cursor from the original |
||||
* position at which the click occurred (and likewise with movement upward); |
||||
* if false, this behavior is disabled |
||||
* general.smoothScroll |
||||
* - set to true to enable finer page scrolling than line-by-line on page-up, |
||||
* page-down, and other such page movements |
||||
* layout.spellcheckDefault |
||||
* - an integer: |
||||
* 0 disables spellchecking |
||||
* 1 enables spellchecking, but only for multiline text fields |
||||
* 2 enables spellchecking for all text fields |
||||
*/ |
||||
|
||||
/** |
||||
* Stores the original value of the spellchecking preference to enable proper |
||||
* restoration if unchanged (since we're mapping a tristate onto a checkbox). |
||||
*/ |
||||
_storedSpellCheck: 0, |
||||
|
||||
/** |
||||
* Returns true if any spellchecking is enabled and false otherwise, caching |
||||
* the current value to enable proper pref restoration if the checkbox is |
||||
* never changed. |
||||
*/ |
||||
readCheckSpelling: function () |
||||
{ |
||||
var pref = document.getElementById("layout.spellcheckDefault"); |
||||
this._storedSpellCheck = pref.value; |
||||
|
||||
return (pref.value != 0); |
||||
}, |
||||
|
||||
/** |
||||
* Returns the value of the spellchecking preference represented by UI, |
||||
* preserving the preference's "hidden" value if the preference is |
||||
* unchanged and represents a value not strictly allowed in UI. |
||||
*/ |
||||
writeCheckSpelling: function () |
||||
{ |
||||
var checkbox = document.getElementById("checkSpelling"); |
||||
return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0; |
||||
}, |
||||
|
||||
/** |
||||
* security.OCSP.enabled is an integer value for legacy reasons. |
||||
* A value of 1 means OCSP is enabled. Any other value means it is disabled. |
||||
*/ |
||||
readEnableOCSP: function () |
||||
{ |
||||
var preference = document.getElementById("security.OCSP.enabled"); |
||||
// This is the case if the preference is the default value.
|
||||
if (preference.value === undefined) { |
||||
return true; |
||||
} |
||||
return preference.value == 1; |
||||
}, |
||||
|
||||
/** |
||||
* See documentation for readEnableOCSP. |
||||
*/ |
||||
writeEnableOCSP: function () |
||||
{ |
||||
var checkbox = document.getElementById("enableOCSP"); |
||||
return checkbox.checked ? 1 : 0; |
||||
}, |
||||
|
||||
/** |
||||
* When the user toggles the layers.acceleration.disabled pref, |
||||
* sync its new value to the gfx.direct2d.disabled pref too. |
||||
*/ |
||||
updateHardwareAcceleration: function() |
||||
{ |
||||
//@line 163 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
var fromPref = document.getElementById("layers.acceleration.disabled"); |
||||
var toPref = document.getElementById("gfx.direct2d.disabled"); |
||||
toPref.value = fromPref.value; |
||||
//@line 167 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
}, |
||||
|
||||
// DATA CHOICES TAB
|
||||
|
||||
/** |
||||
* opening links behind a modal dialog is poor form. Work around flawed text-link handling here. |
||||
*/ |
||||
openTextLink: function (evt) { |
||||
let where = Services.prefs.getBoolPref("browser.preferences.instantApply") ? "tab" : "window"; |
||||
openUILinkIn(evt.target.getAttribute("href"), where); |
||||
evt.preventDefault(); |
||||
}, |
||||
|
||||
/** |
||||
* Set up or hide the Learn More links for various data collection options |
||||
*/ |
||||
_setupLearnMoreLink: function (pref, element) { |
||||
// set up the Learn More link with the correct URL
|
||||
let url = Services.prefs.getCharPref(pref); |
||||
let el = document.getElementById(element); |
||||
|
||||
if (url) { |
||||
el.setAttribute("href", url); |
||||
} else { |
||||
el.setAttribute("hidden", "true"); |
||||
} |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
initSubmitCrashes: function () |
||||
{ |
||||
var checkbox = document.getElementById("submitCrashesBox"); |
||||
try { |
||||
var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"]. |
||||
getService(Components.interfaces.nsICrashReporter); |
||||
checkbox.checked = cr.submitReports; |
||||
} catch (e) { |
||||
checkbox.style.display = "none"; |
||||
} |
||||
this._setupLearnMoreLink("toolkit.crashreporter.infoURL", "crashReporterLearnMore"); |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
updateSubmitCrashes: function () |
||||
{ |
||||
var checkbox = document.getElementById("submitCrashesBox"); |
||||
try { |
||||
var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"]. |
||||
getService(Components.interfaces.nsICrashReporter); |
||||
cr.submitReports = checkbox.checked; |
||||
} catch (e) { } |
||||
}, |
||||
|
||||
|
||||
/** |
||||
* The preference/checkbox is configured in XUL. |
||||
* |
||||
* In all cases, set up the Learn More link sanely |
||||
*/ |
||||
initTelemetry: function () |
||||
{ |
||||
//@line 233 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore"); |
||||
//@line 235 "c:\builds\moz2_slave\rel-m-esr38-w32_bld-0000000000\build\browser\components\preferences\advanced.js"
|
||||
}, |
||||
|
||||
/** |
||||
* Set the status of the telemetry controls based on the input argument. |
||||
* @param {Boolean} aEnabled False disables the controls, true enables them. |
||||
*/ |
||||
setTelemetrySectionEnabled: function (aEnabled) |