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:
arno renevier 2011-09-01 14:13:03 -04:00
parent 09c28c4a99
commit 46c2f6aa69
7 changed files with 380 additions and 171 deletions

View File

@ -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));

View File

@ -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)

View File

@ -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,

View File

@ -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) {

View File

@ -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);
}

View 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);
}

View File

@ -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]