mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
bug 679784: let nsIContentPrefService handle private browsing mode; r=ehsan
Manage private browsing mode in content pref service. CPS should be available in private browsing mode, but should not store informations on disk, and should clear all informations once the private session ends. When setting a pref in private mode, it is stored in an in-memory hash table. When getting a pref, it is retrieved from that hash table if available. Otherwise, it is retrieved using the standard mechanism. When removing a pref, it is retrieved from the hash table. The rationale is that in private mode, it's ok to read a pref from normal database, but not ok to set it. The in-memory hash table is cleared when leaving the private browsing mode. When removing a set of preferences (with removeGroupedPrefs or removePrefsByName), preferences are removed from the in-memory hashtable, *and* from normal mode database. The rationale is that visiting a website may trigger setting/getting/removing for a specific preference only. But removing many prefs at once is the result of an action not associated with a website. For example, user may wish to delete all its informations. In that case, user probably expects to not have those informations restored once it leaves private browsing mode.
This commit is contained in:
parent
09c28c4a99
commit
46c2f6aa69
@ -68,11 +68,8 @@ var FullZoom = {
|
||||
// browser.zoom.updateBackgroundTabs preference cache
|
||||
updateBackgroundTabs: undefined,
|
||||
|
||||
// whether we are in private browsing mode
|
||||
_inPrivateBrowsing: false,
|
||||
|
||||
get siteSpecific() {
|
||||
return !this._inPrivateBrowsing && this._siteSpecificPref;
|
||||
return this._siteSpecificPref;
|
||||
},
|
||||
|
||||
//**************************************************************************//
|
||||
@ -94,15 +91,6 @@ var FullZoom = {
|
||||
// Register ourselves with the service so we know when our pref changes.
|
||||
Services.contentPrefs.addObserver(this.name, this);
|
||||
|
||||
// We disable site-specific preferences in Private Browsing mode, because the
|
||||
// content preferences module is disabled
|
||||
Services.obs.addObserver(this, "private-browsing", true);
|
||||
|
||||
// Retrieve the initial status of the Private Browsing mode.
|
||||
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService).
|
||||
privateBrowsingEnabled;
|
||||
|
||||
this._siteSpecificPref =
|
||||
gPrefService.getBoolPref("browser.zoom.siteSpecific");
|
||||
this.updateBackgroundTabs =
|
||||
@ -113,7 +101,6 @@ var FullZoom = {
|
||||
},
|
||||
|
||||
destroy: function FullZoom_destroy() {
|
||||
Services.obs.removeObserver(this, "private-browsing");
|
||||
gPrefService.removeObserver("browser.zoom.", this);
|
||||
Services.contentPrefs.removeObserver(this.name, this);
|
||||
window.removeEventListener("DOMMouseScroll", this, false);
|
||||
@ -187,16 +174,6 @@ var FullZoom = {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "private-browsing":
|
||||
switch (aData) {
|
||||
case "enter":
|
||||
this._inPrivateBrowsing = true;
|
||||
break;
|
||||
case "exit":
|
||||
this._inPrivateBrowsing = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -321,14 +298,12 @@ var FullZoom = {
|
||||
* one.
|
||||
**/
|
||||
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
|
||||
if ((!this.siteSpecific && !this._inPrivateBrowsing) ||
|
||||
gInPrintPreviewMode)
|
||||
if ((!this.siteSpecific) || gInPrintPreviewMode)
|
||||
return;
|
||||
|
||||
var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
|
||||
try {
|
||||
if (browser.contentDocument instanceof Ci.nsIImageDocument ||
|
||||
this._inPrivateBrowsing)
|
||||
if (browser.contentDocument instanceof Ci.nsIImageDocument)
|
||||
ZoomManager.setZoomForBrowser(browser, 1);
|
||||
else if (typeof aValue != "undefined")
|
||||
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
|
||||
|
@ -104,8 +104,6 @@
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsIFilePicker.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "nsIContentURIGrouper.h"
|
||||
#include "nsIContentPrefService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPopupWindowManager.h"
|
||||
@ -453,7 +451,6 @@ nsHTMLInputElement::InitUploadLastDir() {
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService && gUploadLastDir) {
|
||||
observerService->AddObserver(gUploadLastDir, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_TRUE);
|
||||
observerService->AddObserver(gUploadLastDir, "browser:purge-session-history", PR_TRUE);
|
||||
}
|
||||
}
|
||||
@ -463,38 +460,11 @@ nsHTMLInputElement::DestroyUploadLastDir() {
|
||||
NS_IF_RELEASE(gUploadLastDir);
|
||||
}
|
||||
|
||||
UploadLastDir::UploadLastDir():
|
||||
mInPrivateBrowsing(PR_FALSE)
|
||||
{
|
||||
nsCOMPtr<nsIPrivateBrowsingService> pbService =
|
||||
do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
|
||||
if (pbService) {
|
||||
pbService->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
|
||||
}
|
||||
|
||||
mUploadLastDirStore.Init();
|
||||
}
|
||||
|
||||
nsresult
|
||||
UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsILocalFile** aFile)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "aURI is null");
|
||||
NS_PRECONDITION(aFile, "aFile is null");
|
||||
// Retrieve the data from memory if it's present during private browsing mode,
|
||||
// otherwise fall through to check the CPS
|
||||
if (mInPrivateBrowsing) {
|
||||
nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
|
||||
do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
|
||||
if (!hostnameGrouperService)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
nsString group;
|
||||
hostnameGrouperService->Group(aURI, group);
|
||||
|
||||
if (mUploadLastDirStore.Get(group, aFile)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to get the CPS, if it's not present we'll just return
|
||||
nsCOMPtr<nsIContentPrefService> contentPrefService =
|
||||
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||
@ -536,18 +506,6 @@ UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
|
||||
}
|
||||
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(parentFile);
|
||||
|
||||
// Store the data in memory instead of the CPS during private browsing mode
|
||||
if (mInPrivateBrowsing) {
|
||||
nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
|
||||
do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
|
||||
if (!hostnameGrouperService)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
nsString group;
|
||||
hostnameGrouperService->Group(aURI, group);
|
||||
|
||||
return mUploadLastDirStore.Put(group, localFile);
|
||||
}
|
||||
|
||||
// Attempt to get the CPS, if it's not present we'll just return
|
||||
nsCOMPtr<nsIContentPrefService> contentPrefService =
|
||||
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||
@ -573,19 +531,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
|
||||
NS_IMETHODIMP
|
||||
UploadLastDir::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
|
||||
{
|
||||
if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
|
||||
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
|
||||
mInPrivateBrowsing = PR_TRUE;
|
||||
} else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
|
||||
mInPrivateBrowsing = PR_FALSE;
|
||||
if (mUploadLastDirStore.IsInitialized()) {
|
||||
mUploadLastDirStore.Clear();
|
||||
}
|
||||
}
|
||||
} else if (strcmp(aTopic, "browser:purge-session-history") == 0) {
|
||||
if (mUploadLastDirStore.IsInitialized()) {
|
||||
mUploadLastDirStore.Clear();
|
||||
}
|
||||
if (strcmp(aTopic, "browser:purge-session-history") == 0) {
|
||||
nsCOMPtr<nsIContentPrefService> contentPrefService =
|
||||
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||
if (contentPrefService)
|
||||
|
@ -85,8 +85,6 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
UploadLastDir();
|
||||
|
||||
/**
|
||||
* Fetch the last used directory for this location from the content
|
||||
* pref service, if it is available.
|
||||
@ -104,10 +102,6 @@ public:
|
||||
* file will be stored
|
||||
*/
|
||||
nsresult StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile);
|
||||
private:
|
||||
// Directories are stored here during private browsing mode
|
||||
nsInterfaceHashtable<nsStringHashKey, nsILocalFile> mUploadLastDirStore;
|
||||
PRBool mInPrivateBrowsing;
|
||||
};
|
||||
|
||||
class nsHTMLInputElement : public nsGenericHTMLFormElement,
|
||||
|
@ -134,10 +134,66 @@ function ContentPrefService() {
|
||||
// was due to a temporary condition (like being out of disk space).
|
||||
this._dbInit();
|
||||
|
||||
// detect if we are in private browsing mode
|
||||
this._inPrivateBrowsing = false;
|
||||
try { // The Private Browsing service might not be available.
|
||||
var pbs = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
this._inPrivateBrowsing = pbs.privateBrowsingEnabled;
|
||||
} catch (e) {}
|
||||
this._observerSvc.addObserver(this, "private-browsing", false);
|
||||
|
||||
// Observe shutdown so we can shut down the database connection.
|
||||
this._observerSvc.addObserver(this, "xpcom-shutdown", false);
|
||||
}
|
||||
|
||||
var inMemoryPrefsProto = {
|
||||
getPref: function(aName, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
|
||||
if (this._prefCache[aGroup] && this._prefCache[aGroup].hasOwnProperty(aName)) {
|
||||
let value = this._prefCache[aGroup][aName];
|
||||
return [true, value];
|
||||
}
|
||||
return [false, undefined];
|
||||
},
|
||||
|
||||
setPref: function(aName, aValue, aGroup) {
|
||||
if (typeof aValue == "boolean")
|
||||
aValue = aValue ? 1 : 0;
|
||||
else if (aValue === undefined)
|
||||
aValue = null;
|
||||
|
||||
this.cachePref(aName, aValue, aGroup);
|
||||
},
|
||||
|
||||
removePref: function(aName, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
|
||||
if (this._prefCache[aGroup].hasOwnProperty(aName)) {
|
||||
delete this._prefCache[aGroup][aName];
|
||||
if (Object.keys(this._prefCache[aGroup]).length == 0) {
|
||||
// remove empty group
|
||||
delete this._prefCache[aGroup];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
invalidate: function(aKeepGlobal) {
|
||||
if (!aKeepGlobal) {
|
||||
this._prefCache = {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._prefCache.hasOwnProperty("__GlobalPrefs__")) {
|
||||
let globals = this._prefCache["__GlobalPrefs__"];
|
||||
this._prefCache = {"__GlobalPrefs__": globals};
|
||||
} else {
|
||||
this._prefCache = {};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ContentPrefService.prototype = {
|
||||
//**************************************************************************//
|
||||
// XPCOM Plumbing
|
||||
@ -183,6 +239,7 @@ ContentPrefService.prototype = {
|
||||
|
||||
_destroy: function ContentPrefService__destroy() {
|
||||
this._observerSvc.removeObserver(this, "xpcom-shutdown");
|
||||
this._observerSvc.removeObserver(this, "private-browsing");
|
||||
|
||||
// Finalize statements which may have been used asynchronously.
|
||||
if (this.__stmtSelectPref)
|
||||
@ -210,6 +267,17 @@ ContentPrefService.prototype = {
|
||||
case "xpcom-shutdown":
|
||||
this._destroy();
|
||||
break;
|
||||
case "private-browsing":
|
||||
switch (data) {
|
||||
case "enter":
|
||||
this._inPrivateBrowsing = true;
|
||||
break;
|
||||
case "exit":
|
||||
this._inPrivateBrowsing = false;
|
||||
this._privModeStorage.invalidate();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -217,71 +285,86 @@ ContentPrefService.prototype = {
|
||||
//**************************************************************************//
|
||||
// Prefs cache
|
||||
|
||||
_cache: {
|
||||
_prefCache: {},
|
||||
|
||||
cachePref: function(aName, aValue, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
|
||||
if (!this._prefCache[aGroup]) {
|
||||
this._possiblyCleanCache();
|
||||
this._prefCache[aGroup] = {};
|
||||
}
|
||||
|
||||
this._prefCache[aGroup][aName] = aValue;
|
||||
_cache: Object.create(inMemoryPrefsProto, {
|
||||
_prefCache: {
|
||||
value: {}, configurable: true, writable: true, enumerable: true
|
||||
},
|
||||
|
||||
getPref: function(aName, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
cachePref: { value:
|
||||
function(aName, aValue, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
|
||||
if (this._prefCache[aGroup] && this._prefCache[aGroup].hasOwnProperty(aName)) {
|
||||
let value = this._prefCache[aGroup][aName];
|
||||
return [true, value];
|
||||
}
|
||||
return [false, undefined];
|
||||
},
|
||||
|
||||
setPref: function(aName, aValue, aGroup) {
|
||||
if (typeof aValue == "boolean")
|
||||
aValue = aValue ? 1 : 0;
|
||||
else if (aValue === undefined)
|
||||
aValue = null;
|
||||
|
||||
this.cachePref(aName, aValue, aGroup);
|
||||
},
|
||||
|
||||
removePref: function(aName, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
|
||||
if (this._prefCache[aGroup].hasOwnProperty(aName)) {
|
||||
delete this._prefCache[aGroup][aName];
|
||||
if (Object.keys(this._prefCache[aGroup]).length == 0) {
|
||||
// remove empty group
|
||||
delete this._prefCache[aGroup];
|
||||
if (!this._prefCache[aGroup]) {
|
||||
this._possiblyCleanCache();
|
||||
this._prefCache[aGroup] = {};
|
||||
}
|
||||
}
|
||||
|
||||
this._prefCache[aGroup][aName] = aValue;
|
||||
},
|
||||
},
|
||||
|
||||
invalidate: function() {
|
||||
this._prefCache = {};
|
||||
},
|
||||
_possiblyCleanCache: { value:
|
||||
function() {
|
||||
let groupCount = Object.keys(this._prefCache).length;
|
||||
|
||||
_possiblyCleanCache: function() {
|
||||
let groupCount = Object.keys(this._prefCache).length;
|
||||
if (groupCount >= CACHE_MAX_GROUP_ENTRIES) {
|
||||
// Clean half of the entries
|
||||
for (let entry in this._prefCache) {
|
||||
delete this._prefCache[entry];
|
||||
groupCount--;
|
||||
|
||||
if (groupCount >= CACHE_MAX_GROUP_ENTRIES) {
|
||||
// Clean half of the entries
|
||||
for (let entry in this._prefCache) {
|
||||
delete this._prefCache[entry];
|
||||
groupCount--;
|
||||
|
||||
if (groupCount < CACHE_MAX_GROUP_ENTRIES / 2)
|
||||
break;
|
||||
if (groupCount < CACHE_MAX_GROUP_ENTRIES / 2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
//**************************************************************************//
|
||||
// Private mode storage
|
||||
_privModeStorage: Object.create(inMemoryPrefsProto, {
|
||||
_prefCache: {
|
||||
value: {}, configurable: true, writable: true, enumerable: true
|
||||
},
|
||||
|
||||
cachePref: { value:
|
||||
function(aName, aValue, aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
|
||||
if (!this._prefCache[aGroup]) {
|
||||
this._prefCache[aGroup] = {};
|
||||
}
|
||||
|
||||
this._prefCache[aGroup][aName] = aValue;
|
||||
}
|
||||
},
|
||||
|
||||
getPrefs: { value:
|
||||
function(aGroup) {
|
||||
aGroup = aGroup || "__GlobalPrefs__";
|
||||
if (this._prefCache[aGroup]) {
|
||||
return [true, this._prefCache[aGroup]];
|
||||
}
|
||||
return [false, undefined];
|
||||
}
|
||||
},
|
||||
|
||||
groupsForName: { value:
|
||||
function(aName) {
|
||||
var res = [];
|
||||
for (let entry in this._prefCache) {
|
||||
if (this._prefCache[entry]) {
|
||||
if (entry === "__GlobalPrefs__") {
|
||||
entry = null;
|
||||
}
|
||||
res.push(entry);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
//**************************************************************************//
|
||||
// nsIContentPrefService
|
||||
@ -292,6 +375,20 @@ ContentPrefService.prototype = {
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
var group = this._parseGroupParam(aGroup);
|
||||
|
||||
if (this._inPrivateBrowsing) {
|
||||
let [haspref, value] = this._privModeStorage.getPref(aName, group);
|
||||
if (haspref) {
|
||||
if (aCallback) {
|
||||
this._scheduleCallback(function(){aCallback.onResult(value);});
|
||||
return;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
// if we don't have a pref specific to this private mode browsing
|
||||
// session, to try to get one from normal mode
|
||||
}
|
||||
|
||||
if (group == null)
|
||||
return this._selectGlobalPref(aName, aCallback);
|
||||
return this._selectPref(group, aName, aCallback);
|
||||
@ -304,20 +401,16 @@ ContentPrefService.prototype = {
|
||||
if (currentValue == aValue)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// If we are in private browsing mode, refuse to set new prefs
|
||||
var inPrivateBrowsing = false;
|
||||
try { // The Private Browsing service might not be available.
|
||||
var pbs = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
inPrivateBrowsing = pbs.privateBrowsingEnabled;
|
||||
} catch (e) {}
|
||||
if (inPrivateBrowsing)
|
||||
return;
|
||||
|
||||
var group = this._parseGroupParam(aGroup);
|
||||
|
||||
if (this._inPrivateBrowsing) {
|
||||
this._privModeStorage.setPref(aName, aValue, group);
|
||||
this._notifyPrefSet(group, aName, aValue);
|
||||
return;
|
||||
}
|
||||
|
||||
var settingID = this._selectSettingID(aName) || this._insertSetting(aName);
|
||||
var group = this._parseGroupParam(aGroup);
|
||||
var groupID, prefID;
|
||||
if (group == null) {
|
||||
groupID = null;
|
||||
@ -335,14 +428,8 @@ ContentPrefService.prototype = {
|
||||
this._insertPref(groupID, settingID, aValue);
|
||||
|
||||
this._cache.setPref(aName, aValue, group);
|
||||
for each (var observer in this._getObservers(aName)) {
|
||||
try {
|
||||
observer.onContentPrefSet(group, aName, aValue);
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
this._notifyPrefSet(group, aName, aValue);
|
||||
},
|
||||
|
||||
hasPref: function ContentPrefService_hasPref(aGroup, aName) {
|
||||
@ -357,7 +444,8 @@ ContentPrefService.prototype = {
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
let group = this._parseGroupParam(aGroup);
|
||||
let [cached,] = this._cache.getPref(aName, group);
|
||||
let storage = this._inPrivateBrowsing? this._privModeStorage: this._cache;
|
||||
let [cached,] = storage.getPref(aName, group);
|
||||
return cached;
|
||||
},
|
||||
|
||||
@ -366,9 +454,15 @@ ContentPrefService.prototype = {
|
||||
if (!this.hasPref(aGroup, aName))
|
||||
return;
|
||||
|
||||
var group = this._parseGroupParam(aGroup);
|
||||
|
||||
if (this._inPrivateBrowsing) {
|
||||
this._privModeStorage.removePref(aName, group);
|
||||
this._notifyPrefRemoved(group, aName);
|
||||
return;
|
||||
}
|
||||
|
||||
var settingID = this._selectSettingID(aName);
|
||||
var group = this._parseGroupParam(aGroup);
|
||||
var groupID, prefID;
|
||||
if (group == null) {
|
||||
groupID = null;
|
||||
@ -391,7 +485,12 @@ ContentPrefService.prototype = {
|
||||
},
|
||||
|
||||
removeGroupedPrefs: function ContentPrefService_removeGroupedPrefs() {
|
||||
this._cache.invalidate();
|
||||
// will not delete global preferences
|
||||
if (this._inPrivateBrowsing) {
|
||||
// keep only global prefs
|
||||
this._privModeStorage.invalidate(true);
|
||||
}
|
||||
this._cache.invalidate(true);
|
||||
this._dbConnection.beginTransaction();
|
||||
try {
|
||||
this._dbConnection.executeSimpleSQL("DELETE FROM prefs WHERE groupID IS NOT NULL");
|
||||
@ -413,6 +512,15 @@ ContentPrefService.prototype = {
|
||||
throw Components.Exception("aName cannot be null or an empty string",
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
if (this._inPrivateBrowsing) {
|
||||
let groupNames = this._privModeStorage.groupsForName(aName);
|
||||
for (var i = 0; i < groupNames.length; i++) {
|
||||
let groupName = groupNames[i];
|
||||
this._privModeStorage.removePref(aName, groupName);
|
||||
this._notifyPrefRemoved(groupName, aName);
|
||||
}
|
||||
}
|
||||
|
||||
var settingID = this._selectSettingID(aName);
|
||||
if (!settingID)
|
||||
return;
|
||||
@ -447,14 +555,28 @@ ContentPrefService.prototype = {
|
||||
|
||||
for (var i = 0; i < groupNames.length; i++) {
|
||||
this._cache.removePref(aName, groupNames[i]);
|
||||
this._notifyPrefRemoved(groupNames[i], aName);
|
||||
if (groupNames[i]) // ie. not null, which will be last (and i == groupIDs.length)
|
||||
this._deleteGroupIfUnused(groupIDs[i]);
|
||||
if (!this._inPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(groupNames[i], aName);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getPrefs: function ContentPrefService_getPrefs(aGroup) {
|
||||
var group = this._parseGroupParam(aGroup);
|
||||
if (this._inPrivateBrowsing) {
|
||||
let prefs = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
let [hasbranch,properties] = this._privModeStorage.getPrefs(group);
|
||||
for (let entry in properties) {
|
||||
if (properties.hasOwnProperty(entry)) {
|
||||
prefs.setProperty(entry, properties[entry]);
|
||||
}
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
if (group == null)
|
||||
return this._selectGlobalPrefs();
|
||||
return this._selectPrefs(group);
|
||||
@ -465,9 +587,24 @@ ContentPrefService.prototype = {
|
||||
throw Components.Exception("aName cannot be null or an empty string",
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
if (this._inPrivateBrowsing) {
|
||||
let prefs = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
let groupNames = this._privModeStorage.groupsForName(aName);
|
||||
for (var i = 0; i < groupNames.length; i++) {
|
||||
let groupName = groupNames[i];
|
||||
prefs.setProperty(groupName,
|
||||
this._privModeStorage.getPref(aName, groupName)[1]);
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
return this._selectPrefsByName(aName);
|
||||
},
|
||||
|
||||
// boolean to indicate if we are in private browsing mode
|
||||
_inPrivateBrowsing: false,
|
||||
|
||||
// A hash of arrays of observers, indexed by setting name.
|
||||
_observers: {},
|
||||
|
||||
@ -530,6 +667,17 @@ ContentPrefService.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_notifyPrefSet: function ContentPrefService__notifyPrefSet(aGroup, aName, aValue) {
|
||||
for each (var observer in this._getObservers(aName)) {
|
||||
try {
|
||||
observer.onContentPrefSet(aGroup, aName, aValue);
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_grouper: null,
|
||||
get grouper() {
|
||||
if (!this._grouper)
|
||||
@ -567,7 +715,6 @@ ContentPrefService.prototype = {
|
||||
},
|
||||
|
||||
_selectPref: function ContentPrefService__selectPref(aGroup, aSetting, aCallback) {
|
||||
|
||||
let [cached, value] = this._cache.getPref(aSetting, aGroup);
|
||||
if (cached) {
|
||||
if (aCallback) {
|
||||
@ -617,7 +764,6 @@ ContentPrefService.prototype = {
|
||||
},
|
||||
|
||||
_selectGlobalPref: function ContentPrefService__selectGlobalPref(aName, aCallback) {
|
||||
|
||||
let [cached, value] = this._cache.getPref(aName, null);
|
||||
if (cached) {
|
||||
if (aCallback) {
|
||||
|
@ -83,16 +83,18 @@ function run_test() {
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA);
|
||||
// save Zoom-B
|
||||
cp.setPref(uri2, pref_name, zoomB);
|
||||
// make sure Zoom-B is not retrievable
|
||||
do_check_eq(cp.getPref(uri2, pref_name), undefined);
|
||||
// make sure Zoom-B is retrievable
|
||||
do_check_eq(cp.getPref(uri2, pref_name), zoomB);
|
||||
// update Zoom-A
|
||||
cp.setPref(uri1, pref_name, zoomA_new);
|
||||
// make sure Zoom-A has changed
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA_new);
|
||||
// exit private browsing mode
|
||||
pb.privateBrowsingEnabled = false;
|
||||
// make sure Zoom-A change has persisted
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA_new);
|
||||
// make sure Zoom-A change has not persisted
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA);
|
||||
// make sure Zoom-B change has not persisted
|
||||
do_check_eq(cp.hasPref(uri2, pref_name), false);
|
||||
} catch (e) {
|
||||
do_throw("Unexpected exception: " + e);
|
||||
}
|
||||
|
145
toolkit/components/contentprefs/tests/unit/test_bug679784.js
Normal file
145
toolkit/components/contentprefs/tests/unit/test_bug679784.js
Normal file
@ -0,0 +1,145 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Content Preference Service Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Arno Renevier.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
var prefObserver = {
|
||||
setCalledNum: 0,
|
||||
onContentPrefSet: function(aGroup, aName, aValue) {
|
||||
this.setCalledNum++;
|
||||
},
|
||||
removedCalledNum: 0,
|
||||
onContentPrefRemoved: function(aGroup, aName) {
|
||||
this.removedCalledNum++;
|
||||
}
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
var pbs;
|
||||
try {
|
||||
pbs = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService);
|
||||
} catch(e) {
|
||||
// Private Browsing might not be available
|
||||
return;
|
||||
}
|
||||
|
||||
Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch).
|
||||
setBoolPref("browser.privatebrowsing.keep_current_session", true);
|
||||
|
||||
var cps = Cc["@mozilla.org/content-pref/service;1"].getService(Ci.nsIContentPrefService);
|
||||
cps.removeGroupedPrefs();
|
||||
|
||||
var uri = ContentPrefTest.getURI("http://www.example.com/");
|
||||
var group = cps.grouper.group(uri);
|
||||
|
||||
// first, set a pref in normal mode
|
||||
cps.setPref(uri, "value", "foo");
|
||||
cps.setPref(null, "value-global", "foo-global");
|
||||
|
||||
var num;
|
||||
cps.addObserver("value", prefObserver);
|
||||
cps.addObserver("value-global", prefObserver);
|
||||
|
||||
pbs.privateBrowsingEnabled = true;
|
||||
|
||||
// test setPref
|
||||
num = prefObserver.setCalledNum;
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
do_check_eq(cps.hasPref(uri, "value"), true);
|
||||
do_check_eq(cps.getPref(uri, "value"), "foo-private-browsing");
|
||||
do_check_eq(prefObserver.setCalledNum, num + 1);
|
||||
|
||||
num = prefObserver.setCalledNum;
|
||||
cps.setPref(null, "value-global", "foo-private-browsing-global");
|
||||
do_check_eq(cps.hasPref(null, "value-global"), true);
|
||||
do_check_eq(cps.getPref(null, "value-global"), "foo-private-browsing-global");
|
||||
do_check_eq(prefObserver.setCalledNum, num + 1);
|
||||
|
||||
// test removePref
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.removePref(uri, "value");
|
||||
do_check_eq(cps.hasPref(uri, "value"), true);
|
||||
// fallback to non private mode value
|
||||
do_check_eq(cps.getPref(uri, "value"), "foo");
|
||||
do_check_eq(prefObserver.removedCalledNum, num + 1);
|
||||
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.removePref(null, "value-global");
|
||||
do_check_eq(cps.hasPref(null, "value-global"), true);
|
||||
// fallback to non private mode value
|
||||
do_check_eq(cps.getPref(null, "value-global"), "foo-global") ;
|
||||
do_check_eq(prefObserver.removedCalledNum, num + 1);
|
||||
|
||||
// test removeGroupedPrefs
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
cps.removeGroupedPrefs();
|
||||
do_check_eq(cps.hasPref(uri, "value"), false);
|
||||
do_check_eq(cps.getPref(uri, "value"), undefined);
|
||||
|
||||
cps.setPref(null, "value-global", "foo-private-browsing-global");
|
||||
cps.removeGroupedPrefs();
|
||||
do_check_eq(cps.hasPref(null, "value-global"), true);
|
||||
do_check_eq(cps.getPref(null, "value-global"), "foo-private-browsing-global");
|
||||
|
||||
// test removePrefsByName
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
cps.removePrefsByName("value");
|
||||
do_check_eq(cps.hasPref(uri, "value"), false);
|
||||
do_check_eq(cps.getPref(uri, "value"), undefined);
|
||||
do_check_true(prefObserver.removedCalledNum > num);
|
||||
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.setPref(null, "value-global", "foo-private-browsing");
|
||||
cps.removePrefsByName("value-global");
|
||||
do_check_eq(cps.hasPref(null, "value-global"), false);
|
||||
do_check_eq(cps.getPref(null, "value-global"), undefined);
|
||||
do_check_true(prefObserver.removedCalledNum > num);
|
||||
|
||||
// test getPrefs
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
do_check_eq(cps.getPrefs(uri).getProperty("value"), "foo-private-browsing");
|
||||
|
||||
cps.setPref(null, "value-global", "foo-private-browsing-global");
|
||||
do_check_eq(cps.getPrefs(null).getProperty("value-global"), "foo-private-browsing-global");
|
||||
|
||||
// test getPrefsByName
|
||||
do_check_eq(cps.getPrefsByName("value").getProperty(group), "foo-private-browsing");
|
||||
do_check_eq(cps.getPrefsByName("value-global").getProperty(null), "foo-private-browsing-global");
|
||||
|
||||
cps.removeObserver("value", prefObserver);
|
||||
cps.removeObserver("value-global", prefObserver);
|
||||
}
|
@ -4,6 +4,7 @@ tail = tail_contentPrefs.js
|
||||
|
||||
[test_bug248970.js]
|
||||
[test_bug503971.js]
|
||||
[test_bug679784.js]
|
||||
[test_contentPrefs.js]
|
||||
[test_contentPrefsCache.js]
|
||||
[test_getPrefAsync.js]
|
||||
|
Loading…
Reference in New Issue
Block a user