Bug 829456 - Update browser-fullZoom.js to use nsIContentPrefService2. r=mak

This commit is contained in:
Drew Willcoxon 2013-03-16 15:12:31 -07:00
parent 49ca796bf5
commit b894dca194
18 changed files with 703 additions and 577 deletions

View File

@ -10,15 +10,6 @@
// From nsEventStateManager.cpp.
const MOUSE_SCROLL_ZOOM = 3;
Cu.import('resource://gre/modules/ContentPrefInstance.jsm');
function getContentPrefs(aWindow) {
let context = aWindow ? aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext) : null;
return new ContentPrefInstance(context);
}
/**
* Controls the "full zoom" setting and its site-specific preferences.
*/
@ -26,17 +17,6 @@ var FullZoom = {
// Identifies the setting in the content prefs database.
name: "browser.content.full-zoom",
// The global value (if any) for the setting. Lazily loaded from the service
// when first requested, then updated by the pref change listener as it changes.
// If there is no global value, then this should be undefined.
get globalValue() {
var globalValue = getContentPrefs(gBrowser.contentDocument.defaultView).getPref(null, this.name);
if (typeof globalValue != "undefined")
globalValue = this._ensureValid(globalValue);
delete this.globalValue;
return this.globalValue = globalValue;
},
// browser.zoom.siteSpecific preference cache
_siteSpecificPref: undefined,
@ -64,7 +44,9 @@ var FullZoom = {
window.addEventListener("DOMMouseScroll", this, false);
// Register ourselves with the service so we know when our pref changes.
getContentPrefs().addObserver(this.name, this);
this._cps2 = Cc["@mozilla.org/content-pref/service;1"].
getService(Ci.nsIContentPrefService2);
this._cps2.addObserverForName(this.name, this);
this._siteSpecificPref =
gPrefService.getBoolPref("browser.zoom.siteSpecific");
@ -77,7 +59,7 @@ var FullZoom = {
destroy: function FullZoom_destroy() {
gPrefService.removeObserver("browser.zoom.", this);
getContentPrefs().removeObserver(this.name, this);
this._cps2.removeObserverForName(this.name, this);
window.removeEventListener("DOMMouseScroll", this, false);
},
@ -133,7 +115,14 @@ var FullZoom = {
// We have to call _applySettingToPref in a timeout because we handle
// the event before the event state manager has a chance to apply the zoom
// during nsEventStateManager::PostHandleEvent.
window.setTimeout(function (self) { self._applySettingToPref() }, 0, this);
//
// Since the zoom will have already been updated by the time
// _applySettingToPref is called, pass true to suppress updating the zoom
// again. Note that this is not an optimization: due to asynchronicity of
// the content preference service, the zoom may have been updated again by
// the time that onContentPrefSet is called as a result of this call to
// _applySettingToPref.
window.setTimeout(function (self) self._applySettingToPref(true), 0, this);
},
// nsIObserver
@ -158,33 +147,53 @@ var FullZoom = {
// nsIContentPrefObserver
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
if (aGroup == contentPrefs.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting(aValue);
else if (aGroup == null) {
this.globalValue = this._ensureValid(aValue);
// If the current page doesn't have a site-specific preference,
// then its zoom should be set to the new global preference now that
// the global preference has changed.
if (!contentPrefs.hasPref(gBrowser.currentURI, this.name))
this._applyPrefToSetting();
if (this._ignoreNextOnContentPrefSet) {
delete this._ignoreNextOnContentPrefSet;
return;
}
this._onContentPrefChanged(aGroup, aValue);
},
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
if (aGroup == contentPrefs.grouper.group(gBrowser.currentURI))
this._applyPrefToSetting();
else if (aGroup == null) {
this.globalValue = undefined;
this._onContentPrefChanged(aGroup, undefined);
},
// If the current page doesn't have a site-specific preference,
// then its zoom should be set to the default preference now that
// the global preference has changed.
if (!contentPrefs.hasPref(gBrowser.currentURI, this.name))
this._applyPrefToSetting();
/**
* Appropriately updates the zoom level after a content preference has
* changed.
*
* @param aGroup The group of the changed preference.
* @param aValue The new value of the changed preference. Pass undefined to
* indicate the preference's removal.
*/
_onContentPrefChanged: function FullZoom__onContentPrefChanged(aGroup, aValue) {
if (!gBrowser.currentURI)
return;
let domain = this._cps2.extractDomain(gBrowser.currentURI.spec);
if (aGroup) {
if (aGroup == domain)
this._applyPrefToSetting(aValue);
return;
}
this._globalValue = aValue === undefined ? aValue :
this._ensureValid(aValue);
// If the current page doesn't have a site-specific preference, then its
// zoom should be set to the new global preference now that the global
// preference has changed.
let hasPref = false;
let ctxt = this._loadContextFromWindow(gBrowser.contentWindow);
this._cps2.getByDomainAndName(gBrowser.currentURI.spec, this.name, ctxt, {
handleResult: function () hasPref = true,
handleCompletion: function () {
if (!hasPref &&
gBrowser.currentURI &&
this._cps2.extractDomain(gBrowser.currentURI.spec) == domain)
this._applyPrefToSetting();
}.bind(this)
});
},
// location change observer
@ -201,12 +210,16 @@ var FullZoom = {
* (optional) browser object displaying the document
*/
onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) {
if (!aURI || (aIsTabSwitch && !this.siteSpecific))
if (!aURI || (aIsTabSwitch && !this.siteSpecific)) {
this._notifyOnLocationChange();
return;
}
// Avoid the cps roundtrip and apply the default/global pref.
if (aURI.spec == "about:blank") {
this._applyPrefToSetting(undefined, aBrowser);
this._applyPrefToSetting(undefined, aBrowser, function () {
this._notifyOnLocationChange();
}.bind(this));
return;
}
@ -215,24 +228,32 @@ var FullZoom = {
// Media documents should always start at 1, and are not affected by prefs.
if (!aIsTabSwitch && browser.contentDocument.mozSyntheticDocument) {
ZoomManager.setZoomForBrowser(browser, 1);
this._notifyOnLocationChange();
return;
}
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
if (contentPrefs.hasCachedPref(aURI, this.name)) {
let zoomValue = contentPrefs.getPref(aURI, this.name);
this._applyPrefToSetting(zoomValue, browser);
} else {
var self = this;
contentPrefs.getPref(aURI, this.name, function (aResult) {
// Check that we're still where we expect to be in case this took a while.
// Null check currentURI, since the window may have been destroyed before
// we were called.
if (browser.currentURI && aURI.equals(browser.currentURI)) {
self._applyPrefToSetting(aResult, browser);
let ctxt = this._loadContextFromWindow(browser.contentWindow);
let pref = this._cps2.getCachedByDomainAndName(aURI.spec, this.name, ctxt);
if (pref) {
this._applyPrefToSetting(pref.value, browser, function () {
this._notifyOnLocationChange();
}.bind(this));
return;
}
let value = undefined;
this._cps2.getByDomainAndName(aURI.spec, this.name, ctxt, {
handleResult: function (resultPref) value = resultPref.value,
handleCompletion: function () {
if (browser.currentURI &&
this._cps2.extractDomain(browser.currentURI.spec) ==
this._cps2.extractDomain(aURI.spec)) {
this._applyPrefToSetting(value, browser, function () {
this._notifyOnLocationChange();
}.bind(this));
}
}.bind(this)
});
}
},
// update state of zoom type menu item
@ -246,23 +267,43 @@ var FullZoom = {
//**************************************************************************//
// Setting & Pref Manipulation
reduce: function FullZoom_reduce() {
/**
* Reduces the zoom level of the page in the current browser.
*
* @param callback Optional. If given, it's asynchronously called when the
* zoom update completes.
*/
reduce: function FullZoom_reduce(callback) {
ZoomManager.reduce();
this._applySettingToPref();
this._applySettingToPref(false, callback);
},
enlarge: function FullZoom_enlarge() {
/**
* Enlarges the zoom level of the page in the current browser.
*
* @param callback Optional. If given, it's asynchronously called when the
* zoom update completes.
*/
enlarge: function FullZoom_enlarge(callback) {
ZoomManager.enlarge();
this._applySettingToPref();
this._applySettingToPref(false, callback);
},
reset: function FullZoom_reset() {
if (typeof this.globalValue != "undefined")
ZoomManager.zoom = this.globalValue;
else
/**
* Sets the zoom level of the page in the current browser to the global zoom
* level.
*
* @param callback Optional. If given, it's asynchronously called when the
* zoom update completes.
*/
reset: function FullZoom_reset(callback) {
this._getGlobalValue(gBrowser.contentWindow, function (value) {
if (value === undefined)
ZoomManager.reset();
this._removePref();
else
ZoomManager.zoom = value;
this._removePref(callback);
});
},
/**
@ -283,38 +324,91 @@ var FullZoom = {
* So when we apply new zoom values to the browser, we simply set the zoom.
* We don't check first to see if the new value is the same as the current
* one.
**/
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
if ((!this.siteSpecific) || gInPrintPreviewMode)
*
* @param aValue The zoom level value.
* @param aBrowser The browser containing the page whose zoom level is to be
* set. If falsey, the currently selected browser is used.
* @param aCallback Optional. If given, it's asynchronously called when
* complete.
*/
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser, aCallback) {
if (!this.siteSpecific || gInPrintPreviewMode) {
this._executeSoon(aCallback);
return;
}
var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
try {
if (browser.contentDocument.mozSyntheticDocument)
if (browser.contentDocument.mozSyntheticDocument) {
this._executeSoon(aCallback);
return;
if (typeof aValue != "undefined")
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
else if (typeof this.globalValue != "undefined")
ZoomManager.setZoomForBrowser(browser, this.globalValue);
else
ZoomManager.setZoomForBrowser(browser, 1);
}
catch(ex) {}
},
_applySettingToPref: function FullZoom__applySettingToPref() {
if (!this.siteSpecific || gInPrintPreviewMode ||
content.document.mozSyntheticDocument)
if (aValue !== undefined) {
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
this._executeSoon(aCallback);
return;
}
var zoomLevel = ZoomManager.zoom;
getContentPrefs(gBrowser.contentDocument.defaultView).setPref(gBrowser.currentURI, this.name, zoomLevel);
this._getGlobalValue(browser.contentWindow, function (value) {
if (gBrowser.selectedBrowser == browser)
ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value);
this._executeSoon(aCallback);
});
},
_removePref: function FullZoom__removePref() {
if (!(content.document.mozSyntheticDocument))
getContentPrefs(gBrowser.contentDocument.defaultView).removePref(gBrowser.currentURI, this.name);
/**
* Saves the zoom level of the page in the current browser to the content
* prefs store.
*
* @param suppressZoomChange Because this method sets a content preference,
* our onContentPrefSet method is called as a
* result, which updates the current zoom level.
* If suppressZoomChange is true, then the next
* call to onContentPrefSet will not update the
* zoom level.
* @param callback Optional. If given, it's asynchronously called
* when done.
*/
_applySettingToPref: function FullZoom__applySettingToPref(suppressZoomChange, callback) {
if (!this.siteSpecific ||
gInPrintPreviewMode ||
content.document.mozSyntheticDocument) {
this._executeSoon(callback);
return;
}
this._cps2.set(gBrowser.currentURI.spec, this.name, ZoomManager.zoom,
this._loadContextFromWindow(gBrowser.contentWindow), {
handleCompletion: function () {
if (suppressZoomChange)
// The content preference service calls observers after callbacks, and
// it calls both in the same turn of the event loop. onContentPrefSet
// will therefore be called next, in the same turn of the event loop,
// and it will check this flag.
this._ignoreNextOnContentPrefSet = true;
if (callback)
callback();
}.bind(this)
});
},
/**
* Removes from the content prefs store the zoom level of the current browser.
*
* @param callback Optional. If given, it's asynchronously called when done.
*/
_removePref: function FullZoom__removePref(callback) {
if (content.document.mozSyntheticDocument) {
this._executeSoon(callback);
return;
}
let ctxt = this._loadContextFromWindow(gBrowser.contentWindow);
this._cps2.removeByDomainAndName(gBrowser.currentURI.spec, this.name, ctxt, {
handleCompletion: function () {
if (callback)
callback();
}
});
},
@ -322,6 +416,8 @@ var FullZoom = {
// Utilities
_ensureValid: function FullZoom__ensureValid(aValue) {
// Note that undefined is a valid value for aValue that indicates a known-
// not-to-exist value.
if (isNaN(aValue))
return 1;
@ -332,5 +428,68 @@ var FullZoom = {
return ZoomManager.MAX;
return aValue;
},
/**
* Gets the global browser.content.full-zoom content preference.
*
* WARNING: callback may be called synchronously or asynchronously. The
* reason is that it's usually desirable to avoid turns of the event loop
* where possible, since they can lead to visible, jarring jumps in zoom
* level. It's not always possible to avoid them, though. As a convenience,
* then, this method takes a callback and returns nothing.
*
* @param window The content window pertaining to the zoom.
* @param callback Synchronously or asynchronously called when done. It's
* bound to this object (FullZoom) and passed the preference
* value.
*/
_getGlobalValue: function FullZoom__getGlobalValue(window, callback) {
// * !("_globalValue" in this) => global value not yet cached.
// * this._globalValue === undefined => global value known not to exist.
// * Otherwise, this._globalValue is a number, the global value.
if ("_globalValue" in this) {
callback.call(this, this._globalValue);
return;
}
let value = undefined;
this._cps2.getGlobal(this.name, this._loadContextFromWindow(window), {
handleResult: function (pref) value = pref.value,
handleCompletion: function () {
this._globalValue = this._ensureValid(value);
callback.call(this, this._globalValue);
}.bind(this)
});
},
/**
* Gets the load context from the given window.
*
* @param window The window whose load context will be returned.
* @return The nsILoadContext of the given window.
*/
_loadContextFromWindow: function FullZoom__loadContextFromWindow(window) {
return window.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsILoadContext);
},
/**
* Asynchronously broadcasts a "browser-fullZoom:locationChange" notification
* so that tests can select tabs, load pages, etc. and be notified when the
* zoom levels on those pages change. The notification is always asynchronous
* so that observers are guaranteed a consistent behavior.
*/
_notifyOnLocationChange: function FullZoom__notifyOnLocationChange() {
this._executeSoon(function () {
Services.obs.notifyObservers(null, "browser-fullZoom:locationChange", "");
});
},
_executeSoon: function FullZoom__executeSoon(callback) {
if (!callback)
return;
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
},
};

View File

@ -8,136 +8,82 @@ const FORWARD = 1;
function test() {
waitForExplicitFinish();
Task.spawn(function () {
gTab1 = gBrowser.addTab(gTestPage);
gTab2 = gBrowser.addTab();
gTab3 = gBrowser.addTab();
gBrowser.selectedTab = gTab1;
load(gTab1, gTestPage, function () {
load(gTab2, gTestPage, secondPageLoaded);
});
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1);
yield FullZoomHelper.load(gTab1, gTestPage);
yield FullZoomHelper.load(gTab2, gTestPage);
}).then(secondPageLoaded, FullZoomHelper.failAndContinue(finish));
}
function secondPageLoaded() {
zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1");
zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1");
zoomTest(gTab3, 1, "Initial zoom of tab 3 should be 1");
Task.spawn(function () {
FullZoomHelper.zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1");
FullZoomHelper.zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1");
FullZoomHelper.zoomTest(gTab3, 1, "Initial zoom of tab 3 should be 1");
// Now have three tabs, two with the test page, one blank. Tab 1 is selected
// Zoom tab 1
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
gLevel = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1));
ok(gLevel > 1, "New zoom for tab 1 should be greater than 1");
zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2");
zoomTest(gTab3, 1, "Zooming tab 1 should not affect tab 3");
FullZoomHelper.zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2");
FullZoomHelper.zoomTest(gTab3, 1, "Zooming tab 1 should not affect tab 3");
load(gTab3, gTestPage, thirdPageLoaded);
yield FullZoomHelper.load(gTab3, gTestPage);
}).then(thirdPageLoaded, FullZoomHelper.failAndContinue(finish));
}
function thirdPageLoaded() {
zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
zoomTest(gTab2, 1, "Tab 2 should still not be affected");
zoomTest(gTab3, gLevel, "Tab 3 should have zoomed as it was loading in the background");
Task.spawn(function () {
FullZoomHelper.zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
FullZoomHelper.zoomTest(gTab2, 1, "Tab 2 should still not be affected");
FullZoomHelper.zoomTest(gTab3, gLevel, "Tab 3 should have zoomed as it was loading in the background");
// Switching to tab 2 should update its zoom setting.
afterZoom(function() {
zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
zoomTest(gTab2, gLevel, "Tab 2 should be zoomed now");
zoomTest(gTab3, gLevel, "Tab 3 should still be zoomed");
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2);
FullZoomHelper.zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
FullZoomHelper.zoomTest(gTab2, gLevel, "Tab 2 should be zoomed now");
FullZoomHelper.zoomTest(gTab3, gLevel, "Tab 3 should still be zoomed");
load(gTab1, gTestImage, imageLoaded);
});
gBrowser.selectedTab = gTab2;
yield FullZoomHelper.load(gTab1, gTestImage);
}).then(imageLoaded, FullZoomHelper.failAndContinue(finish));
}
function imageLoaded() {
zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background");
gBrowser.selectedTab = gTab1;
zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
executeSoon(imageZoomSwitch);
Task.spawn(function () {
FullZoomHelper.zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background");
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1);
FullZoomHelper.zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
}).then(imageZoomSwitch, FullZoomHelper.failAndContinue(finish));
}
function imageZoomSwitch() {
navigate(BACK, function () {
navigate(FORWARD, function () {
zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads");
Task.spawn(function () {
yield FullZoomHelper.navigate(BACK);
yield FullZoomHelper.navigate(FORWARD);
FullZoomHelper.zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads");
afterZoom(function() {
zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
finishTest();
});
gBrowser.selectedTab = gTab2;
});
});
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2);
FullZoomHelper.zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
}).then(finishTest, FullZoomHelper.failAndContinue(finish));
}
var finishTestStarted = false;
function finishTest() {
Task.spawn(function () {
ok(!finishTestStarted, "finishTest called more than once");
finishTestStarted = true;
gBrowser.selectedTab = gTab1;
FullZoom.reset();
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1);
yield FullZoomHelper.reset();
gBrowser.removeTab(gTab1);
FullZoom.reset();
yield FullZoomHelper.reset();
gBrowser.removeTab(gTab2);
FullZoom.reset();
yield FullZoomHelper.reset();
gBrowser.removeTab(gTab3);
finish();
}
function zoomTest(tab, val, msg) {
is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
}
function load(tab, url, cb) {
let didLoad = false;
let didZoom = false;
tab.linkedBrowser.addEventListener("load", function (event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
didLoad = true;
if (didZoom)
executeSoon(cb);
}, true);
afterZoom(function() {
didZoom = true;
if (didLoad)
executeSoon(cb);
});
tab.linkedBrowser.loadURI(url);
}
function navigate(direction, cb) {
let didPs = false;
let didZoom = false;
gBrowser.addEventListener("pageshow", function (event) {
gBrowser.removeEventListener("pageshow", arguments.callee, true);
didPs = true;
if (didZoom)
executeSoon(cb);
}, true);
afterZoom(function() {
didZoom = true;
if (didPs)
executeSoon(cb);
});
if (direction == BACK)
gBrowser.goBack();
else if (direction == FORWARD)
gBrowser.goForward();
}
function afterZoom(cb) {
let oldSZFB = ZoomManager.setZoomForBrowser;
ZoomManager.setZoomForBrowser = function(browser, value) {
oldSZFB.call(ZoomManager, browser, value);
ZoomManager.setZoomForBrowser = oldSZFB;
executeSoon(cb);
};
}).then(finish, FullZoomHelper.failAndContinue(finish));
}

View File

@ -1,62 +1,42 @@
var tabElm, zoomLevel;
function start_test_prefNotSet() {
Task.spawn(function () {
is(ZoomManager.zoom, 1, "initial zoom level should be 1");
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
//capture the zoom level to test later
zoomLevel = ZoomManager.zoom;
isnot(zoomLevel, 1, "zoom level should have changed");
afterZoomAndLoad(continue_test_prefNotSet);
content.location =
"http://mochi.test:8888/browser/browser/base/content/test/moz.png";
yield FullZoomHelper.load(gBrowser.selectedTab, "http://mochi.test:8888/browser/browser/base/content/test/moz.png");
}).then(continue_test_prefNotSet, FullZoomHelper.failAndContinue(finish));
}
function continue_test_prefNotSet () {
Task.spawn(function () {
is(ZoomManager.zoom, 1, "zoom level pref should not apply to an image");
FullZoom.reset();
yield FullZoomHelper.reset();
afterZoomAndLoad(end_test_prefNotSet);
content.location =
"http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html";
yield FullZoomHelper.load(gBrowser.selectedTab, "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html");
}).then(end_test_prefNotSet, FullZoomHelper.failAndContinue(finish));
}
function end_test_prefNotSet() {
Task.spawn(function () {
is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted");
// Reset the zoom so that other tests have a fresh zoom level
FullZoom.reset();
yield FullZoomHelper.reset();
gBrowser.removeCurrentTab();
finish();
}).then(finish, FullZoomHelper.failAndContinue(finish));
}
function test() {
waitForExplicitFinish();
Task.spawn(function () {
tabElm = gBrowser.addTab();
gBrowser.selectedTab = tabElm;
afterZoomAndLoad(start_test_prefNotSet);
content.location =
"http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html";
}
function afterZoomAndLoad(cb) {
let didLoad = false;
let didZoom = false;
tabElm.linkedBrowser.addEventListener("load", function() {
tabElm.linkedBrowser.removeEventListener("load", arguments.callee, true);
didLoad = true;
if (didZoom)
executeSoon(cb);
}, true);
let oldSZFB = ZoomManager.setZoomForBrowser;
ZoomManager.setZoomForBrowser = function(browser, value) {
oldSZFB.call(ZoomManager, browser, value);
ZoomManager.setZoomForBrowser = oldSZFB;
didZoom = true;
if (didLoad)
executeSoon(cb);
};
yield FullZoomHelper.selectTabAndWaitForLocationChange(tabElm);
yield FullZoomHelper.load(tabElm, "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html");
}).then(start_test_prefNotSet, FullZoomHelper.failAndContinue(finish));
}

View File

@ -1,24 +1,24 @@
function test() {
waitForExplicitFinish();
Task.spawn(function () {
let testPage = "http://example.org/browser/browser/base/content/test/dummy_page.html";
let tab1 = gBrowser.selectedTab = gBrowser.addTab();
tab1.linkedBrowser.addEventListener("load", (function(event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
let tab1 = gBrowser.addTab();
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
yield FullZoomHelper.load(tab1, testPage);
let tab2 = gBrowser.addTab();
tab2.linkedBrowser.addEventListener("load", (function(event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
yield FullZoomHelper.load(tab2, testPage);
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
let tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
afterZoom(function() {
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
let tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
is(tab2Zoom, tab1Zoom, "Zoom should affect background tabs");
gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false);
FullZoom.reset();
yield FullZoomHelper.reset();
gBrowser.selectedTab = tab1;
tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
@ -28,22 +28,5 @@ function test() {
gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
finish();
});
gBrowser.selectedTab = tab2;
}), true);
tab2.linkedBrowser.loadURI(testPage);
}), true);
content.location = testPage;
}
function afterZoom(cb) {
let oldAPTS = FullZoom._applyPrefToSetting;
FullZoom._applyPrefToSetting = function(value, browser) {
if (!value)
value = undefined;
oldAPTS.call(FullZoom, value, browser);
FullZoom._applyPrefToSetting = oldAPTS;
executeSoon(cb);
};
}).then(finish, FullZoomHelper.failAndContinue(finish));
}

View File

@ -13,19 +13,22 @@ function test() {
const TEST_PAGE_URL = 'data:text/html,<body><iframe src=""></iframe></body>';
const TEST_IFRAME_URL = "http://test2.example.org/";
Task.spawn(function () {
// Prepare the test tab
gBrowser.selectedTab = gBrowser.addTab();
let testBrowser = gBrowser.selectedBrowser;
let tab = gBrowser.addTab();
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab);
testBrowser.addEventListener("load", function () {
testBrowser.removeEventListener("load", arguments.callee, true);
let testBrowser = tab.linkedBrowser;
yield FullZoomHelper.load(tab, TEST_PAGE_URL);
// Change the zoom level and then save it so we can compare it to the level
// after loading the sub-document.
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
var zoomLevel = ZoomManager.zoom;
// Start the sub-document load.
let deferred = Promise.defer();
executeSoon(function () {
testBrowser.addEventListener("load", function (e) {
testBrowser.removeEventListener("load", arguments.callee, true);
@ -34,11 +37,10 @@ function test() {
is(ZoomManager.zoom, zoomLevel, "zoom is retained after sub-document load");
gBrowser.removeCurrentTab();
finish();
deferred.resolve();
}, true);
content.document.querySelector("iframe").src = TEST_IFRAME_URL;
});
}, true);
content.location = TEST_PAGE_URL;
yield deferred.promise;
}).then(finish, FullZoomHelper.failAndContinue(finish));
}

View File

@ -4,59 +4,36 @@
const TEST_PAGE = "/browser/browser/base/content/test/dummy_page.html";
var gTestTab, gBgTab, gTestZoom;
function afterZoomAndLoad(aCallback, aTab) {
let didLoad = false;
let didZoom = false;
aTab.linkedBrowser.addEventListener("load", function() {
aTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
didLoad = true;
if (didZoom)
executeSoon(aCallback);
}, true);
let oldAPTS = FullZoom._applyPrefToSetting;
FullZoom._applyPrefToSetting = function(value, browser) {
if (!value)
value = undefined;
oldAPTS.call(FullZoom, value, browser);
// Don't reset _applyPrefToSetting until we've seen the about:blank load(s)
if (browser && browser.currentURI.spec.startsWith("http:")) {
FullZoom._applyPrefToSetting = oldAPTS;
didZoom = true;
}
if (didLoad && didZoom)
executeSoon(aCallback);
};
}
function testBackgroundLoad() {
Task.spawn(function () {
is(ZoomManager.zoom, gTestZoom, "opening a background tab should not change foreground zoom");
gBrowser.removeTab(gBgTab);
FullZoom.reset();
yield FullZoomHelper.reset();
gBrowser.removeTab(gTestTab);
finish();
}).then(finish, FullZoomHelper.failAndContinue(finish));
}
function testInitialZoom() {
Task.spawn(function () {
is(ZoomManager.zoom, 1, "initial zoom level should be 1");
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
gTestZoom = ZoomManager.zoom;
isnot(gTestZoom, 1, "zoom level should have changed");
afterZoomAndLoad(testBackgroundLoad,
gBgTab = gBrowser.loadOneTab("http://mochi.test:8888" + TEST_PAGE,
{inBackground: true}));
gBgTab = gBrowser.addTab();
yield FullZoomHelper.load(gBgTab, "http://mochi.test:8888" + TEST_PAGE);
}).then(testBackgroundLoad, FullZoomHelper.failAndContinue(finish));
}
function test() {
waitForExplicitFinish();
Task.spawn(function () {
gTestTab = gBrowser.addTab();
gBrowser.selectedTab = gTestTab;
afterZoomAndLoad(testInitialZoom, gTestTab);
content.location = "http://example.org" + TEST_PAGE;
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTestTab);
yield FullZoomHelper.load(gTestTab, "http://example.org" + TEST_PAGE);
}).then(testInitialZoom, FullZoomHelper.failAndContinue(finish));
}

View File

@ -1,3 +1,5 @@
var tab;
function test() {
// ----------
@ -5,43 +7,27 @@ function test() {
waitForExplicitFinish();
let oldOLC = FullZoom.onLocationChange;
FullZoom.onLocationChange = function(aURI, aIsTabSwitch, aBrowser) {
// Ignore calls that are not about tab switching on this test
if (aIsTabSwitch)
oldOLC.call(FullZoom, aURI, aIsTabSwitch, aBrowser);
};
gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", true);
gPrefService.setBoolPref("browser.zoom.siteSpecific", true);
let oldAPTS = FullZoom._applyPrefToSetting;
let uri = "http://example.org/browser/browser/base/content/test/dummy_page.html";
let tab = gBrowser.addTab();
tab.linkedBrowser.addEventListener("load", function(event) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
Task.spawn(function () {
tab = gBrowser.addTab();
yield FullZoomHelper.load(tab, uri);
// -------------------------------------------------------------------
// Test - Trigger a tab switch that should update the zoom level
FullZoom._applyPrefToSetting = function() {
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab);
ok(true, "applyPrefToSetting was called");
endTest();
}
gBrowser.selectedTab = tab;
}).then(endTest, FullZoomHelper.failAndContinue(endTest));
}
}, true);
tab.linkedBrowser.loadURI(uri);
// -------------
// Test clean-up
function endTest() {
FullZoom._applyPrefToSetting = oldAPTS;
FullZoom.onLocationChange = oldOLC;
// -------------
// Test clean-up
function endTest() {
gBrowser.removeTab(tab);
oldAPTS = null;
oldOLC = null;
tab = null;
if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
@ -51,7 +37,4 @@ function test() {
gPrefService.clearUserPref("browser.zoom.siteSpecific");
finish();
}
}

View File

@ -13,25 +13,22 @@ function test() {
gBrowser.removeTab(tab2);
});
tab1 = gBrowser.addTab(TEST_IMAGE);
Task.spawn(function () {
tab1 = gBrowser.addTab();
tab2 = gBrowser.addTab();
gBrowser.selectedTab = tab1;
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
yield FullZoomHelper.load(tab1, TEST_IMAGE);
tab1.linkedBrowser.addEventListener("load", function onload() {
tab1.linkedBrowser.removeEventListener("load", onload, true);
is(ZoomManager.zoom, 1, "initial zoom level for first should be 1");
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
let zoom = ZoomManager.zoom;
isnot(zoom, 1, "zoom level should have changed");
gBrowser.selectedTab = tab2;
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
is(ZoomManager.zoom, 1, "initial zoom level for second tab should be 1");
gBrowser.selectedTab = tab1;
yield FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
is(ZoomManager.zoom, zoom, "zoom level for first tab should not have changed");
finish();
}, true);
}).then(finish, FullZoomHelper.failAndContinue(finish));
}

View File

@ -11,131 +11,71 @@ var gTab1, gTab2, gLevel1, gLevel2;
function test() {
waitForExplicitFinish();
Task.spawn(function () {
gTab1 = gBrowser.addTab();
gTab2 = gBrowser.addTab();
gBrowser.selectedTab = gTab1;
load(gTab1, TEST_PAGE, function() {
load(gTab2, TEST_VIDEO, zoomTab1);
});
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1);
yield FullZoomHelper.load(gTab1, TEST_PAGE);
yield FullZoomHelper.load(gTab2, TEST_VIDEO);
}).then(zoomTab1, FullZoomHelper.failAndContinue(finish));
}
function zoomTab1() {
Task.spawn(function () {
is(gBrowser.selectedTab, gTab1, "Tab 1 is selected");
zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1");
zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1");
FullZoomHelper.zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1");
FullZoomHelper.zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1");
FullZoom.enlarge();
yield FullZoomHelper.enlarge();
gLevel1 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1));
ok(gLevel1 > 1, "New zoom for tab 1 should be greater than 1");
zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2");
FullZoomHelper.zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2");
gBrowser.selectedTab = gTab2;
zoomTest(gTab2, 1, "Tab 2 is still unzoomed after it is selected");
zoomTest(gTab1, gLevel1, "Tab 1 is still zoomed");
zoomTab2();
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2);
FullZoomHelper.zoomTest(gTab2, 1, "Tab 2 is still unzoomed after it is selected");
FullZoomHelper.zoomTest(gTab1, gLevel1, "Tab 1 is still zoomed");
}).then(zoomTab2, FullZoomHelper.failAndContinue(finish));
}
function zoomTab2() {
Task.spawn(function () {
is(gBrowser.selectedTab, gTab2, "Tab 2 is selected");
FullZoom.reduce();
yield FullZoomHelper.reduce();
let gLevel2 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab2));
ok(gLevel2 < 1, "New zoom for tab 2 should be less than 1");
zoomTest(gTab1, gLevel1, "Zooming tab 2 should not affect tab 1");
FullZoomHelper.zoomTest(gTab1, gLevel1, "Zooming tab 2 should not affect tab 1");
afterZoom(function() {
zoomTest(gTab1, gLevel1, "Tab 1 should have the same zoom after it's selected");
testNavigation();
});
gBrowser.selectedTab = gTab1;
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1);
FullZoomHelper.zoomTest(gTab1, gLevel1, "Tab 1 should have the same zoom after it's selected");
}).then(testNavigation, FullZoomHelper.failAndContinue(finish));
}
function testNavigation() {
load(gTab1, TEST_VIDEO, function() {
zoomTest(gTab1, 1, "Zoom should be 1 when a video was loaded");
navigate(BACK, function() {
zoomTest(gTab1, gLevel1, "Zoom should be restored when a page is loaded");
navigate(FORWARD, function() {
zoomTest(gTab1, 1, "Zoom should be 1 again when navigating back to a video");
finishTest();
});
});
});
Task.spawn(function () {
yield FullZoomHelper.load(gTab1, TEST_VIDEO);
FullZoomHelper.zoomTest(gTab1, 1, "Zoom should be 1 when a video was loaded");
yield FullZoomHelper.navigate(FullZoomHelper.BACK);
FullZoomHelper.zoomTest(gTab1, gLevel1, "Zoom should be restored when a page is loaded");
yield FullZoomHelper.navigate(FullZoomHelper.FORWARD);
FullZoomHelper.zoomTest(gTab1, 1, "Zoom should be 1 again when navigating back to a video");
}).then(finishTest, FullZoomHelper.failAndContinue(finish));
}
var finishTestStarted = false;
function finishTest() {
Task.spawn(function () {
ok(!finishTestStarted, "finishTest called more than once");
finishTestStarted = true;
gBrowser.selectedTab = gTab1;
FullZoom.reset();
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1);
yield FullZoomHelper.reset();
gBrowser.removeTab(gTab1);
gBrowser.selectedTab = gTab2;
FullZoom.reset();
yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2);
yield FullZoomHelper.reset();
gBrowser.removeTab(gTab2);
finish();
}
function zoomTest(tab, val, msg) {
is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
}
function load(tab, url, cb) {
let didLoad = false;
let didZoom = false;
tab.linkedBrowser.addEventListener("load", function onload(event) {
event.currentTarget.removeEventListener("load", onload, true);
didLoad = true;
if (didZoom)
executeSoon(cb);
}, true);
afterZoom(function() {
didZoom = true;
if (didLoad)
executeSoon(cb);
});
tab.linkedBrowser.loadURI(url);
}
const BACK = 0;
const FORWARD = 1;
function navigate(direction, cb) {
let didPs = false;
let didZoom = false;
gBrowser.addEventListener("pageshow", function onpageshow(event) {
gBrowser.removeEventListener("pageshow", onpageshow, true);
didPs = true;
if (didZoom)
executeSoon(cb);
}, true);
afterZoom(function() {
didZoom = true;
if (didPs)
executeSoon(cb);
});
if (direction == BACK)
gBrowser.goBack();
else if (direction == FORWARD)
gBrowser.goForward();
}
function afterZoom(cb) {
let oldSZFB = ZoomManager.setZoomForBrowser;
ZoomManager.setZoomForBrowser = function(browser, value) {
oldSZFB.call(ZoomManager, browser, value);
ZoomManager.setZoomForBrowser = oldSZFB;
executeSoon(cb);
};
}).then(finish, FullZoomHelper.failAndContinue(finish));
}

