Merge autoland to mozilla-central r=merge a=merge

This commit is contained in:
Csoregi Natalia 2017-11-06 12:44:18 +02:00
commit 978711ce7c
57 changed files with 902 additions and 1600 deletions

View File

@ -25,6 +25,7 @@
#include <winreg.h>
#include "AccessibleHypertext.h"
#include "AccessibleHypertext2.h"
#include "Accessible2_i.c"
#include "Accessible2_2_i.c"
#include "Accessible2_3_i.c"
@ -209,8 +210,9 @@ AccessibleHandler::QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
return S_OK;
}
if (aIid == IID_IAccessibleText || aIid == IID_IAccessibleHypertext) {
RefPtr<IAccessibleHypertext> textTearoff(new AccessibleTextTearoff(this));
if (aIid == IID_IAccessibleText || aIid == IID_IAccessibleHypertext ||
aIid == IID_IAccessibleHypertext2) {
RefPtr<IAccessibleHypertext2> textTearoff(new AccessibleTextTearoff(this));
textTearoff.forget(aOutInterface);
return S_OK;
}

View File

@ -13,6 +13,7 @@
#include "AccessibleHandlerControl.h"
#include "AccessibleText_i.c"
#include "AccessibleHypertext_i.c"
#include "AccessibleHypertext2_i.c"
#include "Factory.h"
#include "mozilla/Assertions.h"
@ -38,13 +39,14 @@ AccessibleTextTearoff::ResolveAccHypertext()
return E_UNEXPECTED;
}
return proxy->QueryInterface(IID_IAccessibleHypertext,
return proxy->QueryInterface(IID_IAccessibleHypertext2,
getter_AddRefs(mAccHypertextProxy));
}
IMPL_IUNKNOWN_QUERY_HEAD(AccessibleTextTearoff)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleText)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleHypertext)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleHypertext2)
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mHandler)
HRESULT
@ -338,6 +340,17 @@ AccessibleTextTearoff::get_hyperlinkIndex(long charIndex, long *hyperlinkIndex)
return mAccHypertextProxy->get_hyperlinkIndex(charIndex, hyperlinkIndex);
}
HRESULT
AccessibleTextTearoff::get_hyperlinks(IAccessibleHyperlink*** hyperlinks,
long* nHyperlinks)
{
HRESULT hr = ResolveAccHypertext();
if (FAILED(hr)) {
return hr;
}
return mAccHypertextProxy->get_hyperlinks(hyperlinks, nHyperlinks);
}
} // namespace a11y
} // namespace mozilla

View File

@ -12,14 +12,14 @@
#define mozilla_a11y_AccessibleTextTearoff_h
#include "AccessibleHandler.h"
#include "AccessibleHypertext.h"
#include "AccessibleHypertext2.h"
#include "IUnknownImpl.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
class AccessibleTextTearoff final : public IAccessibleHypertext
class AccessibleTextTearoff final : public IAccessibleHypertext2
{
public:
explicit AccessibleTextTearoff(AccessibleHandler* aHandler);
@ -72,12 +72,16 @@ public:
IAccessibleHyperlink **hyperlink) override;
STDMETHODIMP get_hyperlinkIndex(long charIndex, long *hyperlinkIndex) override;
// IAccessibleHypertext2
STDMETHODIMP get_hyperlinks(IAccessibleHyperlink*** hyperlinks,
long* nHyperlinks) override;
private:
~AccessibleTextTearoff() = default;
HRESULT ResolveAccHypertext();
RefPtr<AccessibleHandler> mHandler;
RefPtr<IAccessibleHypertext> mAccHypertextProxy;
RefPtr<IAccessibleHypertext2> mAccHypertextProxy;
};
} // namespace a11y

View File

@ -654,6 +654,7 @@ pref("mousewheel.with_win.action", 1);
pref("browser.xul.error_pages.enabled", true);
pref("browser.xul.error_pages.expert_bad_cert", false);
pref("browser.xul.error_pages.show_safe_browsing_details_on_load", false);
// Enable captive portal detection.
pref("network.captive-portal-service.enabled", true);

View File

@ -199,6 +199,13 @@ var AboutBlockedSiteListener = {
doc.getElementById("firefox_support").setAttribute("href",
"https://support.mozilla.org/kb/how-does-phishing-and-malware-protection-work");
// Show safe browsing details on load if the pref is set to true.
let showDetails = Services.prefs.getBoolPref("browser.xul.error_pages.show_safe_browsing_details_on_load");
if (showDetails) {
let details = content.document.getElementById("errorDescriptionContainer");
details.removeAttribute("hidden");
}
// Set safe browsing advisory link.
let advisoryUrl = Services.prefs.getCharPref(
"browser.safebrowsing.provider." + provider + ".advisoryURL", "");

View File

@ -60,10 +60,6 @@ var whitelist = [
{file: "chrome://global/locale/printPreviewProgress.dtd",
platforms: ["macosx"]},
{file: "chrome://global/locale/printProgress.dtd", platforms: ["macosx"]},
{file: "chrome://global/locale/printdialog.dtd",
platforms: ["macosx", "win"]},
{file: "chrome://global/locale/printjoboptions.dtd",
platforms: ["macosx", "win"]},
// devtools/client/inspector/bin/dev-server.js
{file: "chrome://devtools/content/inspector/markup/markup.xhtml",

View File

@ -1,6 +1,6 @@
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -49,37 +49,39 @@ this.SiteDataManager = {
this._cancelGetQuotaUsage();
this._getQuotaUsagePromise = new Promise(resolve => {
let onUsageResult = request => {
let items = request.result;
for (let item of items) {
if (!item.persisted && item.usage <= 0) {
// An non-persistent-storage site with 0 byte quota usage is redundant for us so skip it.
continue;
}
let principal =
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
let uri = principal.URI;
if (uri.scheme == "http" || uri.scheme == "https") {
let site = this._sites.get(uri.host);
if (!site) {
site = {
persisted: false,
quotaUsage: 0,
principals: [],
appCacheList: [],
};
if (request.resultCode == Cr.NS_OK) {
let items = request.result;
for (let item of items) {
if (!item.persisted && item.usage <= 0) {
// An non-persistent-storage site with 0 byte quota usage is redundant for us so skip it.
continue;
}
// Assume 3 sites:
// - Site A (not persisted): https://www.foo.com
// - Site B (not persisted): https://www.foo.com^userContextId=2
// - Site C (persisted): https://www.foo.com:1234
// Although only C is persisted, grouping by host, as a result,
// we still mark as persisted here under this host group.
if (item.persisted) {
site.persisted = true;
let principal =
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
let uri = principal.URI;
if (uri.scheme == "http" || uri.scheme == "https") {
let site = this._sites.get(uri.host);
if (!site) {
site = {
persisted: false,
quotaUsage: 0,
principals: [],
appCacheList: [],
};
}
// Assume 3 sites:
// - Site A (not persisted): https://www.foo.com
// - Site B (not persisted): https://www.foo.com^userContextId=2
// - Site C (persisted): https://www.foo.com:1234
// Although only C is persisted, grouping by host, as a result,
// we still mark as persisted here under this host group.
if (item.persisted) {
site.persisted = true;
}
site.principals.push(principal);
site.quotaUsage += item.usage;
this._sites.set(uri.host, site);
}
site.principals.push(principal);
site.quotaUsage += item.usage;
this._sites.set(uri.host, site);
}
}
resolve();
@ -222,37 +224,54 @@ this.SiteDataManager = {
}
},
_removeServiceWorkers(site) {
_unregisterServiceWorker(serviceWorker) {
return new Promise(resolve => {
let unregisterCallback = {
unregisterSucceeded: resolve,
unregisterFailed: resolve, // We don't care about failures.
QueryInterface: XPCOMUtils.generateQI([Ci.nsIServiceWorkerUnregisterCallback])
};
serviceWorkerManager.propagateUnregister(serviceWorker.principal, unregisterCallback, serviceWorker.scope);
});
},
_removeServiceWorkersForSites(sites) {
let promises = [];
let targetHosts = sites.map(s => s.principals[0].URI.host);
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
for (let i = 0; i < serviceWorkers.length; i++) {
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
for (let principal of site.principals) {
if (sw.principal.equals(principal)) {
serviceWorkerManager.removeAndPropagate(sw.principal.URI.host);
break;
}
// Sites are grouped and removed by host so we unregister service workers by the same host as well
if (targetHosts.includes(sw.principal.URI.host)) {
promises.push(this._unregisterServiceWorker(sw));
}
}
return Promise.all(promises);
},
remove(hosts) {
let promises = [];
let unknownHost = "";
let targetSites = [];
for (let host of hosts) {
let site = this._sites.get(host);
if (site) {
this._removePermission(site);
this._removeAppCache(site);
this._removeCookie(site);
this._removeServiceWorkers(site);
promises.push(this._removeQuotaUsage(site));
targetSites.push(site);
} else {
unknownHost = host;
break;
}
}
if (promises.length > 0) {
Promise.all(promises).then(() => this.updateSites());
if (targetSites.length > 0) {
this._removeServiceWorkersForSites(targetSites)
.then(() => {
let promises = targetSites.map(s => this._removeQuotaUsage(s));
return Promise.all(promises);
})
.then(() => this.updateSites());
}
if (unknownHost) {
throw `SiteDataManager: removing unknown site of ${unknownHost}`;
@ -265,12 +284,13 @@ this.SiteDataManager = {
OfflineAppCacheHelper.clear();
// Iterate through the service workers and remove them.
let promises = [];
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
for (let i = 0; i < serviceWorkers.length; i++) {
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
let host = sw.principal.URI.host;
serviceWorkerManager.removeAndPropagate(host);
promises.push(this._unregisterServiceWorker(sw));
}
await Promise.all(promises);
// Refresh sites using quota usage again.
// This is for the case:
@ -283,7 +303,7 @@ this.SiteDataManager = {
// because that would clear browser data as well too,
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1312361#c9
await this._getQuotaUsage();
let promises = [];
promises = [];
for (let site of this._sites.values()) {
this._removePermission(site);
promises.push(this._removeQuotaUsage(site));

View File

@ -112,37 +112,16 @@ var gBlocklistManager = {
}
if (activeList !== selected.id) {
const Cc = Components.classes, Ci = Components.interfaces;
let msg = this._bundle.getFormattedString("blocklistChangeRequiresRestart",
[this._brandShortName]);
let title = this._bundle.getFormattedString("shouldRestartTitle",
[this._brandShortName]);
let shouldProceed = Services.prompt.confirm(window, title, msg);
if (shouldProceed) {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
shouldProceed = !cancelQuit.data;
if (shouldProceed) {
let trackingTable = Services.prefs.getCharPref(TRACKING_TABLE_PREF);
if (selected.id != CONTENT_LIST_ID) {
trackingTable = trackingTable.replace("," + CONTENT_LIST_ID + TRACK_SUFFIX, "");
} else {
trackingTable += "," + CONTENT_LIST_ID + TRACK_SUFFIX;
}
Services.prefs.setCharPref(TRACKING_TABLE_PREF, trackingTable);
Services.prefs.setCharPref(UPDATE_TIME_PREF, 42);
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit |
Ci.nsIAppStartup.eRestart);
}
let trackingTable = Services.prefs.getCharPref(TRACKING_TABLE_PREF);
if (selected.id != CONTENT_LIST_ID) {
trackingTable = trackingTable.replace("," + CONTENT_LIST_ID + TRACK_SUFFIX, "");
} else {
trackingTable += "," + CONTENT_LIST_ID + TRACK_SUFFIX;
}
// Don't close the dialog in case we didn't quit.
return;
Services.prefs.setCharPref(TRACKING_TABLE_PREF, trackingTable);
Services.prefs.setCharPref(UPDATE_TIME_PREF, 42);
}
window.close();
},

View File

@ -3,6 +3,8 @@ support-files =
head.js
privacypane_tests_perwindow.js
site_data_test.html
service_worker_test.html
service_worker_test.js
addons/set_homepage.xpi
addons/set_newtab.xpi
offline/offline.html

View File

@ -15,6 +15,7 @@ const TEST_QUOTA_USAGE_URL = TEST_QUOTA_USAGE_ORIGIN + "/browser/browser/compone
const TEST_OFFLINE_HOST = "example.org";
const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST;
const TEST_OFFLINE_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/offline/offline.html";
const TEST_SERVICE_WORKER_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/service_worker_test.html";
const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
@ -22,6 +23,8 @@ const { DownloadUtils } = Cu.import("resource://gre/modules/DownloadUtils.jsm",
const { SiteDataManager } = Cu.import("resource:///modules/SiteDataManager.jsm", {});
const { OfflineAppCacheHelper } = Cu.import("resource:///modules/offlineAppCache.jsm", {});
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager");
const mockOfflineAppCacheHelper = {
clear: null,
@ -87,6 +90,40 @@ function promiseCookiesCleared() {
});
}
async function loadServiceWorkerTestPage(url) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await BrowserTestUtils.waitForCondition(() => {
return ContentTask.spawn(tab.linkedBrowser, {}, () =>
content.document.body.getAttribute("data-test-service-worker-registered") === "true");
}, `Fail to load service worker test ${url}`);
await BrowserTestUtils.removeTab(tab);
}
function promiseServiceWorkerRegisteredFor(url) {
return BrowserTestUtils.waitForCondition(() => {
try {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(url);
let sw = serviceWorkerManager.getRegistrationByPrincipal(principal, principal.URI.spec);
if (sw) {
ok(true, `Found the service worker registered for ${url}`);
return true;
}
} catch (e) {}
return false;
}, `Should register service worker for ${url}`);
}
function promiseServiceWorkersCleared() {
return BrowserTestUtils.waitForCondition(() => {
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
if (serviceWorkers.length == 0) {
ok(true, "Cleared all service workers");
return true;
}
return false;
}, "Should clear all service workers");
}
registerCleanupFunction(function() {
delete window.sinon;
mockOfflineAppCacheHelper.unregister();
@ -250,120 +287,55 @@ add_task(async function() {
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test sorting
// Test clearing service wroker through the "Clear All" button
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager);
mockSiteDataManager.fakeSites = [
{
usage: 1024,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("https://account.xyz.com"),
persisted: true
},
{
usage: 1024 * 2,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("https://books.foo.com"),
persisted: false
},
{
usage: 1024 * 3,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
persisted: true
},
];
let updatePromise = promiseSiteDataManagerSitesUpdated();
// Register a test service
await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL);
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
// Test the initial states
await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL);
// Click the "Clear All" button
let doc = gBrowser.selectedBrowser.contentDocument;
let clearBtn = doc.getElementById("clearSiteDataButton");
let acceptPromise = promiseAlertDialogOpen("accept");
let updatePromise = promiseSiteDataManagerSitesUpdated();
clearBtn.doCommand();
await acceptPromise;
await updatePromise;
await openSiteDataSettingsDialog();
let dialog = content.gSubDialog._topDialog;
let dialogFrame = dialog._frame;
let frameDoc = dialogFrame.contentDocument;
let hostCol = frameDoc.getElementById("hostCol");
let usageCol = frameDoc.getElementById("usageCol");
let statusCol = frameDoc.getElementById("statusCol");
let sitesList = frameDoc.getElementById("sitesList");
// Test default sorting
assertSortByUsage("descending");
// Test sorting on the usage column
usageCol.click();
assertSortByUsage("ascending");
usageCol.click();
assertSortByUsage("descending");
// Test sorting on the host column
hostCol.click();
assertSortByHost("ascending");
hostCol.click();
assertSortByHost("descending");
// Test sorting on the permission status column
statusCol.click();
assertSortByStatus("ascending");
statusCol.click();
assertSortByStatus("descending");
mockSiteDataManager.unregister();
await promiseServiceWorkersCleared();
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test clearing service wroker through the settings panel
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
// Register a test service worker
await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL);
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
// Test the initial states
await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL);
// Open the Site Data Settings panel and remove the site
await openSiteDataSettingsDialog();
let acceptRemovePromise = promiseAlertDialogOpen("accept");
let updatePromise = promiseSiteDataManagerSitesUpdated();
ContentTask.spawn(gBrowser.selectedBrowser, { TEST_OFFLINE_HOST }, args => {
let host = args.TEST_OFFLINE_HOST;
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
let sitesList = frameDoc.getElementById("sitesList");
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
if (site) {
let removeBtn = frameDoc.getElementById("removeSelected");
let saveBtn = frameDoc.getElementById("save");
site.click();
removeBtn.doCommand();
saveBtn.doCommand();
} else {
ok(false, `Should have one site of ${host}`);
}
});
await acceptRemovePromise;
await updatePromise;
await promiseServiceWorkersCleared();
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
function assertSortByHost(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let result = aHost.localeCompare(bHost);
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host");
}
}
}
function assertSortByStatus(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = 0;
if (a.persisted && !b.persisted) {
result = 1;
} else if (!a.persisted && b.persisted) {
result = -1;
}
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by permission status");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by permission status");
}
}
}
function assertSortByUsage(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = a.usage - b.usage;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage");
}
}
}
function findSiteByHost(host) {
return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
}
});

View File

@ -106,3 +106,121 @@ add_task(async function() {
mockSiteDataManager.unregister();
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test sorting
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register(SiteDataManager);
mockSiteDataManager.fakeSites = [
{
usage: 1024,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("https://account.xyz.com"),
persisted: true
},
{
usage: 1024 * 2,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("https://books.foo.com"),
persisted: false
},
{
usage: 1024 * 3,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
persisted: true
},
];
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
let dialog = content.gSubDialog._topDialog;
let dialogFrame = dialog._frame;
let frameDoc = dialogFrame.contentDocument;
let hostCol = frameDoc.getElementById("hostCol");
let usageCol = frameDoc.getElementById("usageCol");
let statusCol = frameDoc.getElementById("statusCol");
let sitesList = frameDoc.getElementById("sitesList");
// Test default sorting
assertSortByUsage("descending");
// Test sorting on the usage column
usageCol.click();
assertSortByUsage("ascending");
usageCol.click();
assertSortByUsage("descending");
// Test sorting on the host column
hostCol.click();
assertSortByHost("ascending");
hostCol.click();
assertSortByHost("descending");
// Test sorting on the permission status column
statusCol.click();
assertSortByStatus("ascending");
statusCol.click();
assertSortByStatus("descending");
mockSiteDataManager.unregister();
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
function assertSortByHost(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let result = aHost.localeCompare(bHost);
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host");
}
}
}
function assertSortByStatus(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = 0;
if (a.persisted && !b.persisted) {
result = 1;
} else if (!a.persisted && b.persisted) {
result = -1;
}
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by permission status");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by permission status");
}
}
}
function assertSortByUsage(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = a.usage - b.usage;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage");
}
}
}
function findSiteByHost(host) {
return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
}
});

