mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1590485: Add UI/UX and global zoom functionality. r=fluent-reviewers,Gijs
Differential Revision: https://phabricator.services.mozilla.com/D50845 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
b95cb66316
commit
2895fb8739
@ -180,9 +180,6 @@ var FullZoom = {
|
||||
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.
|
||||
@ -386,7 +383,7 @@ var FullZoom = {
|
||||
browser.messageManager.sendAsyncMessage("PDFJS:ZoomReset");
|
||||
}
|
||||
let token = this._getBrowserToken(browser);
|
||||
let result = this._getGlobalValue(browser).then(value => {
|
||||
let result = ZoomUI.getGlobalValue().then(value => {
|
||||
if (token.isCurrent) {
|
||||
ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value);
|
||||
this._ignorePendingZoomAccesses(browser);
|
||||
@ -445,7 +442,7 @@ var FullZoom = {
|
||||
}
|
||||
|
||||
let token = this._getBrowserToken(aBrowser);
|
||||
this._getGlobalValue(aBrowser).then(value => {
|
||||
ZoomUI.getGlobalValue().then(value => {
|
||||
if (token.isCurrent) {
|
||||
ZoomManager.setZoomForBrowser(
|
||||
aBrowser,
|
||||
@ -598,35 +595,6 @@ var FullZoom = {
|
||||
return aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the global browser.content.full-zoom content preference.
|
||||
*
|
||||
* @param browser The browser pertaining to the zoom.
|
||||
* @returns Promise<prefValue>
|
||||
* Resolves to the preference value when done.
|
||||
*/
|
||||
_getGlobalValue: function FullZoom__getGlobalValue(browser) {
|
||||
// * !("_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.
|
||||
return new Promise(resolve => {
|
||||
if ("_globalValue" in this) {
|
||||
resolve(this._globalValue);
|
||||
return;
|
||||
}
|
||||
let value = undefined;
|
||||
this._cps2.getGlobal(this.name, this._loadContextFromBrowser(browser), {
|
||||
handleResult(pref) {
|
||||
value = pref.value;
|
||||
},
|
||||
handleCompletion: reason => {
|
||||
this._globalValue = this._ensureValid(value);
|
||||
resolve(this._globalValue);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the load context from the given Browser.
|
||||
*
|
||||
|
@ -106,6 +106,9 @@ with Files("test/webextensions/**"):
|
||||
with Files("test/webrtc/**"):
|
||||
BUG_COMPONENT = ("Core", "WebRTC")
|
||||
|
||||
with Files("test/zoom/**"):
|
||||
BUG_COMPONENT = ("Firefox", "General")
|
||||
|
||||
with Files("aboutNetError.xhtml"):
|
||||
BUG_COMPONENT = ("Firefox", "Security")
|
||||
|
||||
|
@ -67,6 +67,7 @@ const startupPhases = {
|
||||
"resource://gre/modules/PlacesUtils.jsm",
|
||||
"resource://gre/modules/Promise.jsm", // imported by devtools during _delayedStartup
|
||||
"resource://gre/modules/Preferences.jsm",
|
||||
"resource://gre/modules/Sqlite.jsm",
|
||||
]),
|
||||
services: new Set(["@mozilla.org/browser/search-service;1"]),
|
||||
},
|
||||
@ -94,7 +95,6 @@ const startupPhases = {
|
||||
"resource://gre/modules/PlacesBackups.jsm",
|
||||
"resource://gre/modules/PlacesSyncUtils.jsm",
|
||||
"resource://gre/modules/PushComponents.jsm",
|
||||
"resource://gre/modules/Sqlite.jsm",
|
||||
]),
|
||||
services: new Set([
|
||||
"@mozilla.org/browser/annotation-service;1",
|
||||
|
7
browser/base/content/test/zoom/.eslintrc.js
Normal file
7
browser/base/content/test/zoom/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/browser-test"
|
||||
]
|
||||
};
|
8
browser/base/content/test/zoom/browser.ini
Normal file
8
browser/base/content/test/zoom/browser.ini
Normal file
@ -0,0 +1,8 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_default_zoom.js]
|
||||
[browser_default_zoom_multitab.js]
|
||||
[browser_default_zoom_fission.js]
|
||||
skip-if = fission # Bug 1603282
|
160
browser/base/content/test/zoom/browser_default_zoom.js
Normal file
160
browser/base/content/test/zoom/browser_default_zoom.js
Normal file
@ -0,0 +1,160 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_init_default_zoom() {
|
||||
const TEST_PAGE_URL =
|
||||
"data:text/html;charset=utf-8,<body>test_init_default_zoom</body>";
|
||||
|
||||
// Prepare the test tab
|
||||
let tab = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser = gBrowser.getBrowserForTab(tab);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab);
|
||||
await FullZoomHelper.load(tab, TEST_PAGE_URL);
|
||||
|
||||
// 100% global zoom
|
||||
let defaultZoom = await FullZoomHelper.getGlobalValue();
|
||||
is(defaultZoom, 1, "Global zoom is init at 100%");
|
||||
// 100% tab zoom
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser),
|
||||
1,
|
||||
"Current zoom is init at 100%"
|
||||
);
|
||||
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
||||
|
||||
add_task(async function test_set_default_zoom() {
|
||||
const TEST_PAGE_URL =
|
||||
"data:text/html;charset=utf-8,<body>test_set_default_zoom</body>";
|
||||
|
||||
// Prepare the test tab
|
||||
let tab = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser = gBrowser.getBrowserForTab(tab);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab);
|
||||
await FullZoomHelper.load(tab, TEST_PAGE_URL);
|
||||
|
||||
// 120% global zoom
|
||||
await FullZoomHelper.changeDefaultZoom(120);
|
||||
let defaultZoom = await FullZoomHelper.getGlobalValue();
|
||||
is(defaultZoom, 1.2, "Global zoom is at 120%");
|
||||
|
||||
// 120% tab zoom
|
||||
await TestUtils.waitForCondition(() => {
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser) == 1.2;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser),
|
||||
1.2,
|
||||
"Current zoom matches changed default zoom"
|
||||
);
|
||||
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
||||
|
||||
add_task(async function test_enlarge_reduce_reset_local_zoom() {
|
||||
const TEST_PAGE_URL =
|
||||
"data:text/html;charset=utf-8,<body>test_enlarge_reduce_reset_local_zoom</body>";
|
||||
|
||||
// Prepare the test tab
|
||||
let tab = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser = gBrowser.getBrowserForTab(tab);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab);
|
||||
await FullZoomHelper.load(tab, TEST_PAGE_URL);
|
||||
|
||||
// 120% global zoom persists from previous test
|
||||
let defaultZoom = FullZoomHelper.getGlobalValue();
|
||||
console.log("Current global zoom is ", defaultZoom);
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
await FullZoom.enlarge();
|
||||
console.log("Enlarged!");
|
||||
defaultZoom = FullZoomHelper.getGlobalValue();
|
||||
console.log("Current global zoom is ", defaultZoom);
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
|
||||
// 133% tab zoom
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser) == 1.33;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser),
|
||||
1.33,
|
||||
"Increasing zoom changes zoom of current tab."
|
||||
);
|
||||
defaultZoom = await FullZoomHelper.getGlobalValue();
|
||||
// 120% global zoom
|
||||
is(
|
||||
defaultZoom,
|
||||
1.2,
|
||||
"Increasing zoom of current tab doesn't change default zoom."
|
||||
);
|
||||
console.log("Reducing...");
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
await FullZoom.reduce(); // 120% tab zoom
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
await FullZoom.reduce(); // 110% tab zoom
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
await FullZoom.reduce(); // 100% tab zoom
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser) == 1;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser),
|
||||
1,
|
||||
"Decreasing zoom changes zoom of current tab."
|
||||
);
|
||||
defaultZoom = await FullZoomHelper.getGlobalValue();
|
||||
// 120% global zoom
|
||||
is(
|
||||
defaultZoom,
|
||||
1.2,
|
||||
"Decreasing zoom of current tab doesn't change default zoom."
|
||||
);
|
||||
console.log("Resetting...");
|
||||
FullZoom.reset(); // 120% tab zoom
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab zoom is ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser) == 1.2;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser),
|
||||
1.2,
|
||||
"Reseting zoom causes current tab to zoom to default zoom."
|
||||
);
|
||||
|
||||
// no reset necessary, it was performed as part of the test
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
102
browser/base/content/test/zoom/browser_default_zoom_fission.js
Normal file
102
browser/base/content/test/zoom/browser_default_zoom_fission.js
Normal file
@ -0,0 +1,102 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_sitespecific_iframe_global_zoom() {
|
||||
const TEST_PAGE_URL =
|
||||
'data:text/html;charset=utf-8,<body>test_sitespecific_iframe_global_zoom<iframe src=""></iframe></body>';
|
||||
const TEST_IFRAME_URL = "https://example.com/";
|
||||
|
||||
// Prepare the test tab
|
||||
let tab = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser = gBrowser.getBrowserForTab(tab);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab);
|
||||
await FullZoomHelper.load(tab, TEST_PAGE_URL);
|
||||
|
||||
// 67% global zoom
|
||||
await FullZoomHelper.changeDefaultZoom(67);
|
||||
let defaultZoom = await FullZoomHelper.getGlobalValue();
|
||||
is(defaultZoom, 0.67, "Global zoom is at 67%");
|
||||
await TestUtils.waitForCondition(
|
||||
() => ZoomManager.getZoomForBrowser(tabBrowser) == 0.67
|
||||
);
|
||||
|
||||
let zoomLevel = ZoomManager.getZoomForBrowser(tabBrowser);
|
||||
is(zoomLevel, 0.67, "tab zoom has been set to 67%");
|
||||
|
||||
let frameLoadedPromise = BrowserTestUtils.browserLoaded(
|
||||
tabBrowser,
|
||||
true,
|
||||
TEST_IFRAME_URL
|
||||
);
|
||||
SpecialPowers.spawn(tabBrowser, [TEST_IFRAME_URL], url => {
|
||||
content.document.querySelector("iframe").src = url;
|
||||
});
|
||||
let loadedURL = await frameLoadedPromise;
|
||||
is(loadedURL, TEST_IFRAME_URL, "got the load event for the iframe");
|
||||
|
||||
let frameZoom = await SpecialPowers.spawn(
|
||||
gBrowser.selectedBrowser.browsingContext.getChildren()[0],
|
||||
[],
|
||||
async () => {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return content.docShell.contentViewer.fullZoom.toFixed(2) == 0.67;
|
||||
});
|
||||
return content.docShell.contentViewer.fullZoom.toFixed(2);
|
||||
}
|
||||
);
|
||||
|
||||
is(frameZoom, zoomLevel, "global zoom is reflected in iframe");
|
||||
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
||||
|
||||
add_task(async function test_sitespecific_global_zoom_enlarge() {
|
||||
const TEST_PAGE_URL =
|
||||
'data:text/html;charset=utf-8,<body>test_sitespecific_global_zoom_enlarge<iframe src=""></iframe></body>';
|
||||
const TEST_IFRAME_URL = "https://example.org/";
|
||||
|
||||
// Prepare the test tab
|
||||
let tab = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser = gBrowser.getBrowserForTab(tab);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab);
|
||||
await FullZoomHelper.load(tab, TEST_PAGE_URL);
|
||||
|
||||
// 67% global zoom persists from previous test
|
||||
|
||||
let frameLoadedPromise = BrowserTestUtils.browserLoaded(
|
||||
tabBrowser,
|
||||
true,
|
||||
TEST_IFRAME_URL
|
||||
);
|
||||
SpecialPowers.spawn(tabBrowser, [TEST_IFRAME_URL], url => {
|
||||
content.document.querySelector("iframe").src = url;
|
||||
});
|
||||
let loadedURL = await frameLoadedPromise;
|
||||
is(loadedURL, TEST_IFRAME_URL, "got the load event for the iframe");
|
||||
await FullZoom.enlarge();
|
||||
// 80% local zoom
|
||||
await TestUtils.waitForCondition(() => {
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser) == 0.8;
|
||||
});
|
||||
is(ZoomManager.getZoomForBrowser(tabBrowser), 0.8, "Local zoom is increased");
|
||||
|
||||
let frameZoom = await SpecialPowers.spawn(
|
||||
gBrowser.selectedBrowser.browsingContext.getChildren()[0],
|
||||
[],
|
||||
async () => {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return content.docShell.contentViewer.fullZoom.toFixed(2) == 0.8;
|
||||
});
|
||||
return content.docShell.contentViewer.fullZoom.toFixed(2);
|
||||
}
|
||||
);
|
||||
|
||||
is(frameZoom, 0.8, "(without fission) iframe zoom matches page zoom");
|
||||
|
||||
// To ensure site-specific zoom settings don't persist
|
||||
// across multiple runs, we reset the tab and iframe after use.
|
||||
await FullZoom.reduce();
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
154
browser/base/content/test/zoom/browser_default_zoom_multitab.js
Normal file
154
browser/base/content/test/zoom/browser_default_zoom_multitab.js
Normal file
@ -0,0 +1,154 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_multidomain_global_zoom() {
|
||||
const TEST_PAGE_URL_1 = "https://example.com";
|
||||
const TEST_PAGE_URL_2 = "https://example.org";
|
||||
|
||||
// Prepare the test tabs
|
||||
let tab1 = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser1 = gBrowser.getBrowserForTab(tab1);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
|
||||
await FullZoomHelper.load(tab1, TEST_PAGE_URL_1);
|
||||
|
||||
let tab2 = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser2 = gBrowser.getBrowserForTab(tab2);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
|
||||
await FullZoomHelper.load(tab2, TEST_PAGE_URL_2);
|
||||
|
||||
// 67% global zoom
|
||||
await FullZoomHelper.changeDefaultZoom(67);
|
||||
|
||||
// 67% local zoom tab 1
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
|
||||
await TestUtils.waitForCondition(
|
||||
() => ZoomManager.getZoomForBrowser(tabBrowser1) == 0.67
|
||||
);
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser1),
|
||||
0.67,
|
||||
"Setting default zoom causes tab 1 (background) to zoom to default zoom."
|
||||
);
|
||||
|
||||
// 67% local zoom tab 2
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
|
||||
await TestUtils.waitForCondition(
|
||||
() => ZoomManager.getZoomForBrowser(tabBrowser2) == 0.67
|
||||
);
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser2),
|
||||
0.67,
|
||||
"Setting default zoom causes tab 2 (foreground) to zoom to default zoom."
|
||||
);
|
||||
|
||||
await FullZoom.enlarge();
|
||||
// 80% local zoom tab 2
|
||||
await TestUtils.waitForCondition(
|
||||
() => ZoomManager.getZoomForBrowser(tabBrowser2) == 0.8
|
||||
);
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser2),
|
||||
0.8,
|
||||
"Enlarging local zoom of tab 2."
|
||||
);
|
||||
|
||||
// 67% local zoom tab 1
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
|
||||
await TestUtils.waitForCondition(
|
||||
() => ZoomManager.getZoomForBrowser(tabBrowser1) == 0.67
|
||||
);
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser1),
|
||||
0.67,
|
||||
"Tab 1 is unchanged by tab 2's enlarge call."
|
||||
);
|
||||
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
||||
|
||||
add_task(async function test_site_specific_global_zoom() {
|
||||
const TEST_PAGE_URL_1 = "http://example.net";
|
||||
const TEST_PAGE_URL_2 = "http://example.net";
|
||||
|
||||
// Prepare the test tabs
|
||||
let tab1 = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser1 = gBrowser.getBrowserForTab(tab1);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
|
||||
await FullZoomHelper.load(tab1, TEST_PAGE_URL_1);
|
||||
|
||||
let tab2 = BrowserTestUtils.addTab(gBrowser);
|
||||
let tabBrowser2 = gBrowser.getBrowserForTab(tab2);
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
|
||||
await FullZoomHelper.load(tab2, TEST_PAGE_URL_2);
|
||||
|
||||
// 67% global zoom persists from previous test
|
||||
let defaultZoom = FullZoomHelper.getGlobalValue();
|
||||
console.log("Global zoom is: ", defaultZoom);
|
||||
|
||||
// 67% local zoom tab 1
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab 1 zoom is: ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser1)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser1) == 0.67;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser1),
|
||||
0.67,
|
||||
"Setting default zoom causes tab 1 (background) to zoom to default zoom."
|
||||
);
|
||||
|
||||
// 67% local zoom tab 2
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab 2 zoom is: ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser2)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser2) == 0.67;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser2),
|
||||
0.67,
|
||||
"Setting default zoom causes tab 2 (foreground) to zoom to default zoom."
|
||||
);
|
||||
|
||||
// 80% site specific zoom
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab1);
|
||||
console.log("Enlarging");
|
||||
await FullZoom.enlarge();
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab 1 zoom is: ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser1)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser1) == 0.8;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser1),
|
||||
0.8,
|
||||
"Changed local zoom in tab one."
|
||||
);
|
||||
|
||||
await FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current tab 2 zoom is: ",
|
||||
ZoomManager.getZoomForBrowser(tabBrowser2)
|
||||
);
|
||||
return ZoomManager.getZoomForBrowser(tabBrowser2) == 0.8;
|
||||
});
|
||||
is(
|
||||
ZoomManager.getZoomForBrowser(tabBrowser2),
|
||||
0.8,
|
||||
"Second tab respects site specific zoom."
|
||||
);
|
||||
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
await FullZoomHelper.removeTabAndWaitForLocationChange();
|
||||
});
|
173
browser/base/content/test/zoom/head.js
Normal file
173
browser/base/content/test/zoom/head.js
Normal file
@ -0,0 +1,173 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { BrowserTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/BrowserTestUtils.jsm"
|
||||
);
|
||||
|
||||
let gContentPrefs = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
|
||||
let gLoadContext = Cu.createLoadContext();
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await new Promise(resolve => {
|
||||
gContentPrefs.removeByName(window.FullZoom.name, gLoadContext, {
|
||||
handleResult() {},
|
||||
handleCompletion() {
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var FullZoomHelper = {
|
||||
async changeDefaultZoom(newZoom) {
|
||||
let nonPrivateLoadContext = Cu.createLoadContext();
|
||||
/* Because our setGlobal function takes in a browsing context, and
|
||||
* because we want to keep this property consistent across both private
|
||||
* and non-private contexts, we crate a non-private context and use that
|
||||
* to set the property, regardless of our actual context.
|
||||
*/
|
||||
|
||||
let parsedZoomValue = parseFloat((parseInt(newZoom) / 100).toFixed(2));
|
||||
|
||||
await new Promise(resolve => {
|
||||
gContentPrefs.setGlobal(
|
||||
FullZoom.name,
|
||||
parsedZoomValue,
|
||||
nonPrivateLoadContext,
|
||||
{
|
||||
handleCompletion(reason) {
|
||||
resolve();
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
async getGlobalValue() {
|
||||
return new Promise(resolve => {
|
||||
let cachedVal = parseFloat(
|
||||
gContentPrefs.getCachedGlobal(FullZoom.name, gLoadContext)
|
||||
);
|
||||
if (cachedVal) {
|
||||
// We've got cached information, though it may be we've cached
|
||||
// an undefined value, or the cached info is invalid. To ensure
|
||||
// a valid return, we opt to return the default 1.0 in the
|
||||
// undefined and invalid cases.
|
||||
resolve(parseFloat(cachedVal.value) || 1.0);
|
||||
return;
|
||||
}
|
||||
let value = 1.0;
|
||||
gContentPrefs.getGlobal(FullZoom.name, gLoadContext, {
|
||||
handleResult(pref) {
|
||||
if (pref.value) {
|
||||
value = parseFloat(pref.value);
|
||||
}
|
||||
},
|
||||
handleCompletion(reason) {
|
||||
resolve(value);
|
||||
},
|
||||
handleError(error) {
|
||||
Cu.reportError(error);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
waitForLocationChange: function waitForLocationChange() {
|
||||
return new Promise(resolve => {
|
||||
Services.obs.addObserver(function obs(subj, topic, data) {
|
||||
Services.obs.removeObserver(obs, topic);
|
||||
resolve();
|
||||
}, "browser-fullZoom:location-change");
|
||||
});
|
||||
},
|
||||
|
||||
selectTabAndWaitForLocationChange: function selectTabAndWaitForLocationChange(
|
||||
tab
|
||||
) {
|
||||
if (!tab) {
|
||||
throw new Error("tab must be given.");
|
||||
}
|
||||
if (gBrowser.selectedTab == tab) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
BrowserTestUtils.switchTab(gBrowser, tab),
|
||||
this.waitForLocationChange(),
|
||||
]);
|
||||
},
|
||||
|
||||
removeTabAndWaitForLocationChange: function removeTabAndWaitForLocationChange(
|
||||
tab
|
||||
) {
|
||||
tab = tab || gBrowser.selectedTab;
|
||||
let selected = gBrowser.selectedTab == tab;
|
||||
gBrowser.removeTab(tab);
|
||||
if (selected) {
|
||||
return this.waitForLocationChange();
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
load: function load(tab, url) {
|
||||
return new Promise(resolve => {
|
||||
let didLoad = false;
|
||||
let didZoom = false;
|
||||
|
||||
promiseTabLoadEvent(tab).then(event => {
|
||||
didLoad = true;
|
||||
if (didZoom) {
|
||||
resolve();
|
||||
}
|
||||
}, true);
|
||||
|
||||
this.waitForLocationChange().then(function() {
|
||||
didZoom = true;
|
||||
if (didLoad) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for a load (or custom) event to finish in a given tab. If provided
|
||||
* load an uri into the tab.
|
||||
*
|
||||
* @param tab
|
||||
* The tab to load into.
|
||||
* @param [optional] url
|
||||
* The url to load, or the current url.
|
||||
* @return {Promise} resolved when the event is handled.
|
||||
* @resolves to the received event
|
||||
* @rejects if a valid load event is not received within a meaningful interval
|
||||
*/
|
||||
function promiseTabLoadEvent(tab, url) {
|
||||
console.info("Wait tab event: load");
|
||||
|
||||
function handle(loadedUrl) {
|
||||
if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) {
|
||||
console.info(`Skipping spurious load event for ${loadedUrl}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.info("Tab event received: load");
|
||||
return true;
|
||||
}
|
||||
|
||||
let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle);
|
||||
|
||||
if (url) {
|
||||
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
@ -57,6 +57,7 @@ BROWSER_CHROME_MANIFESTS += [
|
||||
'content/test/trackingUI/browser.ini',
|
||||
'content/test/webextensions/browser.ini',
|
||||
'content/test/webrtc/browser.ini',
|
||||
'content/test/zoom/browser.ini',
|
||||
]
|
||||
|
||||
DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
|
||||
|
@ -4,18 +4,31 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var initialPageZoom = ZoomManager.zoom;
|
||||
|
||||
add_task(async function() {
|
||||
info("Check zoom in button existence and functionality");
|
||||
|
||||
is(initialPageZoom, 1, "Initial zoom factor should be 1");
|
||||
is(ZoomManager.zoom, 1, "Initial zoom factor should be 1");
|
||||
|
||||
CustomizableUI.addWidgetToArea(
|
||||
"zoom-controls",
|
||||
CustomizableUI.AREA_FIXED_OVERFLOW_PANEL
|
||||
);
|
||||
registerCleanupFunction(() => CustomizableUI.reset());
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
CustomizableUI.reset();
|
||||
let gContentPrefs = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
let gLoadContext = Cu.createLoadContext();
|
||||
await new Promise(resolve => {
|
||||
gContentPrefs.removeByName(window.FullZoom.name, gLoadContext, {
|
||||
handleResult() {},
|
||||
handleCompletion() {
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await waitForOverflowButtonShown();
|
||||
|
||||
@ -27,12 +40,18 @@ add_task(async function() {
|
||||
|
||||
zoomInButton.click();
|
||||
let pageZoomLevel = parseInt(ZoomManager.zoom * 100);
|
||||
console.log("Page oom level is: ", pageZoomLevel);
|
||||
|
||||
let zoomResetButton = document.getElementById("zoom-reset-button");
|
||||
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
|
||||
ok(
|
||||
pageZoomLevel > 100 && pageZoomLevel == expectedZoomLevel,
|
||||
"Page zoomed in correctly"
|
||||
);
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current zoom is ",
|
||||
parseInt(zoomResetButton.getAttribute("label"), 10)
|
||||
);
|
||||
return parseInt(zoomResetButton.getAttribute("label"), 10) == pageZoomLevel;
|
||||
});
|
||||
|
||||
ok(pageZoomLevel > 100, "Page zoomed in correctly");
|
||||
|
||||
// close the Panel
|
||||
let panelHiddenPromise = promiseOverflowHidden(window);
|
||||
@ -40,9 +59,3 @@ add_task(async function() {
|
||||
await panelHiddenPromise;
|
||||
info("Menu panel was closed");
|
||||
});
|
||||
|
||||
add_task(async function asyncCleanup() {
|
||||
// reset zoom level
|
||||
ZoomManager.zoom = initialPageZoom;
|
||||
info("Zoom level was restored");
|
||||
});
|
||||
|
@ -4,18 +4,31 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var initialPageZoom = ZoomManager.zoom;
|
||||
|
||||
add_task(async function() {
|
||||
info("Check zoom out button existence and functionality");
|
||||
|
||||
is(initialPageZoom, 1, "Initial zoom factor should be 1");
|
||||
is(ZoomManager.zoom, 1, "Initial zoom factor should be 1");
|
||||
|
||||
CustomizableUI.addWidgetToArea(
|
||||
"zoom-controls",
|
||||
CustomizableUI.AREA_FIXED_OVERFLOW_PANEL
|
||||
);
|
||||
registerCleanupFunction(() => CustomizableUI.reset());
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
CustomizableUI.reset();
|
||||
let gContentPrefs = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
let gLoadContext = Cu.createLoadContext();
|
||||
await new Promise(resolve => {
|
||||
gContentPrefs.removeByName(window.FullZoom.name, gLoadContext, {
|
||||
handleResult() {},
|
||||
handleCompletion() {
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await waitForOverflowButtonShown();
|
||||
|
||||
@ -27,13 +40,18 @@ add_task(async function() {
|
||||
|
||||
zoomOutButton.click();
|
||||
let pageZoomLevel = Math.round(ZoomManager.zoom * 100);
|
||||
console.log("Page zoom level is: ", pageZoomLevel);
|
||||
|
||||
let zoomResetButton = document.getElementById("zoom-reset-button");
|
||||
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
|
||||
ok(
|
||||
pageZoomLevel < 100 && pageZoomLevel == expectedZoomLevel,
|
||||
"Page zoomed out correctly"
|
||||
);
|
||||
await TestUtils.waitForCondition(() => {
|
||||
console.log(
|
||||
"Current zoom is ",
|
||||
parseInt(zoomResetButton.getAttribute("label"), 10)
|
||||
);
|
||||
return parseInt(zoomResetButton.getAttribute("label"), 10) == pageZoomLevel;
|
||||
});
|
||||
|
||||
ok(pageZoomLevel < 100, "Page zoomed out correctly");
|
||||
|
||||
// close the panel
|
||||
let panelHiddenPromise = promiseOverflowHidden(window);
|
||||
@ -41,9 +59,3 @@ add_task(async function() {
|
||||
await panelHiddenPromise;
|
||||
info("Menu panel was closed");
|
||||
});
|
||||
|
||||
add_task(async function asyncCleanup() {
|
||||
// reset zoom level
|
||||
ZoomManager.zoom = initialPageZoom;
|
||||
info("Zoom level was restored");
|
||||
});
|
||||
|
@ -268,6 +268,26 @@
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<!-- Zoom -->
|
||||
<groupbox id="zoomGroup" data-category="paneGeneral" hidden="true">
|
||||
<label><html:h2 data-l10n-id="preferences-zoom-header"/></label>
|
||||
|
||||
<hbox id="zoomBox" align="center" hidden="true">
|
||||
<label control="defaultZoom" data-l10n-id="preferences-default-zoom"/>
|
||||
<!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
|
||||
<hbox flex="1">
|
||||
<menulist id="defaultZoom">
|
||||
<menupopup/>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<checkbox id="zoomText"
|
||||
data-l10n-id="preferences-zoom-text-only"
|
||||
preference="browser.zoom.full"/>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<!-- Languages -->
|
||||
<groupbox id="languagesGroup" data-category="paneGeneral" hidden="true">
|
||||
<label><html:h2 data-l10n-id="language-header"/></label>
|
||||
|
@ -369,6 +369,11 @@ var gMainPane = {
|
||||
gMainPane.initBrowserLocale();
|
||||
}
|
||||
|
||||
// We call `initDefaultZoomValues` to set and unhide the
|
||||
// default zoom preferences menu, and to establish a
|
||||
// listener for future menu changes.
|
||||
gMainPane.initDefaultZoomValues();
|
||||
|
||||
let cfrLearnMoreUrl =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL") +
|
||||
"extensionrecommendations";
|
||||
@ -926,6 +931,41 @@ var gMainPane = {
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Fetch the existing default zoom value, initialise and unhide
|
||||
* the preferences menu. This method also establishes a listener
|
||||
* to ensure handleDefaultZoomChange is called on future menu
|
||||
* changes.
|
||||
*/
|
||||
async initDefaultZoomValues() {
|
||||
let win = window.docShell.rootTreeItem.domWindow;
|
||||
let selected = await win.ZoomUI.getGlobalValue();
|
||||
let menulist = document.getElementById("defaultZoom");
|
||||
|
||||
new SelectionChangedMenulist(menulist, event => {
|
||||
let parsedZoom = parseFloat((event.target.value / 100).toFixed(2));
|
||||
gMainPane.handleDefaultZoomChange(parsedZoom);
|
||||
});
|
||||
let zoomValues = win.ZoomManager.zoomValues.map(a => {
|
||||
return Math.round(a * 100);
|
||||
});
|
||||
|
||||
let fragment = document.createDocumentFragment();
|
||||
for (let zoomLevel of zoomValues) {
|
||||
let menuitem = document.createXULElement("menuitem");
|
||||
document.l10n.setAttributes(menuitem, "preferences-default-zoom-value", {
|
||||
percentage: zoomLevel,
|
||||
});
|
||||
menuitem.setAttribute("value", zoomLevel);
|
||||
fragment.appendChild(menuitem);
|
||||
}
|
||||
|
||||
let menupopup = menulist.querySelector("menupopup");
|
||||
menupopup.appendChild(fragment);
|
||||
menulist.value = Math.round(selected * 100);
|
||||
|
||||
document.getElementById("zoomBox").hidden = false;
|
||||
},
|
||||
|
||||
initBrowserLocale() {
|
||||
// Enable telemetry.
|
||||
@ -1101,6 +1141,27 @@ var gMainPane = {
|
||||
this.showConfirmLanguageChangeMessageBar(locales);
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes as newZoom a floating point value representing the
|
||||
* new default zoom. This value should not be a string, and
|
||||
* should not carry a percentage sign/other localisation
|
||||
* characteristics.
|
||||
*/
|
||||
handleDefaultZoomChange(newZoom) {
|
||||
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
let nonPrivateLoadContext = Cu.createLoadContext();
|
||||
/* Because our setGlobal function takes in a browsing context, and
|
||||
* because we want to keep this property consistent across both private
|
||||
* and non-private contexts, we crate a non-private context and use that
|
||||
* to set the property, regardless of our actual context.
|
||||
*/
|
||||
|
||||
let win = window.docShell.rootTreeItem.domWindow;
|
||||
cps2.setGlobal(win.FullZoom.name, newZoom, nonPrivateLoadContext);
|
||||
},
|
||||
|
||||
onBrowserRestoreSessionChange(event) {
|
||||
const value = event.target.checked;
|
||||
const startupPref = Preferences.get("browser.startup.page");
|
||||
|
@ -139,6 +139,7 @@ add_task(async function search_for_password_show_passwordGroup() {
|
||||
child.id == "startupGroup" ||
|
||||
child.id == "languagesGroup" ||
|
||||
child.id == "fontsGroup" ||
|
||||
child.id == "zoomGroup" ||
|
||||
child.id == "downloadsGroup" ||
|
||||
child.id == "applicationsGroup" ||
|
||||
child.id == "drmGroup" ||
|
||||
|
@ -245,6 +245,19 @@ colors-settings =
|
||||
.label = Colors…
|
||||
.accesskey = C
|
||||
|
||||
# Zoom is a noun, and the message is used as header for a group of options
|
||||
preferences-zoom-header = Zoom
|
||||
|
||||
preferences-default-zoom = Default zoom
|
||||
.accesskey = z
|
||||
|
||||
preferences-default-zoom-value =
|
||||
.label = { $percentage }%
|
||||
|
||||
preferences-zoom-text-only =
|
||||
.label = Zoom text only
|
||||
.accesskey = t
|
||||
|
||||
language-header = Language
|
||||
|
||||
choose-language-description = Choose your preferred language for displaying pages
|
||||
|
@ -6,8 +6,12 @@
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ZoomUI"];
|
||||
|
||||
const gLoadContext = Cu.createLoadContext();
|
||||
const gContentPrefs = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const gZoomPropertyName = "browser.content.full-zoom";
|
||||
|
||||
var ZoomUI = {
|
||||
init(aWindow) {
|
||||
@ -28,6 +32,45 @@ var ZoomUI = {
|
||||
{ once: true }
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the global browser.content.full-zoom content preference.
|
||||
*
|
||||
* @returns Promise<prefValue>
|
||||
* Resolves to the preference value (float) when done.
|
||||
*/
|
||||
getGlobalValue() {
|
||||
return new Promise(resolve => {
|
||||
let cachedVal = gContentPrefs.getCachedGlobal(
|
||||
gZoomPropertyName,
|
||||
gLoadContext
|
||||
);
|
||||
if (cachedVal) {
|
||||
// We've got cached information, though it may be we've cached
|
||||
// an undefined value, or the cached info is invalid. To ensure
|
||||
// a valid return, we opt to return the default 1.0 in the
|
||||
// undefined and invalid cases.
|
||||
resolve(parseFloat(cachedVal.value) || 1.0);
|
||||
return;
|
||||
}
|
||||
// Otherwise, nothing is cached, so we must do a full lookup
|
||||
// with `gContentPrefs.getGlobal()`.
|
||||
let value = 1.0;
|
||||
gContentPrefs.getGlobal(gZoomPropertyName, gLoadContext, {
|
||||
handleResult(pref) {
|
||||
if (pref.value) {
|
||||
value = parseFloat(pref.value);
|
||||
}
|
||||
},
|
||||
handleCompletion(reason) {
|
||||
resolve(value);
|
||||
},
|
||||
handleError(error) {
|
||||
Cu.reportError(error);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function fullZoomLocationChangeObserver(aSubject, aTopic) {
|
||||
@ -74,7 +117,7 @@ function onZoomChange(event) {
|
||||
* @param {boolean} aAnimate Should be True for all cases unless the zoom
|
||||
* change is related to tab switching. Optional
|
||||
*/
|
||||
function updateZoomUI(aBrowser, aAnimate = false) {
|
||||
async function updateZoomUI(aBrowser, aAnimate = false) {
|
||||
let win = aBrowser.ownerGlobal;
|
||||
if (!win.gBrowser || win.gBrowser.selectedBrowser != aBrowser) {
|
||||
return;
|
||||
@ -88,10 +131,22 @@ function updateZoomUI(aBrowser, aAnimate = false) {
|
||||
let urlbarZoomButton = win.document.getElementById("urlbar-zoom-button");
|
||||
let zoomFactor = Math.round(win.ZoomManager.zoom * 100);
|
||||
|
||||
// Hide urlbar zoom button if zoom is at 100% or the customizable control is
|
||||
// in the toolbar.
|
||||
// Hide urlbar zoom button if zoom is at the default zoom level,
|
||||
// or the customizable control is in the toolbar
|
||||
|
||||
let defaultZoom = (await ZoomUI.getGlobalValue()) * 100;
|
||||
|
||||
if (!win.gBrowser || win.gBrowser.selectedBrowser != aBrowser) {
|
||||
// Because the CPS call is async, at this point the selected browser
|
||||
// may have changed. We should re-check whether the browser for which we've
|
||||
// been notified is still the selected browser and bail out if not.
|
||||
// If the selected browser changed (again), we will have been called again
|
||||
// with the "right" browser, and that'll update the zoom level.
|
||||
return;
|
||||
}
|
||||
|
||||
urlbarZoomButton.hidden =
|
||||
zoomFactor == 100 ||
|
||||
defaultZoom == zoomFactor ||
|
||||
(customizableZoomControls &&
|
||||
customizableZoomControls.getAttribute("cui-areatype") == "toolbar");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user