View File

@ -261,3 +261,107 @@ function promiseHistoryClearedState(aURIs, aShouldBeCleared) {
return deferred.promise;
}
let FullZoomHelper = {
selectTabAndWaitForLocationChange: function selectTabAndWaitForLocationChange(tab) {
let deferred = Promise.defer();
if (tab && gBrowser.selectedTab == tab) {
deferred.resolve();
return deferred.promise;
}
if (tab)
gBrowser.selectedTab = tab;
Services.obs.addObserver(function obs() {
Services.obs.removeObserver(obs, "browser-fullZoom:locationChange");
deferred.resolve();
}, "browser-fullZoom:locationChange", false);
return deferred.promise;
},
load: function load(tab, url) {
let deferred = Promise.defer();
let didLoad = false;
let didZoom = false;
tab.linkedBrowser.addEventListener("load", function (event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
didLoad = true;
if (didZoom)
deferred.resolve();
}, true);
// Don't select background tabs. That way tests can use this method on
// background tabs without having them automatically be selected. Just wait
// for the zoom to change on the current tab if it's `tab`.
if (tab == gBrowser.selectedTab) {
this.selectTabAndWaitForLocationChange(null).then(function () {
didZoom = true;
if (didLoad)
deferred.resolve();
});
}
else
didZoom = true;
tab.linkedBrowser.loadURI(url);
return deferred.promise;
},
zoomTest: function zoomTest(tab, val, msg) {
is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
},
enlarge: function enlarge() {
let deferred = Promise.defer();
FullZoom.enlarge(function () deferred.resolve());
return deferred.promise;
},
reduce: function reduce() {
let deferred = Promise.defer();
FullZoom.reduce(function () deferred.resolve());
return deferred.promise;
},
reset: function reset() {
let deferred = Promise.defer();
FullZoom.reset(function () deferred.resolve());
return deferred.promise;
},
BACK: 0,
FORWARD: 1,
navigate: function navigate(direction) {
let deferred = Promise.defer();
let didPs = false;
let didZoom = false;
gBrowser.addEventListener("pageshow", function (event) {
gBrowser.removeEventListener("pageshow", arguments.callee, true);
didPs = true;
if (didZoom)
deferred.resolve();
}, true);
if (direction == this.BACK)
gBrowser.goBack();
else if (direction == this.FORWARD)
gBrowser.goForward();
this.selectTabAndWaitForLocationChange(null).then(function () {
didZoom = true;
if (didPs)
deferred.resolve();
});
return deferred.promise;
},
failAndContinue: function failAndContinue(func) {
return function (err) {
ok(false, err);
func();
};
},
};