View File

@ -254,7 +254,7 @@ const mockSiteDataManager = {
usage: site.usage,
persisted: site.persisted
}));
onUsageResult({ result });
onUsageResult({ result, resultCode: Components.results.NS_OK });
},
_removeQuotaUsage(site) {

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Cache-Control" content="public" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<title>Service Worker Test</title>
</head>
<body>
<h1>Service Worker Test</h1>
<script type="text/javascript">
navigator.serviceWorker.register("service_worker_test.js")
.then(regis => document.body.setAttribute("data-test-service-worker-registered", "true"));
</script>
</body>
</html>

View File

@ -0,0 +1 @@
// empty worker, always succeed!

View File

@ -372,11 +372,11 @@ FormAutofillParent.prototype = {
}
}
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record)) {
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record, true)) {
this._recordFormFillingTime("address", "autofill-update", timeStartedFillingMS);
FormAutofillDoorhanger.show(target, "update").then((state) => {
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record);
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record, true);
switch (state) {
case "create":
if (!changedGUIDs.length) {

View File

@ -1153,6 +1153,27 @@ class AutofillRecords {
}
}
/**
* Merge the record if storage has multiple mergeable records.
* @param {Object} targetRecord
* The record for merge.
* @param {boolean} [strict = false]
* In strict merge mode, we'll treat the subset record with empty field
* as unable to be merged, but mergeable if in non-strict mode.
* @returns {Array.<string>}
* Return an array of the merged GUID string.
*/
mergeToStorage(targetRecord, strict = false) {
let mergedGUIDs = [];
for (let record of this.data) {
if (!record.deleted && this.mergeIfPossible(record.guid, targetRecord, strict)) {
mergedGUIDs.push(record.guid);
}
}
this.log.debug("Existing records matching and merging count is", mergedGUIDs.length);
return mergedGUIDs;
}
// A test-only helper.
_nukeAllRecords() {
this._store.data[this._collectionName] = [];
@ -1173,10 +1194,7 @@ class AutofillRecords {
_normalizeFields(record) {}
// An interface to be inherited.
mergeIfPossible(guid, record) {}
// An interface to be inherited.
mergeToStorage(targetRecord) {}
mergeIfPossible(guid, record, strict) {}
}
class Addresses extends AutofillRecords {
@ -1371,10 +1389,13 @@ class Addresses extends AutofillRecords {
* Indicates which address to merge.
* @param {Object} address
* The new address used to merge into the old one.
* @param {boolean} strict
* In strict merge mode, we'll treat the subset record with empty field
* as unable to be merged, but mergeable if in non-strict mode.
* @returns {boolean}
* Return true if address is merged into target with specific guid or false if not.
*/
mergeIfPossible(guid, address) {
mergeIfPossible(guid, address, strict) {
this.log.debug("mergeIfPossible:", guid, address);
let addressFound = this._findByGUID(guid);
@ -1382,7 +1403,7 @@ class Addresses extends AutofillRecords {
throw new Error("No matching address.");
}
let addressToMerge = this._clone(address);
let addressToMerge = strict ? this._clone(address) : this._cloneAndCleanUp(address);
this._normalizeRecord(addressToMerge);
let hasMatchingField = false;
@ -1417,35 +1438,26 @@ class Addresses extends AutofillRecords {
return false;
}
// Early return if the data is the same.
let exactlyMatch = this.VALID_FIELDS.every((field) =>
addressFound[field] === addressToMerge[field]
);
if (exactlyMatch) {
// Early return if the data is the same or subset.
let noNeedToUpdate = this.VALID_FIELDS.every((field) => {
// When addressFound doesn't contain a field, it's unnecessary to update
// if the same field in addressToMerge is omitted or an empty string.
if (addressFound[field] === undefined) {
return !addressToMerge[field];
}
// When addressFound contains a field, it's unnecessary to update if
// the same field in addressToMerge is omitted or a duplicate.
return (addressToMerge[field] === undefined) ||
(addressFound[field] === addressToMerge[field]);
});
if (noNeedToUpdate) {
return true;
}
this.update(guid, addressToMerge, true);
return true;
}
/**
* Merge the address if storage has multiple mergeable records.
* @param {Object} targetAddress
* The address for merge.
* @returns {Array.<string>}
* Return an array of the merged GUID string.
*/
mergeToStorage(targetAddress) {
let mergedGUIDs = [];
for (let address of this.data) {
if (!address.deleted && this.mergeIfPossible(address.guid, targetAddress)) {
mergedGUIDs.push(address.guid);
}
}
this.log.debug("Existing records matching and merging count is", mergedGUIDs.length);
return mergedGUIDs;
}
}
class CreditCards extends AutofillRecords {

View File

@ -119,6 +119,24 @@ add_task(async function check_storage_after_form_submitted() {
ok(matching, "Updated address merged as expected");
});
// Submit a subset address manually.
add_task(async function submit_subset_manually() {
document.querySelector("form").reset();
for (let key in TEST_ADDRESSES[0]) {
await setInput("#" + key, TEST_ADDRESSES[0][key]);
}
// Set organization field to empty
await setInput("#organization", "");
clickOnElement("input[type=submit]");
let expectedAddresses = TEST_ADDRESSES.slice(0);
await sleep(1000);
let matching = await checkAddresses(expectedAddresses);
ok(matching, "The storage is still the same after submitting a subset");
});
</script>
<div>

View File

@ -71,7 +71,7 @@ const MERGE_TESTCASES = [
},
},
{
description: "Merge a subset",
description: "Loose merge a subset",
addressInStorage: {
"given-name": "Timothy",
"street-address": "331 E. Evelyn Avenue",
@ -89,6 +89,29 @@ const MERGE_TESTCASES = [
"tel": "+16509030800",
country: "US",
},
noNeedToUpdate: true,
},
{
description: "Strict merge a subset without empty string",
addressInStorage: {
"given-name": "Timothy",
"street-address": "331 E. Evelyn Avenue",
"tel": "+16509030800",
country: "US",
},
addressToMerge: {
"given-name": "Timothy",
"street-address": "331 E. Evelyn Avenue",
"tel": "+16509030800",
},
expectedAddress: {
"given-name": "Timothy",
"street-address": "331 E. Evelyn Avenue",
"tel": "+16509030800",
country: "US",
},
strict: true,
noNeedToUpdate: true,
},
{
description: "Merge an address with partial overlaps",
@ -444,16 +467,27 @@ MERGE_TESTCASES.forEach((testcase) => {
profileStorage.addresses.pullSyncChanges();
do_check_eq(getSyncChangeCounter(profileStorage.addresses, guid), 1);
Assert.ok(profileStorage.addresses.mergeIfPossible(guid, testcase.addressToMerge));
await onMerged;
Assert.ok(profileStorage.addresses.mergeIfPossible(guid,
testcase.addressToMerge,
testcase.strict));
if (!testcase.noNeedToUpdate) {
await onMerged;
}
addresses = profileStorage.addresses.getAll();
Assert.equal(addresses.length, 1);
Assert.notEqual(addresses[0].timeLastModified, timeLastModified);
do_check_record_matches(addresses[0], testcase.expectedAddress);
if (testcase.noNeedToUpdate) {
Assert.equal(addresses[0].timeLastModified, timeLastModified);
// Record merging should bump the change counter.
do_check_eq(getSyncChangeCounter(profileStorage.addresses, guid), 2);
// No need to bump the change counter if the data is unchanged.
do_check_eq(getSyncChangeCounter(profileStorage.addresses, guid), 1);
} else {
Assert.notEqual(addresses[0].timeLastModified, timeLastModified);
// Record merging should bump the change counter.
do_check_eq(getSyncChangeCounter(profileStorage.addresses, guid), 2);
}
});
});
@ -492,6 +526,11 @@ add_task(async function test_merge_unable_merge() {
// Unable to merge because no overlap
do_check_eq(profileStorage.addresses.mergeIfPossible(guid, TEST_ADDRESS_4), false);
// Unable to strict merge because subset with empty string
let subset = Object.assign({}, TEST_ADDRESS_1);
subset.organization = "";
do_check_eq(profileStorage.addresses.mergeIfPossible(guid, subset, true), false);
// Shouldn't bump the change counter
do_check_eq(getSyncChangeCounter(profileStorage.addresses, guid), 1);
});
@ -507,3 +546,13 @@ add_task(async function test_mergeToStorage() {
do_check_eq(profileStorage.addresses.getAll()[1].email, anotherAddress.email);
do_check_eq(profileStorage.addresses.getAll()[2].email, anotherAddress.email);
});
add_task(async function test_mergeToStorage_strict() {
let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME,
[TEST_ADDRESS_1, TEST_ADDRESS_2]);
// Try to merge a subset with empty string
let anotherAddress = profileStorage.addresses._clone(TEST_ADDRESS_1);
anotherAddress.email = "";
do_check_eq(profileStorage.addresses.mergeToStorage(anotherAddress, true).length, 0);
do_check_eq(profileStorage.addresses.getAll()[0].email, TEST_ADDRESS_1.email);
});

View File

@ -919,4 +919,4 @@ aboutDialog.architecture.thirtyTwoBit = 32-bit
# LOCALIZATION NOTE (certImminentDistrust.message):
# Shown in the browser console when visiting a website that is trusted today,
# but won't be in the future unless the site operator makes a change.
certImminentDistrust.message = The security certificate in use on this web site will no longer be trusted in a future release of Firefox. For more information, visit https://wiki.mozilla.org/CA/Upcoming_Distrust_Actions
certImminentDistrust.message = The security certificate in use on this website will no longer be trusted in a future release. For more information, visit https://wiki.mozilla.org/CA/Upcoming_Distrust_Actions

View File

@ -64,8 +64,6 @@ mozstdName=Disconnect.me basic protection (Recommended).
mozstdDesc=Allows some trackers so websites function properly.
mozfullName=Disconnect.me strict protection.
mozfullDesc2=Blocks known trackers. Some websites may not function properly.
# LOCALIZATION NOTE (blocklistChangeRequiresRestart): %S = brandShortName
blocklistChangeRequiresRestart=%S must restart to change block lists.
#### Master Password

View File

@ -56,7 +56,6 @@ class RequestListContent extends Component {
constructor(props) {
super(props);
this.setScalingStyles = this.setScalingStyles.bind(this);
this.isScrolledToBottom = this.isScrolledToBottom.bind(this);
this.onHover = this.onHover.bind(this);
this.onScroll = this.onScroll.bind(this);
@ -77,9 +76,6 @@ class RequestListContent extends Component {
}
componentDidMount() {
// Set the CSS variables for waterfall scaling
this.setScalingStyles();
// Install event handler for displaying a tooltip
this.tooltip.startTogglingOnHover(this.refs.contentEl, this.onHover, {
toggleDelay: REQUESTS_TOOLTIP_TOGGLE_DELAY,
@ -98,9 +94,6 @@ class RequestListContent extends Component {
}
componentDidUpdate(prevProps) {
// Update the CSS variables for waterfall scaling after props change
this.setScalingStyles(prevProps);
let node = this.refs.contentEl;
// Keep the list scrolled to bottom if a new row was added
if (this.shouldScrollBottom && node.scrollTop !== MAX_SCROLL_HEIGHT) {
@ -116,26 +109,6 @@ class RequestListContent extends Component {
this.tooltip.stopTogglingOnHover();
}
/**
* Set the CSS variables for waterfall scaling. If React supported setting CSS
* variables as part of the "style" property of a DOM element, we would use that.
*
* However, React doesn't support this, so we need to use a hack and update the
* DOM element directly: https://github.com/facebook/react/issues/6411
*/
setScalingStyles(prevProps) {
const { scale } = this.props;
if (prevProps && prevProps.scale === scale) {
return;
}
const { style } = this.refs.contentEl;
style.removeProperty("--timings-scale");
style.removeProperty("--timings-rev-scale");
style.setProperty("--timings-scale", scale);
style.setProperty("--timings-rev-scale", 1 / scale);
}
isScrolledToBottom() {
const { contentEl } = this.refs;
const lastChildEl = contentEl.lastElementChild;
@ -250,6 +223,7 @@ class RequestListContent extends Component {
onSecurityIconMouseDown,
onThumbnailMouseDown,
onWaterfallMouseDown,
scale,
selectedRequestId,
} = this.props;
@ -261,6 +235,7 @@ class RequestListContent extends Component {
className: "requests-list-contents",
tabIndex: 0,
onKeyDown: this.onKeyDown,
style: {"--timings-scale": scale, "--timings-rev-scale": 1 / scale}
},
RequestListHeader(),
displayedRequests.map((item, index) => RequestListItem({

View File

@ -1601,12 +1601,23 @@ HTMLMediaElement::MozRequestDebugInfo(ErrorResult& aRv)
return promise.forget();
}
void
already_AddRefed<Promise>
HTMLMediaElement::MozDumpDebugInfo()
{
if (mDecoder) {
mDecoder->DumpDebugInfo();
ErrorResult rv;
RefPtr<Promise> promise = CreateDOMPromise(rv);
if (NS_WARN_IF(rv.Failed())) {
return nullptr;
}
if (mDecoder) {
mDecoder->DumpDebugInfo()->Then(mAbstractMainThread,
__func__,
promise.get(),
&Promise::MaybeResolveWithUndefined);
} else {
promise->MaybeResolveWithUndefined();
}
return promise.forget();
}
void
@ -6288,7 +6299,8 @@ nsresult HTMLMediaElement::DispatchEvent(const nsAString& aName)
false);
}
nsresult HTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
void
HTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
{
LOG_EVENT(LogLevel::Debug, ("%p Queuing event %s", this,
NS_ConvertUTF16toUTF8(aName).get()));
@ -6297,7 +6309,7 @@ nsresult HTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
// if the page comes out of the bfcache.
if (mEventDeliveryPaused) {
mPendingEvents.AppendElement(aName);
return NS_OK;
return;
}
nsCOMPtr<nsIRunnable> event;
@ -6322,8 +6334,6 @@ nsresult HTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
mPlayTime.Pause();
HiddenVideoStop();
}
return NS_OK;
}
nsresult HTMLMediaElement::DispatchPendingMediaEvents()

View File

@ -220,9 +220,9 @@ public:
// suspended the channel.
virtual void NotifySuspendedByCache(bool aSuspendedByCache) final override;
virtual bool IsActive() const final override;
bool IsActive() const;
virtual bool IsHidden() const final override;
bool IsHidden() const;
// Called by the media decoder and the video frame to get the
// ImageContainer containing the video data.
@ -246,7 +246,7 @@ public:
const PrincipalHandle& aNewPrincipalHandle);
// Dispatch events
virtual nsresult DispatchAsyncEvent(const nsAString& aName) final override;
virtual void DispatchAsyncEvent(const nsAString& aName) final override;
// Triggers a recomputation of readyState.
void UpdateReadyState() override { UpdateReadyStateInternal(); }
@ -624,7 +624,7 @@ public:
// data from decoder/reader/MDSM. Used for debugging purposes.
already_AddRefed<Promise> MozRequestDebugInfo(ErrorResult& aRv);
void MozDumpDebugInfo();
already_AddRefed<Promise> MozDumpDebugInfo();
// For use by mochitests. Enabling pref "media.test.video-suspend"
void SetVisible(bool aVisible);

View File

@ -1255,6 +1255,23 @@ MediaCache::Update()
break;
}
// Don't evict |destinationBlockIndex| if it is within [cur, end) otherwise
// a new channel will be opened to download this block again which is bad.
bool inCurrentCachedRange = false;
for (BlockOwner& owner : mIndex[destinationBlockIndex].mOwners) {
MediaCacheStream* stream = owner.mStream;
int64_t end = OffsetToBlockIndexUnchecked(
stream->GetCachedDataEndInternal(stream->mStreamOffset));
int64_t cur = OffsetToBlockIndexUnchecked(stream->mStreamOffset);
if (cur <= owner.mStreamBlock && owner.mStreamBlock < end) {
inCurrentCachedRange = true;
break;
}
}
if (inCurrentCachedRange) {
continue;
}
if (IsBlockFree(destinationBlockIndex) ||
PredictNextUse(now, destinationBlockIndex) > latestPredictedUseForOverflow) {
// Reuse blocks in the main part of the cache that are less useful than

View File

@ -1553,7 +1553,7 @@ MediaDecoder::GetDebugInfo()
PlayStateStr());
}
void
RefPtr<GenericPromise>
MediaDecoder::DumpDebugInfo()
{
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
@ -1568,17 +1568,20 @@ MediaDecoder::DumpDebugInfo()
if (!GetStateMachine()) {
DUMP("%s", str.get());
return;
return GenericPromise::CreateAndResolve(true, __func__);
}
GetStateMachine()->RequestDebugInfo()->Then(
SystemGroup::AbstractMainThreadFor(TaskCategory::Other), __func__,
[str] (const nsACString& aString) {
return GetStateMachine()->RequestDebugInfo()->Then(
SystemGroup::AbstractMainThreadFor(TaskCategory::Other),
__func__,
[str](const nsACString& aString) {
DUMP("%s", str.get());
DUMP("%s", aString.Data());
return GenericPromise::CreateAndResolve(true, __func__);
},
[str] () {
[str]() {
DUMP("%s", str.get());
return GenericPromise::CreateAndResolve(true, __func__);
});
}

View File

@ -389,7 +389,7 @@ private:
// data. Used for debugging purposes.
virtual void GetMozDebugReaderData(nsACString& aString);
virtual void DumpDebugInfo();
RefPtr<GenericPromise> DumpDebugInfo();
using DebugInfoPromise = MozPromise<nsCString, bool, true>;
RefPtr<DebugInfoPromise> RequestDebugInfo();

View File

@ -28,7 +28,7 @@ public:
virtual void DownloadProgressed() = 0;
// Dispatch an asynchronous event to the decoder owner
virtual nsresult DispatchAsyncEvent(const nsAString& aName) = 0;
virtual void DispatchAsyncEvent(const nsAString& aName) = 0;
// Triggers a recomputation of readyState.
virtual void UpdateReadyState() = 0;
@ -118,12 +118,6 @@ public:
NEXT_FRAME_UNINITIALIZED
};
// Check if the decoder owner is active.
virtual bool IsActive() const = 0;
// Check if the decoder owner is hidden.
virtual bool IsHidden() const = 0;
// Called by media decoder when the audible state changed
virtual void SetAudibleState(bool aAudible) = 0;

View File

@ -14,10 +14,7 @@ namespace mozilla
class MockMediaDecoderOwner : public MediaDecoderOwner
{
public:
nsresult DispatchAsyncEvent(const nsAString& aName) override
{
return NS_OK;
}
void DispatchAsyncEvent(const nsAString& aName) override {}
void FireTimeUpdate(bool aPeriodic) override {}
bool GetPaused() override { return false; }
void MetadataLoaded(const MediaInfo* aInfo,
@ -36,8 +33,6 @@ public:
void FirstFrameLoaded() override {}
void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
const nsAString& aInitDataType) override {}
bool IsActive() const override { return true; }
bool IsHidden() const override { return false; }
void DownloadSuspended() override {}
void DownloadResumed(bool aForceNetworkLoading) override {}
void NotifySuspendedByCache(bool aIsSuspended) override {}

View File

@ -1630,8 +1630,6 @@ function MediaTestManager() {
// Instead MediaTestManager will manage timeout of each test.
SimpleTest.requestLongerTimeout(1000);
this.hasTimeout = false;
// Return how many seconds elapsed since |begin|.
function elapsedTime(begin) {
var end = new Date();
@ -1683,10 +1681,10 @@ function MediaTestManager() {
this.numTestsRunning++;
this.handlers[token] = handler;
var onTimeout = () => {
this.hasTimeout = true;
var onTimeout = async () => {
ok(false, "Test timed out!");
info(`${token} timed out!`);
await dumpDebugInfoForToken(token);
this.finished(token);
};
// Default timeout to 180s for each test.
@ -1752,9 +1750,6 @@ function MediaTestManager() {
if (this.onFinished) {
this.onFinished();
}
if (this.hasTimeout) {
dumpDebugInfo();
}
var onCleanup = () => {
var end = new Date();
SimpleTest.info("Finished at " + end + " (" + (end.getTime() / 1000) + "s)");
@ -1789,6 +1784,20 @@ function isSlowPlatform() {
return SpecialPowers.Services.appinfo.name == "B2G" || getAndroidVersion() == 10;
}
async function dumpDebugInfoForToken(token) {
for (let v of document.getElementsByTagName("video")) {
if (token === v.token) {
return v.mozDumpDebugInfo();
}
}
for (let a of document.getElementsByTagName("audio")) {
if (token === a.token) {
return a.mozDumpDebugInfo();
}
}
return Promise.resolve();
}
function dumpDebugInfo() {
for (var v of document.getElementsByTagName("video")) {
v.mozDumpDebugInfo();

View File

@ -108,7 +108,7 @@ partial interface HTMLMediaElement {
Promise<DOMString> mozRequestDebugInfo();
[Pref="media.test.dumpDebugInfo"]
void mozDumpDebugInfo();
Promise<void> mozDumpDebugInfo();
attribute MediaStream? srcObject;

View File

@ -7270,6 +7270,38 @@ nsTextFrame::DrawTextRunAndDecorations(Range aRange,
PaintDecorationLine(params);
};
// We create a clip region in order to draw the decoration lines only in the
// range of the text. Restricting the draw area prevents the decoration lines
// to be drawn multiple times when a part of the text is selected.
// We skip clipping for the following cases:
// - drawing the whole text
// - having different orientation of the text and the writing-mode, such as
// "text-combine-upright" (Bug 1408825)
bool skipClipping = aRange.Length() == mTextRun->GetLength() ||
verticalDec != verticalRun;
gfxRect clipRect;
if (!skipClipping) {
// Get the inline-size according to the specified range.
gfxFloat clipLength = mTextRun->GetAdvanceWidth(aRange, aParams.provider);
clipRect.width = verticalDec ? frameSize.width : clipLength / app;
clipRect.height = verticalDec ? clipLength / app : frameSize.height;
const bool isInlineReversed = mTextRun->IsInlineReversed();
if (verticalDec) {
clipRect.y = (isInlineReversed ? aTextBaselinePt.y - clipLength
: aTextBaselinePt.y) / app;
} else {
clipRect.x = (isInlineReversed ? aTextBaselinePt.x - clipLength
: aTextBaselinePt.x) / app;
}
clipRect.Round();
params.context->Clip(clipRect);
}
// Underlines
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
for (const LineDecoration& dec : Reversed(aDecorations.mUnderlines)) {
@ -7283,6 +7315,12 @@ nsTextFrame::DrawTextRunAndDecorations(Range aRange,
paintDecorationLine(dec, &Metrics::underlineSize, &Metrics::maxAscent);
}
// Some glyphs and emphasis marks may extend outside the region, so we reset
// the clip region here. For an example, italic glyphs.
if (!skipClipping) {
params.context->PopClip();
}
{
gfxContextMatrixAutoSaveRestore unscaledRestorer;
if (scaledRestorer.HasMatrix()) {
@ -7300,12 +7338,21 @@ nsTextFrame::DrawTextRunAndDecorations(Range aRange,
aTextBaselinePt, aParams.framePt, aRange,
aParams.decorationOverrideColor, aParams.provider);
// Re-apply the clip region when the line-through is being drawn.
if (!skipClipping) {
params.context->Clip(clipRect);
}
// Line-throughs
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
for (const LineDecoration& dec : Reversed(aDecorations.mStrikes)) {
paintDecorationLine(dec, &Metrics::strikeoutSize,
&Metrics::strikeoutOffset);
}
if (!skipClipping) {
params.context->PopClip();
}
}
void

View File

@ -34,7 +34,7 @@ fuzzy-if(skiaContent,1,1200) == addrange-2.html addrange-ref.html
== splitText-normalize.html splitText-normalize-ref.html
== modify-range.html modify-range-ref.html
== dom-mutations.html dom-mutations-ref.html
fuzzy-if(OSX==1010,9,1) fuzzy-if(OSX&&skiaContent,6,1) fuzzy-if(skiaContent&&!OSX,1,2138) == trailing-space-1.html trailing-space-1-ref.html
fuzzy-if(OSX==1010,9,1) fuzzy-if(OSX&&skiaContent,6,1) fuzzy-if(skiaContent&&!OSX,1,2138) fails-if(webrender) == trailing-space-1.html trailing-space-1-ref.html # Bug 1414125
!= invalidation-1-ref.html invalidation-2-ref.html
== invalidation-1a.html invalidation-1-ref.html
== invalidation-1b.html invalidation-1-ref.html
@ -48,3 +48,6 @@ fuzzy-if(OSX==1010,9,1) fuzzy-if(OSX&&skiaContent,6,1) fuzzy-if(skiaContent&&!OS
== invalidation-2d.html invalidation-2-ref.html
== invalidation-2e.html invalidation-2-ref.html
== invalidation-2f.html invalidation-2-ref.html
fuzzy(7,2) fuzzy-if(OSX,1,1) fails-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&isDebugBuild&&!browserIsRemote) fails-if(Android) needs-focus == rtl-selection-with-decoration.html rtl-selection-with-decoration-ref.html
fails-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&isDebugBuild&&!browserIsRemote) fails-if(Android) needs-focus == semitransparent-decoration-line.html semitransparent-decoration-line-ref.html
fuzzy-if(OSX,1,6) fails-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&isDebugBuild&&!browserIsRemote) fails-if(Android) needs-focus == writing-mode.html writing-mode-ref.html

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>rtl-selection-with-decoration-ref</title>
<style>
p {
font-size: 2em;
text-decoration-color: rgba(0, 0, 0, 0.3);
}
#text1 {
text-decoration-line: line-through underline;
}
#text2 {
text-decoration-line: line-through overline;
}
</style>
</head>
<body>
<p id="text1" lang="he">זוהי עובדה הקורא שדעתו מבוססת של תהיה</p>
<p id="text2" lang="he" dir="rtl">זוהי עובדה הקורא שדעתו מבוססת של תהיה</p>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>rtl-selection-with-decoration</title>
<style>
p {
font-size: 2em;
text-decoration-color: rgba(0, 0, 0, 0.3);
}
#text1 {
text-decoration-line: line-through underline;
}
#text2 {
text-decoration-line: line-through overline;
}
::-moz-selection {
background-color: white;
color: black;
}
</style>
<script type="text/javascript" charset="utf-8">
function select() {
window.getSelection().removeAllRanges();
var elems = document.getElementsByTagName('p');
for (var i = 0; i < elems.length; ++i) {
var range = document.createRange();
range.setStart(elems[i].firstChild, 2);
range.setEnd(elems[i].firstChild, 9);
window.getSelection().addRange(range);
}
}
</script>
</head>
<body onload="select()">
<p id="text1" lang="he">זוהי עובדה הקורא שדעתו מבוססת של תהיה</p>
<p id="text2" lang="he" dir="rtl">זוהי עובדה הקורא שדעתו מבוססת של תהיה</p>
</body>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>semitransparent-decoration-line-ref</title>
<style>
.underline {
text-decoration: underline rgba(0,0,0,0.3);
font-size: 2em;
}
.overline {
text-decoration: overline rgba(0,0,0,0.3);
font-size: 2em;
}
.line-through {
text-decoration: line-through rgba(0,0,0,0.3);
font-size: 2em;
}
</style>
</head>
<body>
<p class="underline">Lorem ipsum dolor sit amet</p>
<p class="overline">Lorem ipsum dolor sit amet</p>
<p class="line-through">Lorem ipsum dolor sit amet</p>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>semitransparent-decoration-line</title>
<style>
.underline {
text-decoration: underline rgba(0,0,0,0.3);
font-size: 2em;
}
.overline {
text-decoration: overline rgba(0,0,0,0.3);
font-size: 2em;
}
.line-through {
text-decoration: line-through rgba(0,0,0,0.3);
font-size: 2em;
}
::-moz-selection {
background-color: white;
color: black;
}
</style>
<script type="text/javascript" charset="utf-8">
function select() {
window.getSelection().removeAllRanges();
var elems = document.getElementsByTagName('p');
for (var i = 0; i < elems.length; ++i) {
var range = document.createRange();
range.setStart(elems[i].firstChild, 2);
range.setEnd(elems[i].firstChild, 9);
window.getSelection().addRange(range);
}
}
</script>
</head>
<body onload="select()">
<p class="underline">Lorem ipsum dolor sit amet</p>
<p class="overline">Lorem ipsum dolor sit amet</p>
<p class="line-through">Lorem ipsum dolor sit amet</p>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>writing-mode-ref</title>
<style>
p {
display: inline-block;
margin: 10px;
}
.line-through {
text-decoration: line-through wavy rgba(0, 0, 0, 0.3);
}
.wm-vertical-lr {
writing-mode: vertical-lr;
}
.wm-vertical-rl {
writing-mode: vertical-rl;
}
.wm-sideways-lr {
writing-mode: sideways-lr;
}
.wm-sideways-rl {
writing-mode: sideways-rl;
}
</style>
</head>
<body>
<p lang="zh" dir="ltr" class="wm-vertical-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="ltr" class="wm-vertical-rl line-through">你好世界Hello World!</p>
<p lang="zh" dir="ltr" class="wm-sideways-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="ltr" class="wm-sideways-rl line-through">你好世界Hello World!</p>
<br/>
<p lang="zh" dir="rtl" class="wm-vertical-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="rtl" class="wm-vertical-rl line-through">你好世界Hello World!</p>
<p lang="zh" dir="rtl" class="wm-sideways-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="rtl" class="wm-sideways-rl line-through">你好世界Hello World!</p>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>writing-mode</title>
<style>
p {
display: inline-block;
margin: 10px;
}
.line-through {
text-decoration: line-through wavy rgba(0, 0, 0, 0.3);
}
::-moz-selection {
background-color: white;
color: black;
}
.wm-vertical-lr {
writing-mode: vertical-lr;
display: inline-block;
}
.wm-vertical-rl {
writing-mode: vertical-rl;
}
.wm-sideways-lr {
writing-mode: sideways-lr;
}
.wm-sideways-rl {
writing-mode: sideways-rl;
}
</style>
<script type="text/javascript" charset="utf-8">
function select() {
window.getSelection().removeAllRanges();
var elems = document.getElementsByTagName('p');
for (var i = 0; i < elems.length; ++i) {
var range = document.createRange();
range.setStart(elems[i].firstChild, 2);
range.setEnd(elems[i].firstChild, 9);
window.getSelection().addRange(range);
}
}
</script>
</head>
<body onload="select()">
<p lang="zh" dir="ltr" class="wm-vertical-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="ltr" class="wm-vertical-rl line-through">你好世界Hello World!</p>
<p lang="zh" dir="ltr" class="wm-sideways-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="ltr" class="wm-sideways-rl line-through">你好世界Hello World!</p>
<br/>
<p lang="zh" dir="rtl" class="wm-vertical-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="rtl" class="wm-vertical-rl line-through">你好世界Hello World!</p>
<p lang="zh" dir="rtl" class="wm-sideways-lr line-through">你好世界Hello World!</p>
<p lang="zh" dir="rtl" class="wm-sideways-rl line-through">你好世界Hello World!</p>
</body>
</html>

View File

@ -13,7 +13,7 @@ random-if(Android) == basic-negcoord.xul basic-negcoord-ref.xul
!= blur.html blur-notref.html
== color-inherit.html color-inherit-ref.html
== color-parserorder.html color-parserorder-ref.html
== decorations-multiple-zorder.html decorations-multiple-zorder-ref.html
fails-if(webrender) == decorations-multiple-zorder.html decorations-multiple-zorder-ref.html # Bug 1414125
== multiple-noblur.html multiple-noblur-ref.html
== quirks-decor-noblur.html quirks-decor-noblur-ref.html
== standards-decor-noblur.html standards-decor-noblur-ref.html

View File

@ -962,14 +962,16 @@ H264::HasSPS(const mozilla::MediaByteBuffer* aExtraData)
/* static */ uint8_t
H264::NumSPS(const mozilla::MediaByteBuffer* aExtraData)
{
if (!aExtraData) {
if (!aExtraData || aExtraData->IsEmpty()) {
return 0;
}
BufferReader reader(aExtraData);
const uint8_t* ptr = reader.Read(5);
if (!reader.Read(5)) {
return 0;
}
auto res = reader.ReadU8();
if (!ptr || res.isErr()) {
if (res.isErr()) {
return 0;
}
return res.unwrap() & 0x1f;

4
servo/Cargo.lock generated
View File

@ -3476,7 +3476,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.53.1"
source = "git+https://github.com/servo/webrender#82e85d7f407ff38f08fb0901724918704d6d2e4a"
source = "git+https://github.com/servo/webrender#058dd77d35d938974d16dcf12e2f75a0a6e4cdef"
dependencies = [
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3503,7 +3503,7 @@ dependencies = [
[[package]]
name = "webrender_api"
version = "0.53.1"
source = "git+https://github.com/servo/webrender#82e85d7f407ff38f08fb0901724918704d6d2e4a"
source = "git+https://github.com/servo/webrender#058dd77d35d938974d16dcf12e2f75a0a6e4cdef"
dependencies = [
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -14,7 +14,7 @@
interface nsIDOMWindow;
[scriptable, uuid(328daa3e-09e4-455f-bb6f-0a921766042f)]
[scriptable, uuid(72006d06-a2a5-4250-ae92-04b2f0e2ab8d)]
interface nsIPrintingPromptService : nsISupports
{
/**
@ -38,7 +38,6 @@ interface nsIPrintingPromptService : nsISupports
* showPrintDialog - displays a native dialog
* showPageSetup - displays a XUL dialog
* showProgress - displays a XUL dialog
* showPrinterProperties - n/a
*
* Summary for Windows Embedders:
* Stated once again: There is no "fallback" native platform support in GFX for the
@ -49,7 +48,7 @@ interface nsIPrintingPromptService : nsISupports
*
* Note: The Windows version Mozilla implements this service which is
* automatically built and registered for you. You can use it as an example.
* It is located at "mozilla/toolkit/components/printingui/win". That service
* It is located at "widget/windows/nsPrintDialogService.cpp". That service
* is capable of displaying a native print dialog and a XUL progress dialog.
*
* To fly your own dialog you may:
@ -73,20 +72,17 @@ interface nsIPrintingPromptService : nsISupports
* Mac OS9: showPrintDialog - displays a native dialog
* showPageSetup - displays a native dialog
* showProgress - displays a XUL dialog
* showPrinterProperties - n/a
*
*
* Mac OSX: showPrintDialog - displays a native dialog
* showPageSetup - displays a native dialog
* showProgress - not implemented (provided by OS)
* showPrinterProperties - n/a
*
*
* GTK: There are no native dialog for GTK.
*
* Defaults for platform service:
* showPrintDialog - displays a XUL dialog
* showPageSetup - displays a XUL dialog
* Defaults for platform service:
* showPrintDialog - displays a native dialog
* showPageSetup - displays a native dialog
* showProgress - displays a XUL dialog
* showPrinterProperties - displays a XUL dialog
*
*/
@ -141,20 +137,6 @@ interface nsIPrintingPromptService : nsISupports
in nsIPrintSettings printSettings,
in nsIObserver aObs);
/**
* Sometimes platforms need to bring up a special properties dialog for showing
* print specific properties. Although the PrintSettings has a place to set the
* printer name, here is is an argument to be clear as to what printer is being
* asked to have the properties set for it. The Printer name in the PS is ignored.
*
* @param parent - a DOM windows the dialog will be parented to (required)
* @param printerName - name of printer (required)
* @param printSettings - PrintSettings for page setup (required)
*/
void showPrinterProperties(in mozIDOMWindowProxy parent,
in wstring printerName,
in nsIPrintSettings printSettings);
};
%{C++

View File

@ -1,408 +0,0 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* 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/. */
var dialog;
var printService = null;
var gOriginalNumCopies = 1;
var paramBlock;
var gPrefs = null;
var gPrintSettings = null;
var gWebBrowserPrint = null;
var gPrintSetInterface = Components.interfaces.nsIPrintSettings;
var doDebug = false;
// ---------------------------------------------------
function initDialog() {
dialog = {};
dialog.propertiesButton = document.getElementById("properties");
dialog.descText = document.getElementById("descText");
dialog.printrangeGroup = document.getElementById("printrangeGroup");
dialog.allpagesRadio = document.getElementById("allpagesRadio");
dialog.rangeRadio = document.getElementById("rangeRadio");
dialog.selectionRadio = document.getElementById("selectionRadio");
dialog.frompageInput = document.getElementById("frompageInput");
dialog.frompageLabel = document.getElementById("frompageLabel");
dialog.topageInput = document.getElementById("topageInput");
dialog.topageLabel = document.getElementById("topageLabel");
dialog.numCopiesInput = document.getElementById("numCopiesInput");
dialog.printframeGroup = document.getElementById("printframeGroup");
dialog.aslaidoutRadio = document.getElementById("aslaidoutRadio");
dialog.selectedframeRadio = document.getElementById("selectedframeRadio");
dialog.eachframesepRadio = document.getElementById("eachframesepRadio");
dialog.printframeGroupLabel = document.getElementById("printframeGroupLabel");
dialog.fileCheck = document.getElementById("fileCheck");
dialog.printerLabel = document.getElementById("printerLabel");
dialog.printerList = document.getElementById("printerList");
dialog.printButton = document.documentElement.getButton("accept");
// <data> elements
dialog.printName = document.getElementById("printButton");
dialog.fpDialog = document.getElementById("fpDialog");
dialog.enabled = false;
}
// ---------------------------------------------------
function checkInteger(element) {
var value = element.value;
if (value && value.length > 0) {
value = value.replace(/[^0-9]/g, "");
if (!value) value = "";
element.value = value;
}
if (!value || value < 1 || value > 999)
dialog.printButton.setAttribute("disabled", "true");
else
dialog.printButton.removeAttribute("disabled");
}
// ---------------------------------------------------
function stripTrailingWhitespace(element) {
var value = element.value;
value = value.replace(/\s+$/, "");
element.value = value;
}
// ---------------------------------------------------
function getPrinterDescription(printerName) {
return gPrefs.getCharPref("print.printer_" + printerName + ".printer_description", "");
}
// ---------------------------------------------------
function listElement(aListElement) {
this.listElement = aListElement;
}
listElement.prototype =
{
clearList() {
// remove the menupopup node child of the menulist.
var popup = this.listElement.firstChild;
if (popup) {
this.listElement.removeChild(popup);
}
},
appendPrinterNames(aDataObject) {
if ((null == aDataObject) || !aDataObject.hasMore()) {
// disable dialog
this.listElement.setAttribute("value", "");
this.listElement.setAttribute("label",
document.getElementById("printingBundle")
.getString("noprinter"));
this.listElement.setAttribute("disabled", "true");
dialog.printerLabel.setAttribute("disabled", "true");
dialog.propertiesButton.setAttribute("disabled", "true");
dialog.fileCheck.setAttribute("disabled", "true");
dialog.printButton.setAttribute("disabled", "true");
} else {
// build popup menu from printer names
var list = document.getElementById("printerList");
do {
let printerNameStr = aDataObject.getNext();
list.appendItem(printerNameStr, printerNameStr, getPrinterDescription(printerNameStr));
} while (aDataObject.hasMore());
this.listElement.removeAttribute("disabled");
}
}
};
// ---------------------------------------------------
function getPrinters() {
var selectElement = new listElement(dialog.printerList);
selectElement.clearList();
var printerEnumerator;
try {
printerEnumerator =
Components.classes["@mozilla.org/gfx/printerenumerator;1"]
.getService(Components.interfaces.nsIPrinterEnumerator)
.printerNameList;
} catch (e) { printerEnumerator = null; }
selectElement.appendPrinterNames(printerEnumerator);
selectElement.listElement.value = printService.defaultPrinterName;
// make sure we load the prefs for the initially selected printer
setPrinterDefaultsForSelectedPrinter();
}
// ---------------------------------------------------
// update gPrintSettings with the defaults for the selected printer
function setPrinterDefaultsForSelectedPrinter() {
gPrintSettings.printerName = dialog.printerList.value;
dialog.descText.value = getPrinterDescription(gPrintSettings.printerName);
// First get any defaults from the printer
printService.initPrintSettingsFromPrinter(gPrintSettings.printerName, gPrintSettings);
// now augment them with any values from last time
printService.initPrintSettingsFromPrefs(gPrintSettings, true, gPrintSetInterface.kInitSaveAll);
if (doDebug) {
dump("setPrinterDefaultsForSelectedPrinter: printerName='" + gPrintSettings.printerName + "', paperName='" + gPrintSettings.paperName + "'\n");
}
}
// ---------------------------------------------------
function displayPropertiesDialog() {
gPrintSettings.numCopies = dialog.numCopiesInput.value;
try {
var printingPromptService = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
.getService(Components.interfaces.nsIPrintingPromptService);
if (printingPromptService) {
printingPromptService.showPrinterProperties(null, dialog.printerList.value, gPrintSettings);
dialog.numCopiesInput.value = gPrintSettings.numCopies;
}
} catch (e) {
dump("problems getting printingPromptService\n");
}
}
// ---------------------------------------------------
function doPrintRange(inx) {
if (inx == 1) {
dialog.frompageInput.removeAttribute("disabled");
dialog.frompageLabel.removeAttribute("disabled");
dialog.topageInput.removeAttribute("disabled");
dialog.topageLabel.removeAttribute("disabled");
} else {
dialog.frompageInput.setAttribute("disabled", "true");
dialog.frompageLabel.setAttribute("disabled", "true");
dialog.topageInput.setAttribute("disabled", "true");
dialog.topageLabel.setAttribute("disabled", "true");
}
}
// ---------------------------------------------------
function loadDialog() {
var print_copies = 1;
var print_selection_radio_enabled = false;
var print_frametype = gPrintSetInterface.kSelectedFrame;
var print_howToEnableUI = gPrintSetInterface.kFrameEnableNone;
var print_tofile = "";
try {
gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"];
if (printService) {
printService = printService.getService();
if (printService) {
printService = printService.QueryInterface(Components.interfaces.nsIPrintSettingsService);
}
}
} catch (e) {}
// Note: getPrinters sets up the PrintToFile control
getPrinters();
if (gPrintSettings) {
print_tofile = gPrintSettings.printToFile;
gOriginalNumCopies = gPrintSettings.numCopies;
print_copies = gPrintSettings.numCopies;
print_frametype = gPrintSettings.printFrameType;
print_howToEnableUI = gPrintSettings.howToEnableFrameUI;
print_selection_radio_enabled = gPrintSettings.GetPrintOptions(gPrintSetInterface.kEnableSelectionRB);
}
if (doDebug) {
dump("loadDialog*********************************************\n");
dump("print_tofile " + print_tofile + "\n");
dump("print_frame " + print_frametype + "\n");
dump("print_howToEnableUI " + print_howToEnableUI + "\n");
dump("selection_radio_enabled " + print_selection_radio_enabled + "\n");
}
dialog.printrangeGroup.selectedItem = dialog.allpagesRadio;
if (print_selection_radio_enabled) {
dialog.selectionRadio.removeAttribute("disabled");
} else {
dialog.selectionRadio.setAttribute("disabled", "true");
}
doPrintRange(dialog.rangeRadio.selected);
dialog.frompageInput.value = 1;
dialog.topageInput.value = 1;
dialog.numCopiesInput.value = print_copies;
if (doDebug) {
dump("print_howToEnableUI: " + print_howToEnableUI + "\n");
}
// print frame
if (print_howToEnableUI == gPrintSetInterface.kFrameEnableAll) {
dialog.aslaidoutRadio.removeAttribute("disabled");
dialog.selectedframeRadio.removeAttribute("disabled");
dialog.eachframesepRadio.removeAttribute("disabled");
dialog.printframeGroupLabel.removeAttribute("disabled");
// initialize radio group
dialog.printframeGroup.selectedItem = dialog.selectedframeRadio;
} else if (print_howToEnableUI == gPrintSetInterface.kFrameEnableAsIsAndEach) {
dialog.aslaidoutRadio.removeAttribute("disabled"); // enable
dialog.selectedframeRadio.setAttribute("disabled", "true"); // disable
dialog.eachframesepRadio.removeAttribute("disabled"); // enable
dialog.printframeGroupLabel.removeAttribute("disabled"); // enable
// initialize
dialog.printframeGroup.selectedItem = dialog.eachframesepRadio;
} else {
dialog.aslaidoutRadio.setAttribute("disabled", "true");
dialog.selectedframeRadio.setAttribute("disabled", "true");
dialog.eachframesepRadio.setAttribute("disabled", "true");
dialog.printframeGroupLabel.setAttribute("disabled", "true");
}
dialog.printButton.label = dialog.printName.getAttribute("label");
}
// ---------------------------------------------------
function onLoad() {
// Init dialog.
initDialog();
// param[0]: nsIPrintSettings object
// param[1]: container for return value (1 = print, 0 = cancel)
gPrintSettings = window.arguments[0].QueryInterface(gPrintSetInterface);
gWebBrowserPrint = window.arguments[1].QueryInterface(Components.interfaces.nsIWebBrowserPrint);
paramBlock = window.arguments[2].QueryInterface(Components.interfaces.nsIDialogParamBlock);
// default return value is "cancel"
paramBlock.SetInt(0, 0);
loadDialog();
}
// ---------------------------------------------------
function onAccept() {
let promise;
if (gPrintSettings == null) {
promise = Promise.resolve();
} else {
var print_howToEnableUI = gPrintSetInterface.kFrameEnableNone;
// save these out so they can be picked up by the device spec
gPrintSettings.printerName = dialog.printerList.value;
print_howToEnableUI = gPrintSettings.howToEnableFrameUI;
gPrintSettings.printToFile = dialog.fileCheck.checked;
if (gPrintSettings.printToFile) {
promise = chooseFile();
} else {
promise = Promise.resolve();
}
promise = promise.then(() => {
if (dialog.allpagesRadio.selected) {
gPrintSettings.printRange = gPrintSetInterface.kRangeAllPages;
} else if (dialog.rangeRadio.selected) {
gPrintSettings.printRange = gPrintSetInterface.kRangeSpecifiedPageRange;
} else if (dialog.selectionRadio.selected) {
gPrintSettings.printRange = gPrintSetInterface.kRangeSelection;
}
gPrintSettings.startPageRange = dialog.frompageInput.value;
gPrintSettings.endPageRange = dialog.topageInput.value;
gPrintSettings.numCopies = dialog.numCopiesInput.value;
var frametype = gPrintSetInterface.kNoFrames;
if (print_howToEnableUI != gPrintSetInterface.kFrameEnableNone) {
if (dialog.aslaidoutRadio.selected) {
frametype = gPrintSetInterface.kFramesAsIs;
} else if (dialog.selectedframeRadio.selected) {
frametype = gPrintSetInterface.kSelectedFrame;
} else if (dialog.eachframesepRadio.selected) {
frametype = gPrintSetInterface.kEachFrameSep;
} else {
frametype = gPrintSetInterface.kSelectedFrame;
}
}
gPrintSettings.printFrameType = frametype;
if (doDebug) {
dump("onAccept*********************************************\n");
dump("frametype " + frametype + "\n");
dump("numCopies " + gPrintSettings.numCopies + "\n");
dump("printRange " + gPrintSettings.printRange + "\n");
dump("printerName " + gPrintSettings.printerName + "\n");
dump("startPageRange " + gPrintSettings.startPageRange + "\n");
dump("endPageRange " + gPrintSettings.endPageRange + "\n");
dump("printToFile " + gPrintSettings.printToFile + "\n");
}
});
}
promise.then(() => {
var saveToPrefs = false;
saveToPrefs = gPrefs.getBoolPref("print.save_print_settings");
if (saveToPrefs && printService != null) {
var flags = gPrintSetInterface.kInitSavePaperSize |
gPrintSetInterface.kInitSaveEdges |
gPrintSetInterface.kInitSaveInColor |
gPrintSetInterface.kInitSaveShrinkToFit |
gPrintSetInterface.kInitSaveScaling;
printService.savePrintSettingsToPrefs(gPrintSettings, true, flags);
}
// set return value to "print"
if (paramBlock) {
paramBlock.SetInt(0, 1);
} else {
dump("*** FATAL ERROR: No paramBlock\n");
}
window.close();
});
return false;
}
// ---------------------------------------------------
function onCancel() {
// set return value to "cancel"
if (paramBlock) {
paramBlock.SetInt(0, 0);
} else {
dump("*** FATAL ERROR: No paramBlock\n");
}
return true;
}
// ---------------------------------------------------
const nsIFilePicker = Components.interfaces.nsIFilePicker;
function chooseFile() {
return new Promise(resolve => {
var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
fp.init(window, dialog.fpDialog.getAttribute("label"), nsIFilePicker.modeSave);
fp.appendFilters(nsIFilePicker.filterAll);
fp.open(rv => {
if (rv != Components.interfaces.nsIFilePicker.returnCancel &&
fp.file && fp.file.path) {
gPrintSettings.toFileName = fp.file.path;
resolve(null);
}
});
});
}

View File

@ -1,126 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://global/locale/printdialog.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
ondialogaccept="return onAccept();"
oncancel="return onCancel();"
buttoniconaccept="print"
title="&printDialog.title;"
persist="screenX screenY"
screenX="24" screenY="24">
<script type="application/javascript" src="chrome://global/content/printdialog.js"/>
<stringbundle id="printingBundle" src="chrome://global/locale/printing.properties"/>
<groupbox>
<caption label="&printer.label;"/>
<grid>
<columns>
<column/>
<column flex="1"/>
<column/>
</columns>
<rows>
<row align="center">
<hbox align="center" pack="end">
<label id="printerLabel"
value="&printerInput.label;"
accesskey="&printerInput.accesskey;"
control="printerList"/>
</hbox>
<menulist id="printerList" flex="1" type="description" oncommand="setPrinterDefaultsForSelectedPrinter();"/>
<button id="properties"
label="&propertiesButton.label;"
accesskey="&propertiesButton.accesskey;"
icon="properties"
oncommand="displayPropertiesDialog();"/>
</row>
<row align="center">
<hbox align="center" pack="end">
<label id="descTextLabel" control="descText" value="&descText.label;"/>
</hbox>
<label id="descText"/>
<checkbox id="fileCheck"
checked="false"
label="&fileCheck.label;"
accesskey="&fileCheck.accesskey;"
pack="end"/>
</row>
</rows>
</grid>
</groupbox>
<hbox>
<groupbox flex="1">
<caption label="&printrangeGroup.label;"/>
<radiogroup id="printrangeGroup">
<radio id="allpagesRadio"
label="&allpagesRadio.label;"
accesskey="&allpagesRadio.accesskey;"
oncommand="doPrintRange(0)"/>
<hbox align="center">
<radio id="rangeRadio"
label="&rangeRadio.label;"
accesskey="&rangeRadio.accesskey;"
oncommand="doPrintRange(1)"/>
<label id="frompageLabel"
control="frompageInput"
value="&frompageInput.label;"
accesskey="&frompageInput.accesskey;"/>
<textbox id="frompageInput" style="width:5em;" onkeyup="checkInteger(this)"/>
<label id="topageLabel"
control="topageInput"
value="&topageInput.label;"
accesskey="&topageInput.accesskey;"/>
<textbox id="topageInput" style="width:5em;" onkeyup="checkInteger(this)"/>
</hbox>
<radio id="selectionRadio"
label="&selectionRadio.label;"
accesskey="&selectionRadio.accesskey;"
oncommand="doPrintRange(2)"/>
</radiogroup>
</groupbox>
<groupbox flex="1">
<caption label="&copies.label;"/>
<hbox align="center">
<label control="numCopiesInput"
value="&numCopies.label;"
accesskey="&numCopies.accesskey;"/>
<textbox id="numCopiesInput" style="width:5em;" onkeyup="checkInteger(this)"/>
</hbox>
</groupbox>
</hbox>
<groupbox flex="1">
<caption label="&printframeGroup.label;" id="printframeGroupLabel"/>
<radiogroup id="printframeGroup">
<radio id="aslaidoutRadio"
label="&aslaidoutRadio.label;"
accesskey="&aslaidoutRadio.accesskey;"/>
<radio id="selectedframeRadio"
label="&selectedframeRadio.label;"
accesskey="&selectedframeRadio.accesskey;"/>
<radio id="eachframesepRadio"
label="&eachframesepRadio.label;"
accesskey="&eachframesepRadio.accesskey;"/>
</radiogroup>
</groupbox>
<!-- used to store titles and labels -->
<data style="display:none;" id="printButton" label="&printButton.label;"/>
<data style="display:none;" id="fpDialog" label="&fpDialog.title;"/>
</dialog>

View File

@ -1,373 +0,0 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* 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/. */
var dialog;
var gPrintBundle;
var gPrintSettings = null;
var gPrintSettingsInterface = Components.interfaces.nsIPrintSettings;
var gPaperArray;
var gPrefs;
var gParamBlock;
var gPrintSetInterface = Components.interfaces.nsIPrintSettings;
var doDebug = true;
// ---------------------------------------------------
function checkDouble(element, maxVal) {
var value = element.value;
if (value && value.length > 0) {
value = value.replace(/[^\.|^0-9]/g, "");
if (!value) {
element.value = "";
} else if (value > maxVal) {
element.value = maxVal;
} else {
element.value = value;
}
}
}
// ---------------------------------------------------
function isListOfPrinterFeaturesAvailable() {
return gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".has_special_printerfeatures", false);
}
// ---------------------------------------------------
function getDoubleStr(val, dec) {
var str = val.toString();
var inx = str.indexOf(".");
return str.substring(0, inx + dec + 1);
}
// ---------------------------------------------------
function initDialog() {
gPrintBundle = document.getElementById("printBundle");
dialog = {};
dialog.paperList = document.getElementById("paperList");
dialog.paperGroup = document.getElementById("paperGroup");
dialog.jobTitleLabel = document.getElementById("jobTitleLabel");
dialog.jobTitleGroup = document.getElementById("jobTitleGroup");
dialog.jobTitleInput = document.getElementById("jobTitleInput");
dialog.colorGroup = document.getElementById("colorGroup");
dialog.colorRadioGroup = document.getElementById("colorRadioGroup");
dialog.colorRadio = document.getElementById("colorRadio");
dialog.grayRadio = document.getElementById("grayRadio");
dialog.topInput = document.getElementById("topInput");
dialog.bottomInput = document.getElementById("bottomInput");
dialog.leftInput = document.getElementById("leftInput");
dialog.rightInput = document.getElementById("rightInput");
}
// ---------------------------------------------------
function round10(val) {
return Math.round(val * 10) / 10;
}
// ---------------------------------------------------
function paperListElement(aPaperListElement) {
this.paperListElement = aPaperListElement;
}
paperListElement.prototype =
{
clearPaperList() {
// remove the menupopup node child of the menulist.
this.paperListElement.firstChild.remove();
},
appendPaperNames(aDataObject) {
var popupNode = document.createElement("menupopup");
for (var i = 0;i < aDataObject.length;i++) {
var paperObj = aDataObject[i];
var itemNode = document.createElement("menuitem");
var label;
try {
label = gPrintBundle.getString(paperObj.name);
} catch (e) {
/* No name in string bundle ? Then build one manually (this
* usually happens when gPaperArray was build by createPaperArrayFromPrinterFeatures() ...) */
if (paperObj.inches) {
label = paperObj.name + " (" + round10(paperObj.width) + "x" + round10(paperObj.height) + " inch)";
} else {
label = paperObj.name + " (" + paperObj.width + "x" + paperObj.height + " mm)";
}
}
itemNode.setAttribute("label", label);
itemNode.setAttribute("value", i);
popupNode.appendChild(itemNode);
}
this.paperListElement.appendChild(popupNode);
}
};
// ---------------------------------------------------
function createPaperArrayFromDefaults() {
var paperNames = ["letterSize", "legalSize", "exectiveSize", "a5Size", "a4Size", "a3Size", "a2Size", "a1Size", "a0Size"];
// var paperNames = ["&letterRadio.label;", "&legalRadio.label;", "&exectiveRadio.label;", "&a4Radio.label;", "&a3Radio.label;"];
var paperWidths = [ 8.5, 8.5, 7.25, 148.0, 210.0, 287.0, 420.0, 594.0, 841.0];
var paperHeights = [11.0, 14.0, 10.50, 210.0, 297.0, 420.0, 594.0, 841.0, 1189.0];
var paperInches = [true, true, true, false, false, false, false, false, false];
gPaperArray = [];
for (var i = 0;i < paperNames.length;i++) {
var obj = {};
obj.name = paperNames[i];
obj.width = paperWidths[i];
obj.height = paperHeights[i];
obj.inches = paperInches[i];
/* Calculate the width/height in millimeters */
if (paperInches[i]) {
obj.width_mm = paperWidths[i] * 25.4;
obj.height_mm = paperHeights[i] * 25.4;
} else {
obj.width_mm = paperWidths[i];
obj.height_mm = paperHeights[i];
}
gPaperArray[i] = obj;
}
}
// ---------------------------------------------------
function createPaperArrayFromPrinterFeatures() {
var printername = gPrintSettings.printerName;
if (doDebug) {
dump("createPaperArrayFromPrinterFeatures for " + printername + ".\n");
}
gPaperArray = [];
var numPapers = gPrefs.getIntPref("print.tmp.printerfeatures." + printername + ".paper.count");
if (doDebug) {
dump("processing " + numPapers + " entries...\n");
}
for (var i = 0;i < numPapers;i++) {
var obj = {};
obj.name = gPrefs.getCharPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".name");
obj.width_mm = gPrefs.getIntPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".width_mm");
obj.height_mm = gPrefs.getIntPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".height_mm");
obj.inches = gPrefs.getBoolPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".is_inch");
/* Calculate the width/height in paper's native units (either inches or millimeters) */
if (obj.inches) {
obj.width = obj.width_mm / 25.4;
obj.height = obj.height_mm / 25.4;
} else {
obj.width = obj.width_mm;
obj.height = obj.height_mm;
}
gPaperArray[i] = obj;
if (doDebug) {
dump("paper index=" + i + ", name=" + obj.name + ", width=" + obj.width + ", height=" + obj.height + ".\n");
}
}
}
// ---------------------------------------------------
function createPaperArray() {
if (isListOfPrinterFeaturesAvailable()) {
createPaperArrayFromPrinterFeatures();
} else {
createPaperArrayFromDefaults();
}
}
// ---------------------------------------------------
function createPaperSizeList(selectedInx) {
var selectElement = new paperListElement(dialog.paperList);
selectElement.clearPaperList();
selectElement.appendPaperNames(gPaperArray);
if (selectedInx > -1) {
selectElement.paperListElement.selectedIndex = selectedInx;
}
// dialog.paperList = selectElement;
}
// ---------------------------------------------------
function loadDialog() {
var print_paper_unit = 0;
var print_paper_width = 0.0;
var print_paper_height = 0.0;
var print_paper_name = "";
var print_color = true;
var print_jobtitle = "";
gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
if (gPrintSettings) {
print_paper_unit = gPrintSettings.paperSizeUnit;
print_paper_width = gPrintSettings.paperWidth;
print_paper_height = gPrintSettings.paperHeight;
print_paper_name = gPrintSettings.paperName;
print_color = gPrintSettings.printInColor;
print_jobtitle = gPrintSettings.title;
}
if (doDebug) {
dump("loadDialog******************************\n");
dump("paperSizeType " + print_paper_unit + "\n");
dump("paperWidth " + print_paper_width + "\n");
dump("paperHeight " + print_paper_height + "\n");
dump("paperName " + print_paper_name + "\n");
dump("print_color " + print_color + "\n");
dump("print_jobtitle " + print_jobtitle + "\n");
}
createPaperArray();
var paperSelectedInx = 0;
for (var i = 0;i < gPaperArray.length;i++) {
if (print_paper_name == gPaperArray[i].name) {
paperSelectedInx = i;
break;
}
}
if (doDebug) {
if (i == gPaperArray.length)
dump("loadDialog: No paper found.\n");
else
dump("loadDialog: found paper '" + gPaperArray[paperSelectedInx].name + "'.\n");
}
createPaperSizeList(paperSelectedInx);
/* Enable/disable and/or hide/unhide widgets based in the information
* whether the selected printer and/or print module supports the matching
* feature or not */
if (isListOfPrinterFeaturesAvailable()) {
// job title
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_jobtitle"))
dialog.jobTitleInput.removeAttribute("disabled");
else
dialog.jobTitleInput.setAttribute("disabled", "true");
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".supports_jobtitle_change"))
dialog.jobTitleGroup.removeAttribute("hidden");
else
dialog.jobTitleGroup.setAttribute("hidden", "true");
// paper size
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_paper_size"))
dialog.paperList.removeAttribute("disabled");
else
dialog.paperList.setAttribute("disabled", "true");
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".supports_paper_size_change"))
dialog.paperGroup.removeAttribute("hidden");
else
dialog.paperGroup.setAttribute("hidden", "true");
// color/grayscale radio
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_printincolor"))
dialog.colorRadioGroup.removeAttribute("disabled");
else
dialog.colorRadioGroup.setAttribute("disabled", "true");
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".supports_printincolor_change"))
dialog.colorGroup.removeAttribute("hidden");
else
dialog.colorGroup.setAttribute("hidden", "true");
}
if (print_color) {
dialog.colorRadioGroup.selectedItem = dialog.colorRadio;
} else {
dialog.colorRadioGroup.selectedItem = dialog.grayRadio;
}
dialog.jobTitleInput.value = print_jobtitle;
dialog.topInput.value = gPrintSettings.edgeTop.toFixed(2);
dialog.bottomInput.value = gPrintSettings.edgeBottom.toFixed(2);
dialog.leftInput.value = gPrintSettings.edgeLeft.toFixed(2);
dialog.rightInput.value = gPrintSettings.edgeRight.toFixed(2);
}
// ---------------------------------------------------
function onLoad() {
// Init dialog.
initDialog();
gPrintSettings = window.arguments[0].QueryInterface(gPrintSetInterface);
gParamBlock = window.arguments[1].QueryInterface(Components.interfaces.nsIDialogParamBlock);
if (doDebug) {
if (gPrintSettings == null) alert("PrintSettings is null!");
if (gParamBlock == null) alert("nsIDialogParam is null!");
}
// default return value is "cancel"
gParamBlock.SetInt(0, 0);
loadDialog();
}
// ---------------------------------------------------
function onAccept() {
var print_paper_unit = gPrintSettingsInterface.kPaperSizeInches;
var print_paper_width = 0.0;
var print_paper_height = 0.0;
var print_paper_name = "";
if (gPrintSettings != null) {
var paperSelectedInx = dialog.paperList.selectedIndex;
if (gPaperArray[paperSelectedInx].inches) {
print_paper_unit = gPrintSettingsInterface.kPaperSizeInches;
} else {
print_paper_unit = gPrintSettingsInterface.kPaperSizeMillimeters;
}
print_paper_width = gPaperArray[paperSelectedInx].width;
print_paper_height = gPaperArray[paperSelectedInx].height;
print_paper_name = gPaperArray[paperSelectedInx].name;
gPrintSettings.paperSizeUnit = print_paper_unit;
gPrintSettings.paperWidth = print_paper_width;
gPrintSettings.paperHeight = print_paper_height;
gPrintSettings.paperName = print_paper_name;
// save these out so they can be picked up by the device spec
gPrintSettings.printInColor = dialog.colorRadio.selected;
gPrintSettings.title = dialog.jobTitleInput.value;
gPrintSettings.edgeTop = dialog.topInput.value;
gPrintSettings.edgeBottom = dialog.bottomInput.value;
gPrintSettings.edgeLeft = dialog.leftInput.value;
gPrintSettings.edgeRight = dialog.rightInput.value;
if (doDebug) {
dump("onAccept******************************\n");
dump("paperSizeUnit " + print_paper_unit + "\n");
dump("paperWidth " + print_paper_width + "\n");
dump("paperHeight " + print_paper_height + "\n");
dump("paperName '" + print_paper_name + "'\n");
dump("printInColor " + gPrintSettings.printInColor + "\n");
}
} else {
dump("************ onAccept gPrintSettings: " + gPrintSettings + "\n");
}
if (gParamBlock) {
// set return value to "ok"
gParamBlock.SetInt(0, 1);
} else {
dump("*** FATAL ERROR: paramBlock missing\n");
}
return true;
}

View File

@ -1,110 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://global/locale/printjoboptions.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
ondialogaccept="return onAccept();"
title="&printJobOptions.title;"
persist="screenX screenY"
screenX="24" screenY="24">
<script type="application/javascript" src="chrome://global/content/printjoboptions.js"/>
<stringbundle id="printBundle" src="chrome://global/locale/printPageSetup.properties"/>
<grid>
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row id="jobTitleGroup">
<hbox align="center" pack="end">
<label id="jobTitleLabel"
value="&jobTitleInput.label;"
accesskey="&jobTitleInput.accesskey;"
control="jobTitleInput"/>
</hbox>
<textbox id="jobTitleInput" flex="1"/>
</row>
<row id="paperGroup">
<hbox align="center" pack="end">
<label id="paperLabel"
value="&paperInput.label;"
accesskey="&paperInput.accesskey;"
control="paperList"/>
</hbox>
<menulist id="paperList" flex="1">
<menupopup/>
</menulist>
</row>
<row id="colorGroup">
<hbox align="center" pack="end">
<label control="colorRadioGroup" value="&colorGroup.label;"/>
</hbox>
<radiogroup id="colorRadioGroup" orient="horizontal">
<radio id="grayRadio"
label="&grayRadio.label;"
accesskey="&grayRadio.accesskey;"/>
<radio id="colorRadio"
label="&colorRadio.label;"
accesskey="&colorRadio.accesskey;"/>
</radiogroup>
</row>
</rows>
</grid>
<grid>
<columns>
<column/>
</columns>
<rows>
<row>
<groupbox flex="1">
<caption label="&edgeMarginInput.label;"/>
<hbox>
<hbox align="center">
<label id="topLabel"
value="&topInput.label;"
accesskey="&topInput.accesskey;"
control="topInput"/>
<textbox id="topInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
<hbox align="center">
<label id="bottomLabel"
value="&bottomInput.label;"
accesskey="&bottomInput.accesskey;"
control="bottomInput"/>
<textbox id="bottomInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
<hbox align="center">
<label id="leftLabel"
value="&leftInput.label;"
accesskey="&leftInput.accesskey;"
control="leftInput"/>
<textbox id="leftInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
<hbox align="center">
<label id="rightLabel"
value="&rightInput.label;"
accesskey="&rightInput.accesskey;"
control="rightInput"/>
<textbox id="rightInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
</hbox>
</groupbox>
</row>
</rows>
</grid>
</dialog>

View File

@ -4,14 +4,10 @@
toolkit.jar:
#ifndef XP_MACOSX
#ifdef XP_UNIX
content/global/printdialog.js (content/printdialog.js)
content/global/printdialog.xul (content/printdialog.xul)
content/global/printjoboptions.js (content/printjoboptions.js)
content/global/printjoboptions.xul (content/printjoboptions.xul)
#endif
#ifdef XP_WIN
content/global/printPageSetup.js (content/printPageSetup.js)
content/global/printPageSetup.xul (content/printPageSetup.xul)
#endif
content/global/printPreviewProgress.js (content/printPreviewProgress.js)
content/global/printPreviewProgress.xul (content/printPreviewProgress.xul)
content/global/printProgress.js (content/printProgress.js)

View File

@ -188,14 +188,6 @@ nsPrintingProxy::ShowPageSetup(mozIDOMWindowProxy *parent,
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsPrintingProxy::ShowPrinterProperties(mozIDOMWindowProxy *parent,
const char16_t *printerName,
nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsPrintingProxy::SavePrintSettings(nsIPrintSettings* aPS,
bool aUsePrinterNamePrefix,

View File

@ -72,12 +72,6 @@ nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent, nsIPrintSetti
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent, const char16_t *printerName, nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//*****************************************************************************
// nsPrintingPromptService::nsIWebProgressListener

View File

@ -5,9 +5,6 @@
#include "nsPrintingPromptService.h"
#include "nsArray.h"
#include "nsIComponentManager.h"
#include "nsIDialogParamBlock.h"
#include "nsIDOMWindow.h"
#include "nsIServiceManager.h"
#include "nsISupportsUtils.h"
@ -18,40 +15,8 @@
#include "nsPrintProgress.h"
#include "nsPrintProgressParams.h"
static const char *kPrintDialogURL = "chrome://global/content/printdialog.xul";
static const char *kPrintProgressDialogURL = "chrome://global/content/printProgress.xul";
static const char *kPrtPrvProgressDialogURL = "chrome://global/content/printPreviewProgress.xul";
static const char *kPageSetupDialogURL = "chrome://global/content/printPageSetup.xul";
static const char *kPrinterPropertiesURL = "chrome://global/content/printjoboptions.xul";
/****************************************************************
************************* ParamBlock ***************************
****************************************************************/
class ParamBlock {
public:
ParamBlock()
{
mBlock = 0;
}
~ParamBlock()
{
NS_IF_RELEASE(mBlock);
}
nsresult Init() {
return CallCreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &mBlock);
}
nsIDialogParamBlock * operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mBlock; }
operator nsIDialogParamBlock * () const { return mBlock; }
private:
nsIDialogParamBlock *mBlock;
};
/****************************************************************
***************** nsPrintingPromptService **********************
****************************************************************/
NS_IMPL_ISUPPORTS(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener)
@ -79,21 +44,13 @@ nsPrintingPromptService::ShowPrintDialog(mozIDOMWindowProxy *parent,
NS_ENSURE_ARG(webBrowserPrint);
NS_ENSURE_ARG(printSettings);
// Try to access a component dialog
nsCOMPtr<nsIPrintDialogService> dlgPrint(do_GetService(
NS_PRINTDIALOGSERVICE_CONTRACTID));
if (dlgPrint)
return dlgPrint->Show(nsPIDOMWindowOuter::From(parent),
printSettings, webBrowserPrint);
// Show the built-in dialog instead
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
return DoDialog(parent, block, webBrowserPrint, printSettings, kPrintDialogURL);
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -143,110 +100,15 @@ nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent,
{
NS_ENSURE_ARG(printSettings);
// Try to access a component dialog
nsCOMPtr<nsIPrintDialogService> dlgPrint(do_GetService(
NS_PRINTDIALOGSERVICE_CONTRACTID));
if (dlgPrint)
return dlgPrint->ShowPageSetup(nsPIDOMWindowOuter::From(parent),
printSettings);
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
return DoDialog(parent, block, nullptr, printSettings, kPageSetupDialogURL);
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent,
const char16_t *printerName,
nsIPrintSettings *printSettings)
{
/* fixme: We simply ignore the |aPrinter| argument here
* We should get the supported printer attributes from the printer and
* populate the print job options dialog with these data instead of using
* the "default set" here.
* However, this requires changes on all platforms and is another big chunk
* of patches ... ;-(
*/
NS_ENSURE_ARG(printerName);
NS_ENSURE_ARG(printSettings);
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
return DoDialog(parent, block, nullptr, printSettings, kPrinterPropertiesURL);
}
nsresult
nsPrintingPromptService::DoDialog(mozIDOMWindowProxy *aParent,
nsIDialogParamBlock *aParamBlock,
nsIWebBrowserPrint *aWebBrowserPrint,
nsIPrintSettings* aPS,
const char *aChromeURL)
{
NS_ENSURE_ARG(aParamBlock);
NS_ENSURE_ARG(aPS);
NS_ENSURE_ARG(aChromeURL);
if (!mWatcher)
return NS_ERROR_FAILURE;
// get a parent, if at all possible
// (though we'd rather this didn't fail, it's OK if it does. so there's
// no failure or null check.)
nsCOMPtr<mozIDOMWindowProxy> activeParent;
if (!aParent)
{
mWatcher->GetActiveWindow(getter_AddRefs(activeParent));
aParent = activeParent;
}
// create a nsIMutableArray of the parameters
// being passed to the window
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
nsCOMPtr<nsISupports> psSupports(do_QueryInterface(aPS));
NS_ASSERTION(psSupports, "PrintSettings must be a supports");
array->AppendElement(psSupports);
if (aWebBrowserPrint) {
nsCOMPtr<nsISupports> wbpSupports(do_QueryInterface(aWebBrowserPrint));
NS_ASSERTION(wbpSupports, "nsIWebBrowserPrint must be a supports");
array->AppendElement(wbpSupports);
}
nsCOMPtr<nsISupports> blkSupps(do_QueryInterface(aParamBlock));
NS_ASSERTION(blkSupps, "IOBlk must be a supports");
array->AppendElement(blkSupps);
nsCOMPtr<mozIDOMWindowProxy> dialog;
nsresult rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",
"centerscreen,chrome,modal,titlebar", array,
getter_AddRefs(dialog));
// if aWebBrowserPrint is not null then we are printing
// so we want to pass back NS_ERROR_ABORT on cancel
if (NS_SUCCEEDED(rv) && aWebBrowserPrint)
{
int32_t status;
aParamBlock->GetInt(0, &status);
return status == 0?NS_ERROR_ABORT:NS_OK;
}
return rv;
}
//////////////////////////////////////////////////////////////////////
// nsIWebProgressListener
//////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{

View File

@ -19,7 +19,6 @@
// Printing Progress Includes
#include "nsPrintProgress.h"
#include "nsPrintProgressParams.h"
#include "nsIWebProgressListener.h"
class nsIDOMWindow;
@ -43,12 +42,6 @@ protected:
virtual ~nsPrintingPromptService();
private:
nsresult DoDialog(mozIDOMWindowProxy *aParent,
nsIDialogParamBlock *aParamBlock,
nsIWebBrowserPrint *aWebBrowserPrint,
nsIPrintSettings* aPS,
const char *aChromeURL);
nsCOMPtr<nsIWindowWatcher> mWatcher;
nsCOMPtr<nsIPrintProgress> mPrintProgress;
nsCOMPtr<nsIWebProgressListener> mWebProgressListener;

View File

@ -116,12 +116,6 @@ nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent, nsIPrintSetti
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent, const char16_t *printerName, nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//////////////////////////////////////////////////////////////////////
// nsIWebProgressListener
//////////////////////////////////////////////////////////////////////

View File

@ -1,44 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- extracted from printdialog.xul -->
<!ENTITY printButton.label "Print">
<!ENTITY printDialog.title "Print">
<!ENTITY fpDialog.title "Save File">
<!ENTITY fileCheck.label "Print to File">
<!ENTITY fileCheck.accesskey "F">
<!ENTITY propertiesButton.label "Properties…">
<!ENTITY propertiesButton.accesskey "o">
<!ENTITY descText.label "Printer Description:">
<!ENTITY printer.label "Printer">
<!ENTITY printerInput.label "Printer Name:">
<!ENTITY printerInput.accesskey "N">
<!ENTITY printrangeGroup.label "Print Range">
<!ENTITY allpagesRadio.label "All Pages">
<!ENTITY allpagesRadio.accesskey "A">
<!ENTITY rangeRadio.label "Pages">
<!ENTITY rangeRadio.accesskey "P">
<!ENTITY frompageInput.label "from">
<!ENTITY frompageInput.accesskey "r">
<!ENTITY topageInput.label "to">
<!ENTITY topageInput.accesskey "t">
<!ENTITY selectionRadio.label "Selection">
<!ENTITY selectionRadio.accesskey "S">
<!ENTITY copies.label "Copies">
<!ENTITY numCopies.label "Number of copies:">
<!ENTITY numCopies.accesskey "c">
<!ENTITY printframeGroup.label "Print Frames">
<!ENTITY aslaidoutRadio.label "As laid out on the screen">
<!ENTITY aslaidoutRadio.accesskey "u">
<!ENTITY selectedframeRadio.label "The selected frame">
<!ENTITY selectedframeRadio.accesskey "m">
<!ENTITY eachframesepRadio.label "Each frame separately">
<!ENTITY eachframesepRadio.accesskey "E">

View File

@ -1,29 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- extracted from printjoboptions.xul -->
<!ENTITY printJobOptions.title "Printer Properties">
<!ENTITY paperInput.label "Paper Size:">
<!ENTITY paperInput.accesskey "P">
<!ENTITY jobTitleInput.label "Job Title:">
<!ENTITY jobTitleInput.accesskey "J">
<!ENTITY colorGroup.label "Color:">
<!ENTITY grayRadio.label "Grayscale">
<!ENTITY grayRadio.accesskey "G">
<!ENTITY colorRadio.label "Color">
<!ENTITY colorRadio.accesskey "C">
<!ENTITY edgeMarginInput.label "Gap from edge of paper to Margin">
<!ENTITY topInput.label "Top:">
<!ENTITY topInput.accesskey "T">
<!ENTITY bottomInput.label "Bottom:">
<!ENTITY bottomInput.accesskey "B">
<!ENTITY leftInput.label "Left:">
<!ENTITY leftInput.accesskey "L">
<!ENTITY rightInput.label "Right:">
<!ENTITY rightInput.accesskey "R">

View File

@ -70,9 +70,9 @@
locale/@AB_CD@/global/notification.dtd (%chrome/global/notification.dtd)
locale/@AB_CD@/global/preferences.dtd (%chrome/global/preferences.dtd)
#ifndef MOZ_FENNEC
locale/@AB_CD@/global/printdialog.dtd (%chrome/global/printdialog.dtd)
locale/@AB_CD@/global/printjoboptions.dtd (%chrome/global/printjoboptions.dtd)
#ifndef MOZ_GTK
locale/@AB_CD@/global/printPageSetup.dtd (%chrome/global/printPageSetup.dtd)
#endif
locale/@AB_CD@/global/printPreview.dtd (%chrome/global/printPreview.dtd)
locale/@AB_CD@/global/printPreviewProgress.dtd (%chrome/global/printPreviewProgress.dtd)
locale/@AB_CD@/global/printdialog.properties (%chrome/global/printdialog.properties)

View File

@ -24,7 +24,6 @@ toolkit.jar:
skin/classic/global/numberbox.css
skin/classic/global/popup.css
skin/classic/global/preferences.css
skin/classic/global/printPageSetup.css
skin/classic/global/printPreview.css
skin/classic/global/radio.css
skin/classic/global/scrollbox.css

View File

@ -12,6 +12,10 @@
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
#if defined(MOZ_X11)
#include "prlink.h"
#endif
#define FREEDESKTOP_SCREENSAVER_TARGET "org.freedesktop.ScreenSaver"
#define FREEDESKTOP_SCREENSAVER_OBJECT "/ScreenSaver"
#define FREEDESKTOP_SCREENSAVER_INTERFACE "org.freedesktop.ScreenSaver"
@ -32,6 +36,9 @@ StaticRefPtr<WakeLockListener> WakeLockListener::sSingleton;
enum DesktopEnvironment {
FreeDesktop,
GNOME,
#if defined(MOZ_X11)
XScreenSaver,
#endif
Unsupported,
};
@ -59,6 +66,11 @@ private:
bool SendGNOMEInhibitMessage();
bool SendMessage(DBusMessage* aMessage);
#if defined(MOZ_X11)
static bool CheckXScreenSaverSupport();
static bool InhibitXScreenSaver(bool inhibit);
#endif
static void ReceiveInhibitReply(DBusPendingCall* aPending, void* aUserData);
void InhibitFailed();
void InhibitSucceeded(uint32_t aInhibitRequest);
@ -143,6 +155,71 @@ WakeLockTopic::SendGNOMEInhibitMessage()
}
#if defined(MOZ_X11)
typedef Bool (*_XScreenSaverQueryExtension_fn)(Display* dpy, int* event_base,
int* error_base);
typedef Bool (*_XScreenSaverQueryVersion_fn)(Display* dpy, int* major,
int* minor);
typedef void (*_XScreenSaverSuspend_fn)(Display* dpy, Bool suspend);
static PRLibrary* sXssLib = nullptr;
static _XScreenSaverQueryExtension_fn _XSSQueryExtension = nullptr;
static _XScreenSaverQueryVersion_fn _XSSQueryVersion = nullptr;
static _XScreenSaverSuspend_fn _XSSSuspend = nullptr;
/* static */ bool
WakeLockTopic::CheckXScreenSaverSupport()
{
if (!sXssLib) {
sXssLib = PR_LoadLibrary("libXss.so.1");
if (!sXssLib) {
return false;
}
}
_XSSQueryExtension = (_XScreenSaverQueryExtension_fn)
PR_FindFunctionSymbol(sXssLib, "XScreenSaverQueryExtension");
_XSSQueryVersion = (_XScreenSaverQueryVersion_fn)
PR_FindFunctionSymbol(sXssLib, "XScreenSaverQueryVersion");
_XSSSuspend = (_XScreenSaverSuspend_fn)
PR_FindFunctionSymbol(sXssLib, "XScreenSaverSuspend");
if (!_XSSQueryExtension || !_XSSQueryVersion || !_XSSSuspend) {
return false;
}
GdkDisplay* gDisplay = gdk_display_get_default();
if (!GDK_IS_X11_DISPLAY(gDisplay)) return false;
Display* display = GDK_DISPLAY_XDISPLAY(gDisplay);
int throwaway;
if (!_XSSQueryExtension(display, &throwaway, &throwaway)) return false;
int major, minor;
if (!_XSSQueryVersion(display, &major, &minor)) return false;
// Needs to be compatible with version 1.1
if (major != 1) return false;
if (minor < 1) return false;
return true;
}
/* static */ bool
WakeLockTopic::InhibitXScreenSaver(bool inhibit)
{
// Should only be called if CheckXScreenSaverSupport returns true.
// There's a couple of safety checks here nonetheless.
if (!_XSSSuspend) return false;
GdkDisplay* gDisplay = gdk_display_get_default();
if (!GDK_IS_X11_DISPLAY(gDisplay)) return false;
Display* display = GDK_DISPLAY_XDISPLAY(gDisplay);
_XSSSuspend(display, inhibit);
return true;
}
#endif
bool
WakeLockTopic::SendInhibit()
{
@ -156,6 +233,10 @@ WakeLockTopic::SendInhibit()
case GNOME:
sendOk = SendGNOMEInhibitMessage();
break;
#if defined(MOZ_X11)
case XScreenSaver:
return InhibitXScreenSaver(true);
#endif
case Unsupported:
return false;
}
@ -185,6 +266,11 @@ WakeLockTopic::SendUninhibit()
SESSION_MANAGER_INTERFACE,
"Uninhibit"));
}
#if defined(MOZ_X11)
else if (mDesktopEnvironment == XScreenSaver) {
return InhibitXScreenSaver(false);
}
#endif
if (!message) {
return false;
@ -249,8 +335,11 @@ WakeLockTopic::InhibitFailed()
if (mDesktopEnvironment == FreeDesktop) {
mDesktopEnvironment = GNOME;
#if defined(MOZ_X11)
} else if (mDesktopEnvironment == GNOME && CheckXScreenSaverSupport()) {
mDesktopEnvironment = XScreenSaver;
#endif
} else {
NS_ASSERTION(mDesktopEnvironment == GNOME, "Unknown desktop environment");
mDesktopEnvironment = Unsupported;
mShouldInhibit = false;
}