View File

@ -25,7 +25,7 @@ function test() {
let mozillaZoom = aWindow.ZoomManager.zoom;
// change the zoom on the mozilla page
aWindow.FullZoom.enlarge();
aWindow.FullZoom.enlarge(function () {
// make sure the zoom level has been changed
isnot(aWindow.ZoomManager.zoom, mozillaZoom, "Zoom level can be changed");
mozillaZoom = aWindow.ZoomManager.zoom;
@ -41,11 +41,13 @@ function test() {
"Entering private browsing should not reset the zoom on a tab");
// cleanup
aWindow.FullZoom.reset();
aWindow.FullZoom.reset(function () {
aWindow.gBrowser.removeTab(tabMozilla);
aWindow.gBrowser.removeTab(tabAbout);
aWindow.close();
aCallback();
});
});
}, true);
mozillaBrowser.contentWindow.location = "about:mozilla";
}, true);

View File

@ -16,12 +16,14 @@ function test() {
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
if (aIsZoomedWindow) {
// change the zoom on the blank page
aWindow.FullZoom.enlarge();
aWindow.FullZoom.enlarge(function () {
isnot(aWindow.ZoomManager.zoom, 1, "Zoom level for about:blank should be changed");
} else {
aCallback();
});
return;
}
// make sure the zoom level is set to 1
is(aWindow.ZoomManager.zoom, 1, "Zoom level for about:privatebrowsing should be reset");
}
aCallback();
}, true);
@ -31,10 +33,18 @@ function test() {
function finishTest() {
// cleanup
windowsToReset.forEach(function(win) {
win.FullZoom.reset();
});
let numWindows = windowsToReset.length;
if (!numWindows) {
finish();
return;
}
windowsToReset.forEach(function(win) {
win.FullZoom.reset(function onReset() {
numWindows--;
if (!numWindows)
finish();
});
});
}
function testOnWindow(options, callback) {

View File

@ -59,11 +59,15 @@ interface nsIContentPref;
*
* Callbacks
*
* The methods of callback objects are always called asynchronously. See
* nsIContentPrefCallback2 below for more information about callbacks.
* The methods of callback objects are always called asynchronously.
*
* Observers are called after callbacks are called, but they are called in the
* same turn of the event loop as callbacks.
*
* See nsIContentPrefCallback2 below for more information about callbacks.
*/
[scriptable, uuid(51e1d34a-5e9d-4b77-b14c-0f8346e264ca)]
[scriptable, uuid(133608c7-f812-41ca-bc1c-62a4eb95e52a)]
interface nsIContentPrefService2 : nsISupports
{
/**
@ -318,6 +322,17 @@ interface nsIContentPrefService2 : nsISupports
*/
void removeObserverForName(in AString name,
in nsIContentPrefObserver observer);
/**
* Extracts and returns the domain from the given string representation of a
* URI. This is how the API extracts domains from URIs passed to it.
*
* @param str The string representation of a URI, like
* "http://example.com/foo/bar".
* @return If the given string is a valid URI, the domain of that URI is
* returned. Otherwise, the string itself is returned.
*/
AString extractDomain(in AString str);
};
/**
@ -336,7 +351,7 @@ interface nsIContentPrefCallback2 : nsISupports
/**
* Called when an error occurs. This may be called multiple times before
* onComplete is called.
* handleCompletion is called.
*
* @param error A number in Components.results describing the error.
*/

View File

@ -195,8 +195,8 @@ ContentPrefService2.prototype = {
if (context && context.usePrivateBrowsing) {
this._pbStore.set(group, name, value);
this._schedule(function () {
this._cps._broadcastPrefSet(group, name, value);
cbHandleCompletion(callback, Ci.nsIContentPrefCallback2.COMPLETE_OK);
this._cps._broadcastPrefSet(group, name, value);
});
return;
}
@ -258,11 +258,11 @@ ContentPrefService2.prototype = {
this._execStmts(stmts, {
onDone: function onDone(reason, ok) {
if (ok) {
if (ok)
this._cache.setWithCast(group, name, value);
this._cps._broadcastPrefSet(group, name, value);
}
cbHandleCompletion(callback, reason);
if (ok)
this._cps._broadcastPrefSet(group, name, value);
},
onError: function onError(nsresult) {
cbHandleError(callback, nsresult);
@ -342,11 +342,13 @@ ContentPrefService2.prototype = {
this._pbStore.remove(sgroup, name);
}
}
}
cbHandleCompletion(callback, reason);
if (ok) {
for (let [sgroup, , ] in prefs) {
this._cps._broadcastPrefRemoved(sgroup, name);
}
}
cbHandleCompletion(callback, reason);
},
onError: function onError(nsresult) {
cbHandleError(callback, nsresult);
@ -421,18 +423,18 @@ ContentPrefService2.prototype = {
this._cache.set(grp, name, undefined);
},
onDone: function onDone(reason, ok) {
if (ok) {
if (context && context.usePrivateBrowsing) {
if (ok && context && context.usePrivateBrowsing) {
for (let [sgroup, sname, ] in this._pbStore) {
prefs.set(sgroup, sname);
this._pbStore.remove(sgroup, sname);
}
}
cbHandleCompletion(callback, reason);
if (ok) {
for (let [sgroup, sname, ] in prefs) {
this._cps._broadcastPrefRemoved(sgroup, sname);
}
}
cbHandleCompletion(callback, reason);
},
onError: function onError(nsresult) {
cbHandleError(callback, nsresult);
@ -473,18 +475,18 @@ ContentPrefService2.prototype = {
this._cache.set(grp, name, undefined);
},
onDone: function onDone(reason, ok) {
if (ok) {
if (context && context.usePrivateBrowsing) {
if (ok && context && context.usePrivateBrowsing) {
for (let [sgroup, sname, ] in this._pbStore) {
prefs.set(sgroup, sname);
}
this._pbStore.removeGrouped();
}
cbHandleCompletion(callback, reason);
if (ok) {
for (let [sgroup, sname, ] in prefs) {
this._cps._broadcastPrefRemoved(sgroup, sname);
}
}
cbHandleCompletion(callback, reason);
},
onError: function onError(nsresult) {
cbHandleError(callback, nsresult);
@ -544,8 +546,7 @@ ContentPrefService2.prototype = {
this._cache.set(grp, name, undefined);
},
onDone: function onDone(reason, ok) {
if (ok) {
if (context && context.usePrivateBrowsing) {
if (ok && context && context.usePrivateBrowsing) {
for (let [sgroup, sname, ] in this._pbStore) {
if (sname === name) {
prefs.set(sgroup, name);
@ -553,11 +554,12 @@ ContentPrefService2.prototype = {
}
}
}
cbHandleCompletion(callback, reason);
if (ok) {
for (let [sgroup, , ] in prefs) {
this._cps._broadcastPrefRemoved(sgroup, name);
}
}
cbHandleCompletion(callback, reason);
},
onError: function onError(nsresult) {
cbHandleError(callback, nsresult);
@ -682,6 +684,10 @@ ContentPrefService2.prototype = {
this._cps.removeObserver(name, observer);
},
extractDomain: function CPS2_extractDomain(str) {
return this._parseGroup(str);
},
/**
* Tests use this as a backchannel by calling it directly.
*

View File

@ -273,7 +273,7 @@ function dbOK(expectedRows) {
stmt.finalize();
}
function on(event, names) {
function on(event, names, dontRemove) {
let args = {
reset: function () {
for (let prop in this) {
@ -281,9 +281,6 @@ function on(event, names) {
this[prop].splice(0, this[prop].length);
}
},
destroy: function () {
names.forEach(function (n) cps.removeObserverForName(n, observers[n]));
},
};
let observers = {};
@ -302,7 +299,15 @@ function on(event, names) {
cps.addObserverForName(name, obs);
});
return args;
do_execute_soon(function () {
if (!dontRemove)
names.forEach(function (n) cps.removeObserverForName(n, observers[n]));
next(args);
});
}
function wait() {
do_execute_soon(next);
}
function observerArgsOK(actualArgs, expectedArgs) {

View File

@ -0,0 +1,20 @@
/* 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/. */
function run_test() {
let tests = {
"http://example.com": "example.com",
"http://example.com/": "example.com",
"http://example.com/foo/bar/baz": "example.com",
"http://subdomain.example.com/foo/bar/baz": "subdomain.example.com",
"http://qix.quux.example.com/foo/bar/baz": "qix.quux.example.com",
"file:///home/foo/bar": "file:///home/foo/bar",
"not a url": "not a url",
};
let cps = Cc["@mozilla.org/content-pref/service;1"].
getService(Ci.nsIContentPrefService2);
for (let url in tests) {
do_check_eq(cps.extractDomain(url), tests[url]);
}
}

View File

@ -9,43 +9,40 @@ function run_test() {
let tests = [
function observerForName_set() {
let args = on("Set", ["foo", null, "bar"]);
yield set("a.com", "foo", 1);
let args = yield on("Set", ["foo", null, "bar"]);
observerArgsOK(args.foo, [["a.com", "foo", 1]]);
observerArgsOK(args.null, [["a.com", "foo", 1]]);
observerArgsOK(args.bar, []);
args.reset();
yield setGlobal("foo", 2);
args = yield on("Set", ["foo", null, "bar"]);
observerArgsOK(args.foo, [[null, "foo", 2]]);
observerArgsOK(args.null, [[null, "foo", 2]]);
observerArgsOK(args.bar, []);
args.reset();
},
function observerForName_remove() {
yield set("a.com", "foo", 1);
yield setGlobal("foo", 2);
let args = on("Removed", ["foo", null, "bar"]);
yield cps.removeByDomainAndName("a.com", "bogus", null, makeCallback());
let args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, []);
observerArgsOK(args.null, []);
observerArgsOK(args.bar, []);
args.reset();
yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, [["a.com", "foo"]]);
observerArgsOK(args.null, [["a.com", "foo"]]);
observerArgsOK(args.bar, []);
args.reset();
yield cps.removeGlobal("foo", null, makeCallback());
args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, [[null, "foo"]]);
observerArgsOK(args.null, [[null, "foo"]]);
observerArgsOK(args.bar, []);
args.reset();
},
function observerForName_removeByDomain() {
@ -53,24 +50,23 @@ let tests = [
yield set("b.a.com", "bar", 2);
yield setGlobal("foo", 3);
let args = on("Removed", ["foo", null, "bar"]);
yield cps.removeByDomain("bogus", null, makeCallback());
let args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, []);
observerArgsOK(args.null, []);
observerArgsOK(args.bar, []);
args.reset();
yield cps.removeBySubdomain("a.com", null, makeCallback());
args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, [["a.com", "foo"]]);
observerArgsOK(args.null, [["a.com", "foo"], ["b.a.com", "bar"]]);
observerArgsOK(args.bar, [["b.a.com", "bar"]]);
args.reset();
yield cps.removeAllGlobals(null, makeCallback());
args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, [[null, "foo"]]);
observerArgsOK(args.null, [[null, "foo"]]);
observerArgsOK(args.bar, []);
args.reset();
},
function observerForName_removeAllDomains() {
@ -78,12 +74,11 @@ let tests = [
yield setGlobal("foo", 2);
yield set("b.com", "bar", 3);
let args = on("Removed", ["foo", null, "bar"]);
yield cps.removeAllDomains(null, makeCallback());
let args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, [["a.com", "foo"]]);
observerArgsOK(args.null, [["a.com", "foo"], ["b.com", "bar"]]);
observerArgsOK(args.bar, [["b.com", "bar"]]);
args.reset();
},
function observerForName_removeByName() {
@ -91,25 +86,25 @@ let tests = [
yield set("a.com", "bar", 2);
yield setGlobal("foo", 3);
let args = on("Removed", ["foo", null, "bar"]);
yield cps.removeByName("bogus", null, makeCallback());
let args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, []);
observerArgsOK(args.null, []);
observerArgsOK(args.bar, []);
args.reset();
yield cps.removeByName("foo", null, makeCallback());
args = yield on("Removed", ["foo", null, "bar"]);
observerArgsOK(args.foo, [["a.com", "foo"], [null, "foo"]]);
observerArgsOK(args.null, [["a.com", "foo"], [null, "foo"]]);
observerArgsOK(args.bar, []);
args.reset();
},
function removeObserverForName() {
let args = on("Set", ["foo", null, "bar"]);
let args = yield on("Set", ["foo", null, "bar"], true);
cps.removeObserverForName("foo", args.foo.observer);
yield set("a.com", "foo", 1);
yield wait();
observerArgsOK(args.foo, []);
observerArgsOK(args.null, [["a.com", "foo", 1]]);
observerArgsOK(args.bar, []);
@ -117,6 +112,7 @@ let tests = [
cps.removeObserverForName(null, args.null.observer);
yield set("a.com", "foo", 2);
yield wait();
observerArgsOK(args.foo, []);
observerArgsOK(args.null, []);
observerArgsOK(args.bar, []);

View File

@ -12,3 +12,4 @@ tail =
[test_getCached.js]
[test_getCachedSubdomains.js]
[test_observers.js]
[test_extractDomain.js]