зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to central, a=merge
MozReview-Commit-ID: L5hcbQfx0kn
This commit is contained in:
Коммит
0104e2c466
|
@ -15,7 +15,7 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
|
|||
|
||||
// lazy module getters
|
||||
|
||||
/* global AboutHome:false, AddonWatcher:false, AppConstants: false,
|
||||
/* global AboutHome:false, AddonWatcher:false,
|
||||
BrowserUITelemetry:false, BrowserUsageTelemetry:false, BrowserUtils:false,
|
||||
CastingApps:false, CharsetMenu:false, Color:false, ContentSearch:false,
|
||||
Deprecated:false, E10SUtils:false, FormValidationHandler:false,
|
||||
|
@ -38,7 +38,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
|
|||
[
|
||||
["AboutHome", "resource:///modules/AboutHome.jsm"],
|
||||
["AddonWatcher", "resource://gre/modules/AddonWatcher.jsm"],
|
||||
["AppConstants", "resource://gre/modules/AppConstants.jsm"],
|
||||
["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
|
||||
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
|
||||
["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
|
||||
|
@ -6680,6 +6679,35 @@ function BrowserOpenSyncTabs() {
|
|||
gSyncUI.openSyncedTabsPanel();
|
||||
}
|
||||
|
||||
function ReportFalseDeceptiveSite() {
|
||||
let docURI = gBrowser.selectedBrowser.documentURI;
|
||||
let isPhishingPage =
|
||||
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
|
||||
|
||||
if (isPhishingPage) {
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
let onMessage = (message) => {
|
||||
mm.removeMessageListener("DeceptiveBlockedDetails:Result", onMessage);
|
||||
let reportUrl = gSafeBrowsing.getReportURL("PhishMistake", message.data.blockedInfo);
|
||||
if (reportUrl) {
|
||||
openUILinkIn(reportUrl, "tab");
|
||||
} else {
|
||||
let promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
|
||||
getService(Ci.nsIPromptService);
|
||||
let bundle =
|
||||
Services.strings.createBundle("chrome://browser/locale/safebrowsing/safebrowsing.properties");
|
||||
promptService.alert(window,
|
||||
bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
|
||||
bundle.formatStringFromName("errorReportFalseDeceptiveMessage",
|
||||
[message.data.blockedInfo.provider], 1));
|
||||
}
|
||||
}
|
||||
mm.addMessageListener("DeceptiveBlockedDetails:Result", onMessage);
|
||||
|
||||
mm.sendAsyncMessage("DeceptiveBlockedDetails");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a URL
|
||||
* eg:
|
||||
|
|
|
@ -262,6 +262,35 @@ function getSerializedSecurityInfo(docShell) {
|
|||
return serhelper.serializeToString(securityInfo);
|
||||
}
|
||||
|
||||
function getSiteBlockedErrorDetails(docShell) {
|
||||
let blockedInfo = {};
|
||||
if (docShell.failedChannel) {
|
||||
let classifiedChannel = docShell.failedChannel.
|
||||
QueryInterface(Ci.nsIClassifiedChannel);
|
||||
if (classifiedChannel) {
|
||||
let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
let reportUri = httpChannel.URI.clone();
|
||||
|
||||
// Remove the query to avoid leaking sensitive data
|
||||
if (reportUri instanceof Ci.nsIURL) {
|
||||
reportUri.query = "";
|
||||
}
|
||||
|
||||
blockedInfo = { list: classifiedChannel.matchedList,
|
||||
provider: classifiedChannel.matchedProvider,
|
||||
uri: reportUri.asciiSpec };
|
||||
}
|
||||
}
|
||||
return blockedInfo;
|
||||
}
|
||||
|
||||
addMessageListener("DeceptiveBlockedDetails", (message) => {
|
||||
sendAsyncMessage("DeceptiveBlockedDetails:Result", {
|
||||
blockedInfo: getSiteBlockedErrorDetails(docShell),
|
||||
});
|
||||
});
|
||||
|
||||
var AboutNetAndCertErrorListener = {
|
||||
init(chromeGlobal) {
|
||||
addMessageListener("CertErrorDetails", this);
|
||||
|
@ -583,32 +612,13 @@ var ClickEventHandler = {
|
|||
let docShell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
let blockedInfo = {};
|
||||
if (docShell.failedChannel) {
|
||||
let classifiedChannel = docShell.failedChannel.
|
||||
QueryInterface(Ci.nsIClassifiedChannel);
|
||||
if (classifiedChannel) {
|
||||
let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
let reportUri = httpChannel.URI.clone();
|
||||
|
||||
// Remove the query to avoid leaking sensitive data
|
||||
if (reportUri instanceof Ci.nsIURL) {
|
||||
reportUri.query = "";
|
||||
}
|
||||
|
||||
blockedInfo = { list: classifiedChannel.matchedList,
|
||||
provider: classifiedChannel.matchedProvider,
|
||||
uri: reportUri.asciiSpec };
|
||||
}
|
||||
}
|
||||
|
||||
sendAsyncMessage("Browser:SiteBlockedError", {
|
||||
location: ownerDoc.location.href,
|
||||
reason,
|
||||
elementId: targetElement.getAttribute("id"),
|
||||
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
|
||||
blockedInfo
|
||||
blockedInfo: getSiteBlockedErrorDetails(docShell),
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
accesskey="&safeb.palm.notdeceptive.accesskey;"
|
||||
insertbefore="aboutSeparator"
|
||||
observes="reportPhishingErrorBroadcaster"
|
||||
oncommand="openUILinkIn(gSafeBrowsing.getReportURL('PhishMistake'), 'tab');"
|
||||
oncommand="ReportFalseDeceptiveSite();"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
</menupopup>
|
||||
</overlay>
|
||||
|
|
|
@ -4,39 +4,31 @@
|
|||
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
var testPage = "data:text/html,<body><style>:-moz-window-inactive { background-color: red; }</style><div id='area'></div></body>";
|
||||
var testPage = "data:text/html;charset=utf-8,<body><style>:-moz-window-inactive { background-color: red; }</style><div id='area'></div></body>";
|
||||
|
||||
var colorChangeNotifications = 0;
|
||||
var otherWindow;
|
||||
|
||||
var browser1, browser2;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
waitForFocus(reallyRunTests);
|
||||
}
|
||||
add_task(function* reallyRunTests() {
|
||||
|
||||
function reallyRunTests() {
|
||||
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, testPage);
|
||||
browser1 = tab1.linkedBrowser;
|
||||
|
||||
let tab1 = gBrowser.addTab();
|
||||
let tab2 = gBrowser.addTab();
|
||||
browser1 = gBrowser.getBrowserForTab(tab1);
|
||||
browser2 = gBrowser.getBrowserForTab(tab2);
|
||||
// This can't use openNewForegroundTab because if we focus tab2 now, we
|
||||
// won't send a focus event during test 6, further down in this file.
|
||||
let tab2 = gBrowser.addTab(testPage);
|
||||
browser2 = tab2.linkedBrowser;
|
||||
yield BrowserTestUtils.browserLoaded(browser2);
|
||||
|
||||
browser1.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
|
||||
browser2.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
|
||||
|
||||
gURLBar.focus();
|
||||
|
||||
var loadCount = 0;
|
||||
function check() {
|
||||
// wait for both tabs to load
|
||||
if (++loadCount != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
browser1.removeEventListener("load", check, true);
|
||||
browser2.removeEventListener("load", check, true);
|
||||
|
||||
sendGetBackgroundRequest(true);
|
||||
}
|
||||
let testFinished = {};
|
||||
testFinished.promise = new Promise(resolve => testFinished.resolve = resolve);
|
||||
|
||||
// The test performs four checks, using -moz-window-inactive on two child tabs.
|
||||
// First, the initial state should be transparent. The second check is done
|
||||
|
@ -74,7 +66,7 @@ function reallyRunTests() {
|
|||
break;
|
||||
case 8:
|
||||
is(message.data.color, "rgba(0, 0, 0, 0)", "second window after tab switch");
|
||||
finishTest();
|
||||
testFinished.resolve();
|
||||
break;
|
||||
case 9:
|
||||
ok(false, "too many color change notifications");
|
||||
|
@ -97,16 +89,17 @@ function reallyRunTests() {
|
|||
ok(message.data.ok, "Test:DeactivateEvent");
|
||||
});
|
||||
|
||||
browser1.addEventListener("load", check, true);
|
||||
browser2.addEventListener("load", check, true);
|
||||
browser1.contentWindow.location = testPage;
|
||||
browser2.contentWindow.location = testPage;
|
||||
|
||||
browser1.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
|
||||
browser2.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
|
||||
|
||||
gBrowser.selectedTab = tab1;
|
||||
}
|
||||
|
||||
// Start the test.
|
||||
sendGetBackgroundRequest(true);
|
||||
|
||||
yield testFinished.promise;
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab1);
|
||||
yield BrowserTestUtils.removeTab(tab2);
|
||||
otherWindow = null;
|
||||
});
|
||||
|
||||
function sendGetBackgroundRequest(ifChanged) {
|
||||
browser1.messageManager.sendAsyncMessage("Test:GetBackgroundColor", { ifChanged });
|
||||
|
@ -114,19 +107,12 @@ function sendGetBackgroundRequest(ifChanged) {
|
|||
}
|
||||
|
||||
function runOtherWindowTests() {
|
||||
otherWindow = window.open("data:text/html,<body>Hi</body>", "", "chrome");
|
||||
otherWindow = window.open("data:text/html;charset=utf-8,<body>Hi</body>", "", "chrome");
|
||||
waitForFocus(function() {
|
||||
sendGetBackgroundRequest(true);
|
||||
}, otherWindow);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.removeCurrentTab();
|
||||
otherWindow = null;
|
||||
finish();
|
||||
}
|
||||
|
||||
function childFunction() {
|
||||
let oldColor = null;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<title>&welcomeback2.tabtitle;</title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/info-pages.css" type="text/css" media="all"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutWelcomeBack.css" type="text/css" media="all"/>
|
||||
<link rel="icon" type="image/png" href="chrome://global/skin/icons/information-16.png"/>
|
||||
<link rel="icon" type="image/png" href="chrome://browser/skin/info.svg"/>
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/aboutSessionRestore.js"/>
|
||||
</head>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# 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/.
|
||||
|
||||
errorReportFalseDeceptiveTitle=This isn’t a deceptive site
|
||||
errorReportFalseDeceptiveMessage=It’s not possible to report this error at this time.
|
|
@ -54,6 +54,7 @@
|
|||
locale/browser/places/moveBookmarks.dtd (%chrome/browser/places/moveBookmarks.dtd)
|
||||
locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
|
||||
locale/browser/safebrowsing/report-phishing.dtd (%chrome/browser/safebrowsing/report-phishing.dtd)
|
||||
locale/browser/safebrowsing/safebrowsing.properties (%chrome/browser/safebrowsing/safebrowsing.properties)
|
||||
locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd)
|
||||
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
|
||||
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)
|
||||
|
|
|
@ -7,7 +7,7 @@ body {
|
|||
|
||||
#message-box {
|
||||
margin-top: 2em;
|
||||
background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
|
||||
background: url(chrome://browser/skin/info.svg) no-repeat left 8px;
|
||||
padding-inline-start: 30px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
The certificate authority and server certificates here are generated by $topsrcdir/build/pgo/genpgocert.py.
|
||||
|
||||
You can generate a new CA cert by running:
|
||||
$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-ca
|
||||
./mach python build/pgo/genpgocert.py --gen-ca
|
||||
|
||||
You can generate new server certificates by running:
|
||||
$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-server
|
||||
./mach python build/pgo/genpgocert.py --gen-server
|
||||
|
||||
These will place the new files in this directory where you can commit them.
|
||||
These commands will modify cert8.db and key3.db. The changes to these should be committed.
|
||||
|
|
|
@ -442,6 +442,21 @@ BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
|
||||
{
|
||||
// Never destroy an existing CSP on the principal.
|
||||
// This method should only be called in rare cases.
|
||||
|
||||
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
|
||||
if (mCSP) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
mCSP = aCsp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP)
|
||||
|
|
|
@ -222,6 +222,7 @@ public:
|
|||
NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final;
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
|
||||
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
|
||||
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
|
||||
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
|
||||
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
|
||||
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
|
||||
|
|
|
@ -151,10 +151,11 @@ interface nsIPrincipal : nsISerializable
|
|||
|
||||
/**
|
||||
* A Content Security Policy associated with this principal.
|
||||
*
|
||||
* Use this function to query the associated CSP with this principal.
|
||||
* Please *only* use this function to *set* a CSP when you know exactly what you are doing.
|
||||
* Most likely you want to call ensureCSP instead of setCSP.
|
||||
*/
|
||||
[noscript] readonly attribute nsIContentSecurityPolicy csp;
|
||||
[noscript] attribute nsIContentSecurityPolicy csp;
|
||||
|
||||
/*
|
||||
* Use this function to query a CSP associated with this principal.
|
||||
|
|
|
@ -108,6 +108,20 @@ nsNullPrincipal::GetHashValue(uint32_t *aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
// Never destroy an existing CSP on the principal.
|
||||
// This method should only be called in rare cases.
|
||||
|
||||
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
|
||||
if (mCSP) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
mCSP = aCsp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::GetURI(nsIURI** aURI)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
|
||||
NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
|
||||
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
|
||||
NS_IMETHOD GetURI(nsIURI** aURI) override;
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
|
||||
|
|
|
@ -269,10 +269,68 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
|
|||
nsIPrincipal** aPrincipal,
|
||||
bool aIgnoreSandboxing)
|
||||
{
|
||||
NS_PRECONDITION(aChannel, "Must have channel!");
|
||||
// Check whether we have an nsILoadInfo that says what we should do.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
if (loadInfo && loadInfo->GetForceInheritPrincipalOverruleOwner()) {
|
||||
NS_PRECONDITION(aChannel, "Must have channel!");
|
||||
// Check whether we have an nsILoadInfo that says what we should do.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
if (loadInfo && loadInfo->GetForceInheritPrincipalOverruleOwner()) {
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
|
||||
if (!principalToInherit) {
|
||||
principalToInherit = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
principalToInherit.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> owner;
|
||||
aChannel->GetOwner(getter_AddRefs(owner));
|
||||
if (owner) {
|
||||
CallQueryInterface(owner, aPrincipal);
|
||||
if (*aPrincipal) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadInfo) {
|
||||
if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(loadInfo->GetSandboxedLoadingPrincipal(aPrincipal)));
|
||||
MOZ_ASSERT(*aPrincipal);
|
||||
// if the new NullPrincipal (above) loads an iframe[srcdoc], we
|
||||
// need to inherit an existing CSP to avoid bypasses (bug 1073952).
|
||||
// We continue inheriting for nested frames with e.g., data: URLs.
|
||||
if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aChannel->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString URISpec;
|
||||
uri->GetSpec(URISpec);
|
||||
bool isData = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData);
|
||||
if (URISpec.EqualsLiteral("about:srcdoc") || isData) {
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
|
||||
if (!principalToInherit) {
|
||||
principalToInherit = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
nsCOMPtr<nsIContentSecurityPolicy> originalCsp;
|
||||
principalToInherit->GetCsp(getter_AddRefs(originalCsp));
|
||||
// if the principalToInherit had a CSP,
|
||||
// add it to the newly created NullPrincipal.
|
||||
if (originalCsp) {
|
||||
nsresult rv = (*aPrincipal)->SetCsp(originalCsp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool forceInherit = loadInfo->GetForceInheritPrincipal();
|
||||
if (aIgnoreSandboxing && !forceInherit) {
|
||||
// Check if SEC_FORCE_INHERIT_PRINCIPAL was dropped because of
|
||||
// sandboxing:
|
||||
if (loadInfo->GetLoadingSandboxed() &&
|
||||
loadInfo->GetForceInheritPrincipalDropped()) {
|
||||
forceInherit = true;
|
||||
}
|
||||
}
|
||||
if (forceInherit) {
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
|
||||
if (!principalToInherit) {
|
||||
principalToInherit = loadInfo->TriggeringPrincipal();
|
||||
|
@ -281,67 +339,33 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> owner;
|
||||
aChannel->GetOwner(getter_AddRefs(owner));
|
||||
if (owner) {
|
||||
CallQueryInterface(owner, aPrincipal);
|
||||
if (*aPrincipal) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
|
||||
// The data: inheritance flags should only apply to the initial load,
|
||||
// not to loads that it might have redirected to.
|
||||
if (loadInfo->RedirectChain().IsEmpty() &&
|
||||
(securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
|
||||
securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
|
||||
securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) {
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
|
||||
if (!principalToInherit) {
|
||||
principalToInherit = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
bool inheritForAboutBlank = loadInfo->GetAboutBlankInherits();
|
||||
|
||||
if (nsContentUtils::ChannelShouldInheritPrincipal(principalToInherit,
|
||||
uri,
|
||||
inheritForAboutBlank,
|
||||
false)) {
|
||||
principalToInherit.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadInfo) {
|
||||
if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(loadInfo->GetSandboxedLoadingPrincipal(aPrincipal)));
|
||||
MOZ_ASSERT(*aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool forceInherit = loadInfo->GetForceInheritPrincipal();
|
||||
if (aIgnoreSandboxing && !forceInherit) {
|
||||
// Check if SEC_FORCE_INHERIT_PRINCIPAL was dropped because of
|
||||
// sandboxing:
|
||||
if (loadInfo->GetLoadingSandboxed() &&
|
||||
loadInfo->GetForceInheritPrincipalDropped()) {
|
||||
forceInherit = true;
|
||||
}
|
||||
}
|
||||
if (forceInherit) {
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
|
||||
if (!principalToInherit) {
|
||||
principalToInherit = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
principalToInherit.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
|
||||
// The data: inheritance flags should only apply to the initial load,
|
||||
// not to loads that it might have redirected to.
|
||||
if (loadInfo->RedirectChain().IsEmpty() &&
|
||||
(securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
|
||||
securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
|
||||
securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) {
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
|
||||
if (!principalToInherit) {
|
||||
principalToInherit = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
bool inheritForAboutBlank = loadInfo->GetAboutBlankInherits();
|
||||
|
||||
if (nsContentUtils::ChannelShouldInheritPrincipal(principalToInherit,
|
||||
uri,
|
||||
inheritForAboutBlank,
|
||||
false)) {
|
||||
principalToInherit.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return GetChannelURIPrincipal(aChannel, aPrincipal);
|
||||
}
|
||||
return GetChannelURIPrincipal(aChannel, aPrincipal);
|
||||
}
|
||||
|
||||
/* The principal of the URI that this channel is loading. This is never
|
||||
|
|
|
@ -57,7 +57,7 @@ nsSystemPrincipal::GetHashValue(uint32_t *result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::GetURI(nsIURI** aURI)
|
||||
{
|
||||
*aURI = nullptr;
|
||||
|
@ -78,6 +78,15 @@ nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
|
||||
{
|
||||
// Never destroy an existing CSP on the principal.
|
||||
// This method should only be called in rare cases.
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP)
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
|
||||
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
|
||||
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
|
||||
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
|
||||
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
|
||||
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
|
||||
|
|
|
@ -34,6 +34,7 @@ ostream
|
|||
set
|
||||
stack
|
||||
string
|
||||
thread
|
||||
type_traits
|
||||
utility
|
||||
vector
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
|
||||
const TAB_URL = "data:text/html,<title>foo</title>";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { tab, document } = yield openAboutDebugging("tabs");
|
||||
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
// Test that the spacebar key press toggles the toggleAll button state
|
||||
// when a node with no animation is selected.
|
||||
// This test doesn't need to test if animations actually pause/resume
|
||||
|
|
|
@ -30,12 +30,6 @@ let checkToolbox = Task.async(function* (tab, location) {
|
|||
ok(!!gDevTools.getToolbox(target), `Toolbox exists ${location}`);
|
||||
});
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
.notificationbox .messageImage {
|
||||
display: inline-block;
|
||||
background-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 6px;
|
||||
|
@ -59,7 +60,7 @@
|
|||
/* Default icons for notifications */
|
||||
|
||||
.notificationbox .messageImage[data-type="info"] {
|
||||
background-image: url("chrome://global/skin/icons/information-16.png");
|
||||
background-image: url("chrome://global/skin/icons/info.svg");
|
||||
}
|
||||
|
||||
.notificationbox .messageImage[data-type="warning"] {
|
||||
|
|
|
@ -13,12 +13,6 @@ const TEST_DOC = "https://example.com/browser/devtools/client/webconsole/" +
|
|||
"test/test_bug1092055_shouldwarn.html";
|
||||
const SAMPLE_MSG = "specified a header that could not be parsed successfully.";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { browser } = yield loadTab(TEST_URI);
|
||||
|
||||
|
|
|
@ -9,10 +9,6 @@ const TEST_URI = "data:text/html;charset=utf-8,Web Console test for splitting";
|
|||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]}, runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Test is slow on Linux EC2 instances - Bug 962931
|
||||
requestLongerTimeout(2);
|
||||
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
// Check that the duration, iterationCount and delay are retrieved correctly for
|
||||
// multiple animations.
|
||||
|
||||
|
|
|
@ -4406,7 +4406,8 @@ nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// Loading the sheet sync.
|
||||
RefPtr<css::Loader> loader = new css::Loader(GetStyleBackendType());
|
||||
RefPtr<css::Loader> loader =
|
||||
new css::Loader(GetStyleBackendType(), GetDocGroup());
|
||||
|
||||
css::SheetParsingMode parsingMode;
|
||||
switch (aType) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
#define NS_EVENT_STATE_HIGHEST_SERVO_BIT 12
|
||||
#define NS_EVENT_STATE_HIGHEST_SERVO_BIT 19
|
||||
|
||||
/**
|
||||
* EventStates is the class used to represent the event states of nsIContent
|
||||
|
@ -223,6 +223,21 @@ private:
|
|||
#define NS_EVENT_STATE_INVALID NS_DEFINE_EVENT_STATE_MACRO(11)
|
||||
// UI friendly version of :valid pseudo-class.
|
||||
#define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(12)
|
||||
// Content could not be rendered (image/object/etc).
|
||||
#define NS_EVENT_STATE_BROKEN NS_DEFINE_EVENT_STATE_MACRO(13)
|
||||
// Content disabled by the user (images turned off, say).
|
||||
#define NS_EVENT_STATE_USERDISABLED NS_DEFINE_EVENT_STATE_MACRO(14)
|
||||
// Content suppressed by the user (ad blocking, etc).
|
||||
#define NS_EVENT_STATE_SUPPRESSED NS_DEFINE_EVENT_STATE_MACRO(15)
|
||||
// Content is still loading such that there is nothing to show the
|
||||
// user (eg an image which hasn't started coming in yet).
|
||||
#define NS_EVENT_STATE_LOADING NS_DEFINE_EVENT_STATE_MACRO(16)
|
||||
// Handler for the content has been blocked.
|
||||
#define NS_EVENT_STATE_HANDLER_BLOCKED NS_DEFINE_EVENT_STATE_MACRO(17)
|
||||
// Handler for the content has been disabled.
|
||||
#define NS_EVENT_STATE_HANDLER_DISABLED NS_DEFINE_EVENT_STATE_MACRO(18)
|
||||
// Handler for the content has crashed
|
||||
#define NS_EVENT_STATE_HANDLER_CRASHED NS_DEFINE_EVENT_STATE_MACRO(19)
|
||||
|
||||
/*
|
||||
* Bits below here do not have Servo-related ordering constraints.
|
||||
|
@ -232,42 +247,27 @@ private:
|
|||
*/
|
||||
|
||||
// Drag is hovering over content.
|
||||
#define NS_EVENT_STATE_DRAGOVER NS_DEFINE_EVENT_STATE_MACRO(13)
|
||||
#define NS_EVENT_STATE_DRAGOVER NS_DEFINE_EVENT_STATE_MACRO(20)
|
||||
// Content is required.
|
||||
#define NS_EVENT_STATE_REQUIRED NS_DEFINE_EVENT_STATE_MACRO(14)
|
||||
#define NS_EVENT_STATE_REQUIRED NS_DEFINE_EVENT_STATE_MACRO(21)
|
||||
// Content is optional (and can be required).
|
||||
#define NS_EVENT_STATE_OPTIONAL NS_DEFINE_EVENT_STATE_MACRO(15)
|
||||
#define NS_EVENT_STATE_OPTIONAL NS_DEFINE_EVENT_STATE_MACRO(22)
|
||||
// Link has been visited.
|
||||
#define NS_EVENT_STATE_VISITED NS_DEFINE_EVENT_STATE_MACRO(16)
|
||||
#define NS_EVENT_STATE_VISITED NS_DEFINE_EVENT_STATE_MACRO(23)
|
||||
// Link hasn't been visited.
|
||||
#define NS_EVENT_STATE_UNVISITED NS_DEFINE_EVENT_STATE_MACRO(17)
|
||||
#define NS_EVENT_STATE_UNVISITED NS_DEFINE_EVENT_STATE_MACRO(24)
|
||||
// Content value is in-range (and can be out-of-range).
|
||||
#define NS_EVENT_STATE_INRANGE NS_DEFINE_EVENT_STATE_MACRO(18)
|
||||
#define NS_EVENT_STATE_INRANGE NS_DEFINE_EVENT_STATE_MACRO(25)
|
||||
// Content value is out-of-range.
|
||||
#define NS_EVENT_STATE_OUTOFRANGE NS_DEFINE_EVENT_STATE_MACRO(19)
|
||||
#define NS_EVENT_STATE_OUTOFRANGE NS_DEFINE_EVENT_STATE_MACRO(26)
|
||||
// These two are temporary (see bug 302188)
|
||||
// Content is read-only.
|
||||
#define NS_EVENT_STATE_MOZ_READONLY NS_DEFINE_EVENT_STATE_MACRO(20)
|
||||
#define NS_EVENT_STATE_MOZ_READONLY NS_DEFINE_EVENT_STATE_MACRO(27)
|
||||
// Content is editable.
|
||||
#define NS_EVENT_STATE_MOZ_READWRITE NS_DEFINE_EVENT_STATE_MACRO(21)
|
||||
#define NS_EVENT_STATE_MOZ_READWRITE NS_DEFINE_EVENT_STATE_MACRO(28)
|
||||
// Content is the default one (meaning depends of the context).
|
||||
#define NS_EVENT_STATE_DEFAULT NS_DEFINE_EVENT_STATE_MACRO(22)
|
||||
// Content could not be rendered (image/object/etc).
|
||||
#define NS_EVENT_STATE_BROKEN NS_DEFINE_EVENT_STATE_MACRO(23)
|
||||
// Content disabled by the user (images turned off, say).
|
||||
#define NS_EVENT_STATE_USERDISABLED NS_DEFINE_EVENT_STATE_MACRO(24)
|
||||
// Content suppressed by the user (ad blocking, etc).
|
||||
#define NS_EVENT_STATE_SUPPRESSED NS_DEFINE_EVENT_STATE_MACRO(25)
|
||||
// Content is still loading such that there is nothing to show the
|
||||
// user (eg an image which hasn't started coming in yet).
|
||||
#define NS_EVENT_STATE_LOADING NS_DEFINE_EVENT_STATE_MACRO(26)
|
||||
#define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL NS_DEFINE_EVENT_STATE_MACRO(27)
|
||||
// Handler for the content has been blocked.
|
||||
#define NS_EVENT_STATE_HANDLER_BLOCKED NS_DEFINE_EVENT_STATE_MACRO(28)
|
||||
// Handler for the content has been disabled.
|
||||
#define NS_EVENT_STATE_HANDLER_DISABLED NS_DEFINE_EVENT_STATE_MACRO(29)
|
||||
// Handler for the content has crashed
|
||||
#define NS_EVENT_STATE_HANDLER_CRASHED NS_DEFINE_EVENT_STATE_MACRO(30)
|
||||
#define NS_EVENT_STATE_DEFAULT NS_DEFINE_EVENT_STATE_MACRO(29)
|
||||
#define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL NS_DEFINE_EVENT_STATE_MACRO(30)
|
||||
// Content has focus and should show a ring.
|
||||
#define NS_EVENT_STATE_FOCUSRING NS_DEFINE_EVENT_STATE_MACRO(31)
|
||||
// Content is a submit control and the form isn't valid.
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe srcdoc="<img src=x onerror='parent.postMessage({result: `unexpected-csp-violation`}, `*`);'>"
|
||||
sandbox="allow-scripts"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
content-security-policy: default-src *;
|
|
@ -0,0 +1,79 @@
|
|||
// Custom *.sjs file specifically for the needs of
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1073952
|
||||
|
||||
"use strict";
|
||||
Components.utils.importGlobalProperties(["URLSearchParams"]);
|
||||
|
||||
const SCRIPT = `
|
||||
<script>
|
||||
parent.parent.postMessage({result: "allowed"}, "*");
|
||||
</script>`;
|
||||
|
||||
const SIMPLE_IFRAME_SRCDOC = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body>
|
||||
<iframe sandbox="allow-scripts" srcdoc="` + SCRIPT + `"></iframe>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const INNER_SRCDOC_IFRAME = `
|
||||
<iframe sandbox='allow-scripts' srcdoc='<script>
|
||||
parent.parent.parent.postMessage({result: "allowed"}, "*");
|
||||
</script>'>
|
||||
</iframe>`;
|
||||
|
||||
const NESTED_IFRAME_SRCDOC = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body>
|
||||
<iframe sandbox="allow-scripts" srcdoc="` + INNER_SRCDOC_IFRAME + `"></iframe>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
|
||||
const INNER_DATAURI_IFRAME = `
|
||||
<iframe sandbox='allow-scripts' src='data:text/html,<script>
|
||||
parent.parent.parent.postMessage({result: "allowed"}, "*");
|
||||
</script>'>
|
||||
</iframe>`;
|
||||
|
||||
const NESTED_IFRAME_SRCDOC_DATAURI = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body>
|
||||
<iframe sandbox="allow-scripts" srcdoc="` + INNER_DATAURI_IFRAME + `"></iframe>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
function handleRequest(request, response) {
|
||||
const query = new URLSearchParams(request.queryString);
|
||||
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
if (typeof query.get("csp") === "string") {
|
||||
response.setHeader("Content-Security-Policy", query.get("csp"), false);
|
||||
}
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
|
||||
if (query.get("action") === "simple_iframe_srcdoc") {
|
||||
response.write(SIMPLE_IFRAME_SRCDOC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query.get("action") === "nested_iframe_srcdoc") {
|
||||
response.write(NESTED_IFRAME_SRCDOC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query.get("action") === "nested_iframe_srcdoc_datauri") {
|
||||
response.write(NESTED_IFRAME_SRCDOC_DATAURI);
|
||||
return;
|
||||
}
|
||||
|
||||
// we should never get here, but just in case
|
||||
// return something unexpected
|
||||
response.write("do'h");
|
||||
}
|
|
@ -205,6 +205,9 @@ support-files =
|
|||
file_upgrade_insecure_navigation.sjs
|
||||
file_punycode_host_src.sjs
|
||||
file_punycode_host_src.js
|
||||
file_iframe_srcdoc.sjs
|
||||
file_iframe_sandbox_srcdoc.html
|
||||
file_iframe_sandbox_srcdoc.html^headers^
|
||||
|
||||
[test_base-uri.html]
|
||||
[test_blob_data_schemes.html]
|
||||
|
@ -293,3 +296,5 @@ tags = mcb
|
|||
[test_strict_dynamic_default_src.html]
|
||||
[test_upgrade_insecure_navigation.html]
|
||||
[test_punycode_host_src.html]
|
||||
[test_iframe_sandbox_srcdoc.html]
|
||||
[test_iframe_srcdoc.html]
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display">Bug 1073952</p>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||
// get sent out to the wire.
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
|
||||
do_QueryInterface(subject, "nsISupportsCString"), "data");
|
||||
// the violation subject for inline script violations is unfortunately vague,
|
||||
// all we can do is match the string.
|
||||
if (!violationString.includes("Inline Script")) {
|
||||
return
|
||||
}
|
||||
ok(true, "CSP inherited into sandboxed srcdoc iframe, script blocked.");
|
||||
window.testFinished();
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
function testFinished() {
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addEventListener("message", function(e) {
|
||||
ok(false, "We should not execute JS in srcdoc iframe.");
|
||||
window.testFinished();
|
||||
})
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
// ... this loads the testbed of good and bad requests.
|
||||
document.getElementById('cspframe').src = 'file_iframe_sandbox_srcdoc.html';
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,140 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1073952 - Test CSP enforcement within iframe srcdoc</title>
|
||||
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe style="width:100%;" id="testframe"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/*
|
||||
* Description of the test:
|
||||
* (1) We serve a site which makes use of script-allowed sandboxed iframe srcdoc
|
||||
* and make sure that CSP applies to the nested browsing context
|
||||
* within the iframe.
|
||||
* [PAGE WITH CSP [IFRAME SANDBOX SRCDOC [SCRIPT]]]
|
||||
*
|
||||
* (2) We serve a site which nests script within an script-allowed sandboxed
|
||||
* iframe srcdoc within another script-allowed sandboxed iframe srcdoc and
|
||||
* make sure that CSP applies to the nested browsing context
|
||||
* within the iframe*s*.
|
||||
* [PAGE WITH CSP [IFRAME SANDBOX SRCDOC [IFRAME SANDBOX SRCDOC [SCRIPT]]]]
|
||||
*
|
||||
* Please note that the test relies on the "csp-on-violate-policy" observer.
|
||||
* Whenever the script within the iframe is blocked observers are notified.
|
||||
* In turn, this renders the 'result' within tests[] unused. In case the script
|
||||
* would execute however, the postMessageHandler would bubble up 'allowed' and
|
||||
* the test would fail.
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var tests = [
|
||||
// [PAGE *WITHOUT* CSP [IFRAME SRCDOC [SCRIPT]]]
|
||||
{ csp: "",
|
||||
result: "allowed",
|
||||
query: "simple_iframe_srcdoc",
|
||||
desc: "No CSP should run script within script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
{ csp: "script-src https://test1.com",
|
||||
result: "blocked",
|
||||
query: "simple_iframe_srcdoc",
|
||||
desc: "CSP should block script within script-allowed sandboxediframe srcdoc"
|
||||
},
|
||||
// [PAGE *WITHOUT* CSP [IFRAME SRCDOC [IFRAME SRCDOC [SCRIPT]]]]
|
||||
{ csp: "",
|
||||
result: "allowed",
|
||||
query: "nested_iframe_srcdoc",
|
||||
desc: "No CSP should run script within script-allowed sandboxed iframe srcdoc nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
// [PAGE WITH CSP [IFRAME SRCDOC ]]
|
||||
{ csp: "script-src https://test2.com",
|
||||
result: "blocked",
|
||||
query: "nested_iframe_srcdoc",
|
||||
desc: "CSP should block script within script-allowed sandboxed iframe srcdoc nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
{ csp: "",
|
||||
result: "allowed",
|
||||
query: "nested_iframe_srcdoc_datauri",
|
||||
desc: "No CSP, should run script within script-allowed sandboxed iframe src with data URL nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
{ csp: "script-src https://test3.com",
|
||||
result: "blocked",
|
||||
query: "nested_iframe_srcdoc_datauri",
|
||||
desc: "CSP should block script within script-allowed sandboxed iframe src with data URL nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
// initializing to -1 so we start at index 0 when we start the test
|
||||
var counter = -1;
|
||||
|
||||
function finishTest() {
|
||||
window.removeEventListener("message", receiveMessage, false);
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
function receiveMessage(event) {
|
||||
var result = event.data.result;
|
||||
testComplete(result, tests[counter].result, tests[counter].desc);
|
||||
}
|
||||
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic === "csp-on-violate-policy") {
|
||||
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
|
||||
do_QueryInterface(subject, "nsISupportsCString"), "data");
|
||||
// the violation subject for inline script violations is unfortunately vague,
|
||||
// all we can do is match the string.
|
||||
if (!violationString.includes("Inline Script")) {
|
||||
return
|
||||
}
|
||||
testComplete("blocked", tests[counter].result, tests[counter].desc);
|
||||
}
|
||||
},
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
}
|
||||
}
|
||||
|
||||
function testComplete(result, expected, desc) {
|
||||
is(result, expected, desc);
|
||||
// ignore cases when we get csp violations and postMessage from the same frame.
|
||||
var frameURL = new URL(document.getElementById("testframe").src);
|
||||
var params = new URLSearchParams(frameURL.search);
|
||||
var counterInFrame = params.get("counter");
|
||||
if (counterInFrame == counter) {
|
||||
loadNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function loadNextTest() {
|
||||
counter++;
|
||||
if (counter == tests.length) {
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
var src = "file_iframe_srcdoc.sjs";
|
||||
src += "?csp=" + escape(tests[counter].csp);
|
||||
src += "&action=" + escape(tests[counter].query);
|
||||
src += "&counter=" + counter;
|
||||
document.getElementById("testframe").src = src;
|
||||
}
|
||||
|
||||
// start running the tests
|
||||
window.examiner = new examiner();
|
||||
loadNextTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,77 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Dragging the scrollbar on a page with a fixed-positioned element just past the right edge of the content</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<style>
|
||||
body {
|
||||
height: 2000px;
|
||||
}
|
||||
#fixed {
|
||||
width: 240px;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: -240px;
|
||||
z-index: 1000;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
#fixed-content {
|
||||
height: 2000px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var root;
|
||||
var scrollPos;
|
||||
var haveScrolled = false;
|
||||
var generatedAll = false;
|
||||
|
||||
// Be careful not to call subtestDone() until we've scrolled AND generated
|
||||
// all of the events.
|
||||
function maybeDone() {
|
||||
if (haveScrolled && generatedAll) {
|
||||
subtestDone();
|
||||
}
|
||||
}
|
||||
|
||||
function scrolled(e) {
|
||||
// Test that we have scrolled
|
||||
ok(root.scrollTop > scrollPos, "document scrolled after dragging scrollbar");
|
||||
haveScrolled = true;
|
||||
maybeDone();
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
root = document.scrollingElement;
|
||||
scrollPos = root.scrollTop;
|
||||
document.addEventListener('scroll', scrolled);
|
||||
|
||||
var scrollbarX = (window.innerWidth + root.clientWidth) / 2;
|
||||
// Move the mouse to the scrollbar
|
||||
yield synthesizeNativeMouseEvent(root, scrollbarX, 100, nativeMouseMoveEventMsg(), testDriver);
|
||||
// mouse down
|
||||
yield synthesizeNativeMouseEvent(root, scrollbarX, 100, nativeMouseDownEventMsg(), testDriver);
|
||||
// drag vertically
|
||||
yield synthesizeNativeMouseEvent(root, scrollbarX, 150, nativeMouseMoveEventMsg(), testDriver);
|
||||
// and release
|
||||
yield synthesizeNativeMouseEvent(root, scrollbarX, 150, nativeMouseUpEventMsg(), testDriver);
|
||||
|
||||
generatedAll = true;
|
||||
maybeDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test));
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="fixed">
|
||||
<p id="fixed-content"></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -10,6 +10,7 @@
|
|||
helper_bug1280013.html
|
||||
helper_bug1285070.html
|
||||
helper_bug1299195.html
|
||||
helper_bug1346632.html
|
||||
helper_click.html
|
||||
helper_div_pan.html
|
||||
helper_drag_click.html
|
||||
|
|
|
@ -17,7 +17,9 @@ var subtests = [
|
|||
// Sanity test for click but with some mouse movement between the down and up
|
||||
{'file': 'helper_drag_click.html'},
|
||||
// Test for dragging on a fake-scrollbar element that scrolls the page
|
||||
{'file': 'helper_drag_scroll.html'}
|
||||
{'file': 'helper_drag_scroll.html'},
|
||||
// Test for dragging the scrollbar with a fixed-pos element overlaying it
|
||||
{'file': 'helper_bug1346632.html'}
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
|
|
|
@ -628,8 +628,15 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
|
|||
ScrollableLayerGuid guid(aGuid.mLayersId, 0, FrameMetrics::NULL_SCROLL_ID);
|
||||
nsPoint point =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aRefPoint, aRootFrame);
|
||||
uint32_t flags = 0;
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// On Android, we need IGNORE_ROOT_SCROLL_FRAME for correct hit testing
|
||||
// when zoomed out. On desktop, don't use it because it interferes with
|
||||
// hit testing for some purposes such as scrollbar dragging.
|
||||
flags = nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME;
|
||||
#endif
|
||||
nsIFrame* target =
|
||||
nsLayoutUtils::GetFrameForPoint(aRootFrame, point, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
|
||||
nsLayoutUtils::GetFrameForPoint(aRootFrame, point, flags);
|
||||
nsIScrollableFrame* scrollAncestor = target
|
||||
? nsLayoutUtils::GetAsyncScrollableAncestorFrame(target)
|
||||
: aRootFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
|
||||
|
|
|
@ -74,6 +74,7 @@ APZThreadUtils::IsControllerThread()
|
|||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(GenericTimerCallbackBase, nsITimerCallback)
|
||||
NS_IMPL_ISUPPORTS(GenericNamedTimerCallbackBase, nsITimerCallback, nsINamed)
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define mozilla_layers_APZThreadUtils_h
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "nsINamed.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -98,6 +99,68 @@ GenericTimerCallback<Function>* NewTimerCallback(const Function& aFunction)
|
|||
return new GenericTimerCallback<Function>(aFunction);
|
||||
}
|
||||
|
||||
// A base class for GenericNamedTimerCallback<Function>.
|
||||
// This is necessary because NS_IMPL_ISUPPORTS doesn't work for a class
|
||||
// template.
|
||||
class GenericNamedTimerCallbackBase : public nsITimerCallback,
|
||||
public nsINamed
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
protected:
|
||||
virtual ~GenericNamedTimerCallbackBase() {}
|
||||
};
|
||||
|
||||
// An nsITimerCallback implementation with nsINamed that can be used with any
|
||||
// function object that's callable with no arguments.
|
||||
template <typename Function>
|
||||
class GenericNamedTimerCallback final : public GenericNamedTimerCallbackBase
|
||||
{
|
||||
public:
|
||||
explicit GenericNamedTimerCallback(const Function& aFunction,
|
||||
const char* aName)
|
||||
: mFunction(aFunction)
|
||||
, mName(aName)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Notify(nsITimer*) override
|
||||
{
|
||||
mFunction();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetName(nsACString& aName) override
|
||||
{
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD SetName(const char * aName) override
|
||||
{
|
||||
mName.Assign(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
Function mFunction;
|
||||
nsCString mName;
|
||||
};
|
||||
|
||||
// Convenience function for constructing a GenericNamedTimerCallback.
|
||||
// Returns a raw pointer, suitable for passing directly as an argument to
|
||||
// nsITimer::InitWithCallback(). The intention is to enable the following
|
||||
// terse inline usage:
|
||||
// timer->InitWithCallback(NewNamedTimerCallback([](){ ... }, name), delay);
|
||||
template <typename Function>
|
||||
GenericNamedTimerCallback<Function>*
|
||||
NewNamedTimerCallback(const Function& aFunction,
|
||||
const char* aName)
|
||||
{
|
||||
return new GenericNamedTimerCallback<Function>(aFunction, aName);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ static pfn_ovr_GetFloatArray ovr_GetFloatArray = nullptr;
|
|||
static pfn_ovr_SetFloatArray ovr_SetFloatArray = nullptr;
|
||||
static pfn_ovr_GetString ovr_GetString = nullptr;
|
||||
static pfn_ovr_SetString ovr_SetString = nullptr;
|
||||
static pfn_ovr_GetBoundaryDimensions ovr_GetBoundaryDimensions = nullptr;
|
||||
|
||||
#ifdef XP_WIN
|
||||
static pfn_ovr_CreateTextureSwapChainDX ovr_CreateTextureSwapChainDX = nullptr;
|
||||
|
@ -286,6 +287,7 @@ InitializeOculusCAPI()
|
|||
REQUIRE_FUNCTION(ovr_SetFloatArray);
|
||||
REQUIRE_FUNCTION(ovr_GetString);
|
||||
REQUIRE_FUNCTION(ovr_SetString);
|
||||
REQUIRE_FUNCTION(ovr_GetBoundaryDimensions);
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
|
@ -356,6 +358,7 @@ VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
|
|||
, mVertexBuffer(nullptr)
|
||||
, mInputLayout(nullptr)
|
||||
, mIsPresenting(false)
|
||||
, mEyeHeight(OVR_DEFAULT_EYE_HEIGHT)
|
||||
{
|
||||
MOZ_COUNT_CTOR_INHERITED(VRDisplayOculus, VRDisplayHost);
|
||||
|
||||
|
@ -373,6 +376,7 @@ VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
|
|||
if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Position) {
|
||||
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Position;
|
||||
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
|
||||
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_StageParameters;
|
||||
}
|
||||
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
|
||||
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_MountDetection;
|
||||
|
@ -401,6 +405,8 @@ VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
|
|||
// take the max of both for eye resolution
|
||||
mDisplayInfo.mEyeResolution.width = std::max(texSize[VRDisplayInfo::Eye_Left].w, texSize[VRDisplayInfo::Eye_Right].w);
|
||||
mDisplayInfo.mEyeResolution.height = std::max(texSize[VRDisplayInfo::Eye_Left].h, texSize[VRDisplayInfo::Eye_Right].h);
|
||||
|
||||
UpdateStageParameters();
|
||||
}
|
||||
|
||||
VRDisplayOculus::~VRDisplayOculus() {
|
||||
|
@ -418,10 +424,49 @@ VRDisplayOculus::Destroy()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRDisplayOculus::UpdateStageParameters()
|
||||
{
|
||||
ovrVector3f playArea;
|
||||
ovrResult res = ovr_GetBoundaryDimensions(mSession, ovrBoundary_PlayArea, &playArea);
|
||||
if (res == ovrSuccess) {
|
||||
mDisplayInfo.mStageSize.width = playArea.x;
|
||||
mDisplayInfo.mStageSize.height = playArea.z;
|
||||
} else {
|
||||
// If we fail, fall back to reasonable defaults.
|
||||
// 1m x 1m space
|
||||
mDisplayInfo.mStageSize.width = 1.0f;
|
||||
mDisplayInfo.mStageSize.height = 1.0f;
|
||||
}
|
||||
|
||||
mEyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
|
||||
|
||||
mDisplayInfo.mSittingToStandingTransform._11 = 1.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._12 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._13 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._14 = 0.0f;
|
||||
|
||||
mDisplayInfo.mSittingToStandingTransform._21 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._22 = 1.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._23 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._24 = 0.0f;
|
||||
|
||||
mDisplayInfo.mSittingToStandingTransform._31 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._32 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._33 = 1.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._34 = 0.0f;
|
||||
|
||||
mDisplayInfo.mSittingToStandingTransform._41 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._42 = mEyeHeight;
|
||||
mDisplayInfo.mSittingToStandingTransform._43 = 0.0f;
|
||||
mDisplayInfo.mSittingToStandingTransform._44 = 1.0f;
|
||||
}
|
||||
|
||||
void
|
||||
VRDisplayOculus::ZeroSensor()
|
||||
{
|
||||
ovr_RecenterTrackingOrigin(mSession);
|
||||
UpdateStageParameters();
|
||||
}
|
||||
|
||||
VRHMDSensorState
|
||||
|
@ -440,6 +485,7 @@ VRDisplayOculus::GetSensorState()
|
|||
result = GetSensorState(frameDelta);
|
||||
result.inputFrameID = mInputFrameID;
|
||||
mLastSensorState[result.inputFrameID % kMaxLatencyFrames] = result;
|
||||
result.position[1] -= mEyeHeight;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -988,6 +1034,11 @@ VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
|||
ovrResult orv = ovr_Create(&session, &luid);
|
||||
if (orv == ovrSuccess) {
|
||||
mSession = session;
|
||||
orv = ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
if (orv != ovrSuccess) {
|
||||
NS_WARNING("ovr_SetTrackingOriginType failed.\n");
|
||||
}
|
||||
|
||||
mHMDInfo = new VRDisplayOculus(session);
|
||||
}
|
||||
}
|
||||
|
@ -1099,6 +1150,9 @@ VRSystemManagerOculus::HandleInput()
|
|||
poseState.linearAcceleration[0] = pose.LinearAcceleration.x;
|
||||
poseState.linearAcceleration[1] = pose.LinearAcceleration.y;
|
||||
poseState.linearAcceleration[2] = pose.LinearAcceleration.z;
|
||||
|
||||
float eyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
|
||||
poseState.position[1] -= eyeHeight;
|
||||
}
|
||||
HandlePoseTracking(i, poseState, controller);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ protected:
|
|||
const VRHMDSensorState& aSensorState,
|
||||
const gfx::Rect& aLeftEyeRect,
|
||||
const gfx::Rect& aRightEyeRect) override;
|
||||
void UpdateStageParameters();
|
||||
|
||||
public:
|
||||
explicit VRDisplayOculus(ovrSession aSession);
|
||||
|
@ -82,7 +83,8 @@ protected:
|
|||
RefPtr<ID3D11InputLayout> mInputLayout;
|
||||
|
||||
bool mIsPresenting;
|
||||
|
||||
float mEyeHeight;
|
||||
|
||||
bool UpdateConstantBuffers();
|
||||
|
||||
struct Vertex
|
||||
|
|
|
@ -45,10 +45,6 @@ parent:
|
|||
// asynchronously to children via UpdateDisplayInfo.
|
||||
async RefreshDisplays();
|
||||
|
||||
// GetDisplays synchronously returns the VR displays that have already been
|
||||
// enumerated by RefreshDisplays() but does not enumerate new ones.
|
||||
sync GetDisplays() returns(VRDisplayInfo[] aDisplayInfo);
|
||||
|
||||
// Reset the sensor of the display identified by aDisplayID so that the current
|
||||
// sensor state is the "Zero" position.
|
||||
async ResetSensor(uint32_t aDisplayID);
|
||||
|
|
|
@ -293,16 +293,6 @@ VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
|
|||
bool
|
||||
VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayClient>>& aDisplays)
|
||||
{
|
||||
if (!mDisplaysInitialized) {
|
||||
/**
|
||||
* If we haven't received any asynchronous callback after requesting
|
||||
* display enumeration with RefreshDisplays, get the existing displays
|
||||
* that have already been enumerated by other VRManagerChild instances.
|
||||
*/
|
||||
nsTArray<VRDisplayInfo> displays;
|
||||
Unused << SendGetDisplays(&displays);
|
||||
UpdateDisplayInfo(displays);
|
||||
}
|
||||
aDisplays = mDisplays;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -241,14 +241,6 @@ VRManagerParent::RecvRefreshDisplays()
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
VRManagerParent::RecvGetDisplays(nsTArray<VRDisplayInfo> *aDisplays)
|
||||
{
|
||||
VRManager* vm = VRManager::Get();
|
||||
vm->GetVRDisplayInfo(*aDisplays);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
VRManagerParent::RecvResetSensor(const uint32_t& aDisplayID)
|
||||
{
|
||||
|
|
|
@ -86,7 +86,6 @@ protected:
|
|||
void OnChannelConnected(int32_t pid) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvRefreshDisplays() override;
|
||||
virtual mozilla::ipc::IPCResult RecvGetDisplays(nsTArray<VRDisplayInfo> *aDisplays) override;
|
||||
virtual mozilla::ipc::IPCResult RecvResetSensor(const uint32_t& aDisplayID) override;
|
||||
virtual mozilla::ipc::IPCResult RecvGetSensorState(const uint32_t& aDisplayID, VRHMDSensorState* aState) override;
|
||||
virtual mozilla::ipc::IPCResult RecvSetHaveEventListener(const bool& aHaveEventListener) override;
|
||||
|
|
|
@ -567,8 +567,15 @@ typedef enum {
|
|||
ovrDebugHudStereo_EnumSize = 0x7fffffff
|
||||
} ovrDebugHudStereoMode;
|
||||
|
||||
typedef enum {
|
||||
// Outer boundary - closely represents user setup walls
|
||||
ovrBoundary_Outer = 0x0001,
|
||||
// Play area - safe rectangular area inside outer boundary which can optionally be used to restrict user interactions and motion.
|
||||
ovrBoundary_PlayArea = 0x0100,
|
||||
} ovrBoundaryType;
|
||||
|
||||
typedef ovrBool(OVR_PFN* pfn_ovr_GetBool)(ovrSession session, const char* propertyName, ovrBool defaultVal);
|
||||
typedef ovrBool(OVR_PFN* pfn_ovr_SetBool)(ovrSession session, const char* propertyName, ovrBool value);
|
||||
typedef ovrBool(OVR_PFN* pfn_ovr_SetBool)(ovrSession session, const char* propertyName, ovrBool value);
|
||||
typedef int (OVR_PFN* pfn_ovr_GetInt)(ovrSession session, const char* propertyName, int defaultVal);
|
||||
typedef ovrBool (OVR_PFN* pfn_ovr_SetInt)(ovrSession session, const char* propertyName, int value);
|
||||
typedef float (OVR_PFN* pfn_ovr_GetFloat)(ovrSession session, const char* propertyName, float defaultVal);
|
||||
|
@ -581,8 +588,9 @@ typedef const char* (OVR_PFN* pfn_ovr_GetString)(ovrSession session, const char*
|
|||
const char* defaultVal);
|
||||
typedef ovrBool (OVR_PFN* pfn_ovr_SetString)(ovrSession session, const char* propertyName,
|
||||
const char* value);
|
||||
|
||||
|
||||
typedef ovrResult (OVR_PFN* pfn_ovr_GetBoundaryDimensions)(ovrSession session,
|
||||
ovrBoundaryType boundaryType,
|
||||
ovrVector3f* outDimensions);
|
||||
|
||||
typedef enum {
|
||||
ovrError_MemoryAllocationFailure = -1000,
|
||||
|
@ -714,7 +722,10 @@ typedef ovrResult (OVR_PFN* pfn_ovr_GetMirrorTextureBufferGL)(ovrSession session
|
|||
ovrMirrorTexture mirrorTexture,
|
||||
unsigned int* out_TexId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define OVR_KEY_EYE_HEIGHT "EyeHeight" // float meters
|
||||
#define OVR_DEFAULT_EYE_HEIGHT 1.675f
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -949,8 +949,6 @@ description =
|
|||
description =
|
||||
[PWebRenderBridge::DPGetSnapshot]
|
||||
description =
|
||||
[PVRManager::GetDisplays]
|
||||
description =
|
||||
[PVRManager::GetSensorState]
|
||||
description =
|
||||
[PVRManager::SetHaveEventListener]
|
||||
|
|
|
@ -552,7 +552,7 @@ PrintSingleError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
|
|||
const char* kindPrefix = nullptr;
|
||||
switch (kind) {
|
||||
case PrintErrorKind::Error:
|
||||
break;
|
||||
MOZ_CRASH("unreachable");
|
||||
case PrintErrorKind::Warning:
|
||||
kindPrefix = "warning";
|
||||
break;
|
||||
|
|
|
@ -2294,8 +2294,8 @@ nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument)
|
|||
nsAutoString sheets;
|
||||
elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
|
||||
if (!sheets.IsEmpty() && baseURI) {
|
||||
RefPtr<mozilla::css::Loader> cssLoader =
|
||||
new mozilla::css::Loader(backendType);
|
||||
RefPtr<css::Loader> cssLoader =
|
||||
new css::Loader(backendType, aDocument->GetDocGroup());
|
||||
|
||||
char *str = ToNewCString(sheets);
|
||||
char *newStr = str;
|
||||
|
|
|
@ -218,7 +218,7 @@ LoadSheet(nsIURI* aURI,
|
|||
StyleBackendType aType,
|
||||
RefPtr<StyleSheet>* aResult)
|
||||
{
|
||||
RefPtr<css::Loader> loader = new css::Loader(aType);
|
||||
RefPtr<css::Loader> loader = new css::Loader(aType, nullptr);
|
||||
return loader->LoadSheetSync(aURI, aParsingMode, true, aResult);
|
||||
}
|
||||
|
||||
|
|
|
@ -386,10 +386,10 @@ fails == 315920-14.html 315920-14.html
|
|||
== 315920-15.html 315920-15.html
|
||||
fails == 315920-16.html 315920-16.html
|
||||
fails == 315920-17.html 315920-17.html
|
||||
== 315920-18a.html 315920-18a.html
|
||||
fails == 315920-18b.html 315920-18b.html
|
||||
== 315920-18c.html 315920-18c.html
|
||||
== 315920-18d.html 315920-18d.html
|
||||
skip-if(stylo) == 315920-18a.html 315920-18a.html # bug 1338982, which makes this timing-dependent
|
||||
skip-if(stylo) == 315920-18b.html 315920-18b.html # bug 1338982, which makes this timing-dependent
|
||||
skip-if(stylo) == 315920-18c.html 315920-18c.html # bug 1338982, which makes this timing-dependent
|
||||
skip-if(stylo) == 315920-18d.html 315920-18d.html # bug 1338982, which makes this timing-dependent
|
||||
fails == 315920-18e.html 315920-18e.html
|
||||
fails == 315920-18f.html 315920-18f.html
|
||||
fails == 315920-18g.html 315920-18g.html
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
img {
|
||||
border: 10px solid green;
|
||||
}
|
||||
</style>
|
||||
<img src="nosuch:url">
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
:-moz-broken {
|
||||
border: 10px solid green;
|
||||
}
|
||||
</style>
|
||||
<img src="nosuch:url">
|
|
@ -126,3 +126,5 @@ fuzzy(1,1) == image-orientation-background.html?90&flip image-orientation-r
|
|||
|
||||
== image-resize-percent-height.html image-resize-ref.html
|
||||
== image-resize-percent-width.html image-resize-ref.html
|
||||
|
||||
== moz-broken-matching-1.html moz-broken-matching-1-ref.html
|
||||
|
|
|
@ -988,7 +988,7 @@ CSSStyleSheet::ReparseSheet(const nsAString& aInput)
|
|||
loader = mDocument->CSSLoader();
|
||||
NS_ASSERTION(loader, "Document with no CSS loader!");
|
||||
} else {
|
||||
loader = new css::Loader(StyleBackendType::Gecko);
|
||||
loader = new css::Loader(StyleBackendType::Gecko, nullptr);
|
||||
}
|
||||
|
||||
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/css/Loader.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "nsCSSScanner.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDocument.h"
|
||||
|
@ -153,7 +154,11 @@ ErrorReporter::~ErrorReporter()
|
|||
// balance between performance and memory usage, so we only allow
|
||||
// short-term caching.
|
||||
if (sSpecCache && sSpecCache->IsInUse() && !sSpecCache->IsPending()) {
|
||||
if (NS_FAILED(NS_DispatchToCurrentThread(sSpecCache))) {
|
||||
nsCOMPtr<nsIRunnable> runnable(sSpecCache);
|
||||
nsresult rv =
|
||||
SystemGroup::Dispatch("ShortTermURISpecCache", TaskCategory::Other,
|
||||
runnable.forget());
|
||||
if (NS_FAILED(rv)) {
|
||||
// Peform the "deferred" cleanup immediately if the dispatch fails.
|
||||
sSpecCache->Run();
|
||||
} else {
|
||||
|
|
|
@ -104,6 +104,8 @@ FontFaceSet::FontFaceSet(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument)
|
|||
, mHasLoadingFontFacesIsDirty(false)
|
||||
, mDelayedLoadCheck(false)
|
||||
{
|
||||
MOZ_ASSERT(mDocument, "We should get a valid document from the caller!");
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aWindow);
|
||||
|
||||
// If the pref is not set, don't create the Promise (which the page wouldn't
|
||||
|
@ -1473,9 +1475,9 @@ FontFaceSet::OnFontFaceStatusChanged(FontFace* aFontFace)
|
|||
if (!mDelayedLoadCheck) {
|
||||
mDelayedLoadCheck = true;
|
||||
nsCOMPtr<nsIRunnable> checkTask =
|
||||
NewRunnableMethod("FontFaceSet::CheckLoadingFinishedAfterDelay",
|
||||
this, &FontFaceSet::CheckLoadingFinishedAfterDelay);
|
||||
NS_DispatchToMainThread(checkTask);
|
||||
NewRunnableMethod(this, &FontFaceSet::CheckLoadingFinishedAfterDelay);
|
||||
mDocument->Dispatch("FontFaceSet::CheckLoadingFinishedAfterDelay",
|
||||
TaskCategory::Other, checkTask.forget());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,6 +162,8 @@ public:
|
|||
return set ? set->GetPresContext() : nullptr;
|
||||
}
|
||||
|
||||
nsIDocument* Document() const { return mDocument; }
|
||||
|
||||
// -- Web IDL --------------------------------------------------------------
|
||||
|
||||
IMPL_EVENT_HANDLER(loading)
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
#include "mozilla/css/Loader.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIUnicharStreamLoader.h"
|
||||
#include "nsSyncLoadService.h"
|
||||
|
@ -519,8 +520,9 @@ LoaderReusableStyleSheets::FindReusableStyleSheet(nsIURI* aURL,
|
|||
* Loader Implementation *
|
||||
*************************/
|
||||
|
||||
Loader::Loader(StyleBackendType aType)
|
||||
Loader::Loader(StyleBackendType aType, DocGroup* aDocGroup)
|
||||
: mDocument(nullptr)
|
||||
, mDocGroup(aDocGroup)
|
||||
, mDatasToNotifyOn(0)
|
||||
, mCompatMode(eCompatibility_FullStandards)
|
||||
, mStyleBackendType(Some(aType))
|
||||
|
@ -542,6 +544,8 @@ Loader::Loader(nsIDocument* aDocument)
|
|||
, mSyncCallback(false)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(mDocument, "We should get a valid document from the caller!");
|
||||
|
||||
// We can just use the preferred set, since there are no sheets in the
|
||||
// document yet (if there are, how did they get there? _we_ load the sheets!)
|
||||
// and hence the selected set makes no sense at this time.
|
||||
|
@ -2471,13 +2475,24 @@ Loader::PostLoadEvent(nsIURI* aURI,
|
|||
aObserver,
|
||||
nullptr,
|
||||
mDocument);
|
||||
NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!mPostedEvents.AppendElement(evt)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = NS_DispatchToCurrentThread(evt);
|
||||
nsresult rv;
|
||||
RefPtr<SheetLoadData> runnable(evt);
|
||||
if (mDocument) {
|
||||
rv = mDocument->Dispatch("SheetLoadData", TaskCategory::Other,
|
||||
runnable.forget());
|
||||
} else if (mDocGroup) {
|
||||
rv = mDocGroup->Dispatch("SheetLoadData", TaskCategory::Other,
|
||||
runnable.forget());
|
||||
} else {
|
||||
rv = SystemGroup::Dispatch("SheetLoadData", TaskCategory::Other,
|
||||
runnable.forget());
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch stylesheet load event");
|
||||
mPostedEvents.RemoveElement(evt);
|
||||
|
|
|
@ -36,6 +36,7 @@ class nsIStyleSheetLinkingElement;
|
|||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DocGroup;
|
||||
class Element;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -191,7 +192,11 @@ class Loader final {
|
|||
typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
|
||||
|
||||
public:
|
||||
explicit Loader(StyleBackendType aType);
|
||||
// aDocGroup is used for dispatching SheetLoadData in PostLoadEvent(). It
|
||||
// can be null if you want to use this constructor, and there's no
|
||||
// document when the Loader is constructed.
|
||||
Loader(StyleBackendType aType, mozilla::dom::DocGroup* aDocGroup);
|
||||
|
||||
explicit Loader(nsIDocument*);
|
||||
|
||||
private:
|
||||
|
@ -574,6 +579,8 @@ private:
|
|||
// DropDocumentReference().
|
||||
nsIDocument* MOZ_NON_OWNING_REF mDocument; // the document we live for
|
||||
|
||||
// For dispatching events via DocGroup::Dispatch() when mDocument is nullptr.
|
||||
RefPtr<mozilla::dom::DocGroup> mDocGroup;
|
||||
|
||||
// Number of datas still waiting to be notified on if we're notifying on a
|
||||
// whole bunch at once (e.g. in one of the stop methods). This is used to
|
||||
|
|
|
@ -71,7 +71,7 @@ PreloadedStyleSheet::GetSheet(StyleBackendType aType, StyleSheet** aResult)
|
|||
aType == StyleBackendType::Gecko ? mGecko : mServo;
|
||||
|
||||
if (!sheet) {
|
||||
RefPtr<css::Loader> loader = new css::Loader(aType);
|
||||
RefPtr<css::Loader> loader = new css::Loader(aType, nullptr);
|
||||
nsresult rv = loader->LoadSheetSync(mURI, mParsingMode, true, &sheet);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
MOZ_ASSERT(sheet);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "mozilla/ServoElementSnapshot.h"
|
||||
#include "mozilla/ServoRestyleManager.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "mozilla/DeclarationBlockInlines.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ElementInlines.h"
|
||||
|
@ -344,7 +345,8 @@ Gecko_DropElementSnapshot(ServoElementSnapshotOwned aSnapshot)
|
|||
// descendants of a new display:none root).
|
||||
if (MOZ_UNLIKELY(!NS_IsMainThread())) {
|
||||
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() { delete aSnapshot; });
|
||||
NS_DispatchToMainThread(task.forget());
|
||||
SystemGroup::Dispatch("Gecko_DropElementSnapshot", TaskCategory::Other,
|
||||
task.forget());
|
||||
} else {
|
||||
delete aSnapshot;
|
||||
}
|
||||
|
|
|
@ -3057,7 +3057,9 @@ css::ImageValue::Initialize(nsIDocument* aDocument)
|
|||
|
||||
css::ImageValue::~ImageValue()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread() || mRequests.Count() == 0,
|
||||
"Destructor should run on main thread, or on non-main thread "
|
||||
"when mRequest is empty!");
|
||||
|
||||
for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsIDocument* doc = iter.Key();
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
#include "nsFontFaceLoader.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#include "nsError.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
@ -55,6 +53,8 @@ nsFontFaceLoader::nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry,
|
|||
mFontFaceSet(aFontFaceSet),
|
||||
mChannel(aChannel)
|
||||
{
|
||||
MOZ_ASSERT(mFontFaceSet,
|
||||
"We should get a valid FontFaceSet from the caller!");
|
||||
mStartTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
|
@ -87,10 +87,13 @@ nsFontFaceLoader::StartedLoading(nsIStreamLoader* aStreamLoader)
|
|||
if (loadTimeout > 0) {
|
||||
mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (mLoadTimer) {
|
||||
mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
|
||||
static_cast<void*>(this),
|
||||
loadTimeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mLoadTimer->SetTarget(
|
||||
mFontFaceSet->Document()->EventTargetFor(TaskCategory::Other));
|
||||
mLoadTimer->InitWithNamedFuncCallback(LoadTimerCallback,
|
||||
static_cast<void*>(this),
|
||||
loadTimeout,
|
||||
nsITimer::TYPE_ONE_SHOT,
|
||||
"LoadTimerCallback");
|
||||
}
|
||||
} else {
|
||||
mUserFontEntry->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
|
||||
|
|
|
@ -773,7 +773,7 @@ nsLayoutStylesheetCache::LoadSheet(nsIURI* aURI,
|
|||
gCSSLoader_Servo;
|
||||
|
||||
if (!loader) {
|
||||
loader = new mozilla::css::Loader(mBackendType);
|
||||
loader = new Loader(mBackendType, nullptr);
|
||||
if (!loader) {
|
||||
ErrorLoadingSheet(aURI, "no Loader", eCrash);
|
||||
return;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "CounterStyleManager.h"
|
||||
|
||||
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/ImageTracker.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -1890,7 +1891,7 @@ nsStyleGradient::HasCalc()
|
|||
|
||||
/**
|
||||
* Runnable to release the nsStyleImageRequest's mRequestProxy,
|
||||
* mImageValue and mImageValue on the main thread, and to perform
|
||||
* mImageValue and mImageTracker on the main thread, and to perform
|
||||
* any necessary unlocking and untracking of the image.
|
||||
*/
|
||||
class StyleImageRequestCleanupTask : public mozilla::Runnable
|
||||
|
@ -1911,7 +1912,8 @@ public:
|
|||
|
||||
NS_IMETHOD Run() final
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mRequestProxy || NS_IsMainThread(),
|
||||
"If mRequestProxy is non-null, we need to run on main thread!");
|
||||
|
||||
if (!mRequestProxy) {
|
||||
return NS_OK;
|
||||
|
@ -1932,7 +1934,15 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual ~StyleImageRequestCleanupTask() { MOZ_ASSERT(NS_IsMainThread()); }
|
||||
virtual ~StyleImageRequestCleanupTask()
|
||||
{
|
||||
MOZ_ASSERT(mImageValue->mRequests.Count() == 0 || NS_IsMainThread(),
|
||||
"If mImageValue has any mRequests, we need to run on main "
|
||||
"thread to release ImageValues!");
|
||||
MOZ_ASSERT((!mRequestProxy && !mImageTracker) || NS_IsMainThread(),
|
||||
"mRequestProxy and mImageTracker's destructor need to run "
|
||||
"on the main thread!");
|
||||
}
|
||||
|
||||
private:
|
||||
Mode mModeFlags;
|
||||
|
@ -1986,10 +1996,13 @@ nsStyleImageRequest::~nsStyleImageRequest()
|
|||
mRequestProxy.forget(),
|
||||
mImageValue.forget(),
|
||||
mImageTracker.forget());
|
||||
if (NS_IsMainThread()) {
|
||||
if (NS_IsMainThread() || !IsResolved()) {
|
||||
task->Run();
|
||||
} else {
|
||||
NS_DispatchToMainThread(task.forget());
|
||||
MOZ_ASSERT(IsResolved() == bool(mDocGroup),
|
||||
"We forgot to cache mDocGroup in Resolve()?");
|
||||
mDocGroup->Dispatch("StyleImageRequestCleanupTask",
|
||||
TaskCategory::Other, task.forget());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2003,8 +2016,10 @@ nsStyleImageRequest::Resolve(nsPresContext* aPresContext)
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsResolved(), "already resolved");
|
||||
MOZ_ASSERT(aPresContext);
|
||||
|
||||
mResolved = true;
|
||||
mDocGroup = aPresContext->Document()->GetDocGroup();
|
||||
|
||||
// For now, just have unique nsCSSValue/ImageValue objects. We should
|
||||
// really store the ImageValue on the Servo specified value, so that we can
|
||||
|
|
|
@ -385,6 +385,9 @@ private:
|
|||
RefPtr<mozilla::css::ImageValue> mImageValue;
|
||||
RefPtr<mozilla::dom::ImageTracker> mImageTracker;
|
||||
|
||||
// Cache DocGroup for dispatching events in the destructor.
|
||||
RefPtr<mozilla::dom::DocGroup> mDocGroup;
|
||||
|
||||
Mode mModeFlags;
|
||||
bool mResolved;
|
||||
};
|
||||
|
|
|
@ -378,7 +378,6 @@ to mochitest command.
|
|||
* background-position invalid 3-value form **issue to be filed**
|
||||
* test_shorthand_property_getters.html `should serialize to 4-value` [2]
|
||||
* test_variables.html `--weird`: name of custom property is not escaped properly servo/servo#15399 [1]
|
||||
* ... `got "--`: CSS-wide keywords in custom properties servo/servo#15401 [3]
|
||||
* image-layer values should omit some of its parts when they are initial servo/servo#15951
|
||||
* test_shorthand_property_getters.html `background` [2]
|
||||
* counter-{reset,increment} doesn't serialize none servo/servo#15977
|
||||
|
@ -407,7 +406,7 @@ to mochitest command.
|
|||
* :-moz-window-inactive bug 1348489
|
||||
* test_selectors.html `:-moz-window-inactive` [2]
|
||||
* :-moz-{first,last}-node
|
||||
* test_selectors.html `:-moz-` [13]
|
||||
* test_selectors.html `:-moz-` [6]
|
||||
* ... `unexpected rule index` [5]
|
||||
* :dir
|
||||
* test_selectors.html `:dir` [10]
|
||||
|
|
|
@ -66,18 +66,26 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
|
||||
private synchronized void onSample(Sample sample) {
|
||||
if (sample == null) {
|
||||
Log.w(LOGTAG, "WARN: null input sample");
|
||||
// Ignore empty input.
|
||||
mSamplePool.recycleInput(mDequeuedSamples.remove());
|
||||
Log.w(LOGTAG, "WARN: empty input sample");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sample.isEOS()) {
|
||||
Sample temp = sample;
|
||||
sample = mDequeuedSamples.remove();
|
||||
sample.info = temp.info;
|
||||
sample.cryptoInfo = temp.cryptoInfo;
|
||||
temp.dispose();
|
||||
if (sample.isEOS()) {
|
||||
queueSample(sample);
|
||||
return;
|
||||
}
|
||||
|
||||
Sample dequeued = mDequeuedSamples.remove();
|
||||
dequeued.info = sample.info;
|
||||
dequeued.cryptoInfo = sample.cryptoInfo;
|
||||
queueSample(dequeued);
|
||||
|
||||
sample.dispose();
|
||||
}
|
||||
|
||||
private void queueSample(Sample sample) {
|
||||
if (!mInputSamples.offer(sample)) {
|
||||
reportError(Error.FATAL, new Exception("FAIL: input sample queue is full"));
|
||||
return;
|
||||
|
@ -196,8 +204,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
return;
|
||||
}
|
||||
|
||||
Sample output = obtainOutputSample(index, info);
|
||||
try {
|
||||
Sample output = obtainOutputSample(index, info);
|
||||
mSentIndices.add(index);
|
||||
mSentOutputs.add(output);
|
||||
mCallbacks.onOutput(output);
|
||||
|
@ -471,8 +479,13 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized Sample dequeueInput(int size) {
|
||||
return mInputProcessor.onAllocate(size);
|
||||
public synchronized Sample dequeueInput(int size) throws RemoteException {
|
||||
try {
|
||||
return mInputProcessor.onAllocate(size);
|
||||
} catch (Exception e) {
|
||||
// Translate allocation error to remote exception.
|
||||
throw new RemoteException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -170,34 +170,40 @@ public final class CodecProxy {
|
|||
Log.e(LOGTAG, "cannot send input to an ended codec");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean eos = info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM;
|
||||
mCallbacks.setEndOfInput(eos);
|
||||
|
||||
if (eos) {
|
||||
return sendInput(Sample.EOS);
|
||||
}
|
||||
|
||||
try {
|
||||
return sendInput(mRemote.dequeueInput(info.size).set(bytes, info, cryptoInfo));
|
||||
} catch (RemoteException e) {
|
||||
Log.e(LOGTAG, "fail to dequeue input buffer", e);
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
Log.e(LOGTAG, "fail to copy input data.", e);
|
||||
// Balance dequeue/queue.
|
||||
return sendInput(null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendInput(Sample sample) {
|
||||
try {
|
||||
Sample sample = processInput(bytes, info, cryptoInfo);
|
||||
if (sample == null) {
|
||||
return false;
|
||||
}
|
||||
mRemote.queueInput(sample);
|
||||
sample.dispose();
|
||||
if (sample != null) {
|
||||
sample.dispose();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "fail to input sample: size=" + info.size +
|
||||
", pts=" + info.presentationTimeUs +
|
||||
", flags=" + Integer.toHexString(info.flags), e);
|
||||
Log.e(LOGTAG, "fail to queue input:" + sample, e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Sample processInput(ByteBuffer bytes, BufferInfo info, CryptoInfo cryptoInfo)
|
||||
throws RemoteException, IOException {
|
||||
if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
|
||||
mCallbacks.setEndOfInput(true);
|
||||
return Sample.EOS;
|
||||
} else {
|
||||
mCallbacks.setEndOfInput(false);
|
||||
return mRemote.dequeueInput(info.size).set(bytes, info, cryptoInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public synchronized boolean flush() {
|
||||
if (mRemote == null) {
|
||||
|
|
|
@ -32,7 +32,7 @@ final class SamplePool {
|
|||
mDefaultBufferSize = size;
|
||||
}
|
||||
|
||||
private synchronized Sample obtain(int size) {
|
||||
private synchronized Sample obtain(int size) {
|
||||
if (!mRecycledSamples.isEmpty()) {
|
||||
return mRecycledSamples.remove(0);
|
||||
}
|
||||
|
@ -48,13 +48,11 @@ final class SamplePool {
|
|||
SharedMemory shm = null;
|
||||
try {
|
||||
shm = new SharedMemory(mNextId++, Math.max(size, mDefaultBufferSize));
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException | IOException e) {
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
|
||||
return shm != null ? Sample.create(shm) : Sample.create();
|
||||
return Sample.create(shm);
|
||||
}
|
||||
|
||||
private synchronized void recycle(Sample recycled) {
|
||||
|
|
|
@ -54,7 +54,11 @@ public final class SharedMemBuffer implements Sample.Buffer {
|
|||
if (!src.isDirect()) {
|
||||
throw new IOException("SharedMemBuffer only support reading from direct byte buffer.");
|
||||
}
|
||||
nativeReadFromDirectBuffer(src, mSharedMem.getPointer(), offset, size);
|
||||
try {
|
||||
nativeReadFromDirectBuffer(src, mSharedMem.getPointer(), offset, size);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private native static void nativeReadFromDirectBuffer(ByteBuffer src, long dest, int offset, int size);
|
||||
|
@ -64,7 +68,11 @@ public final class SharedMemBuffer implements Sample.Buffer {
|
|||
if (!dest.isDirect()) {
|
||||
throw new IOException("SharedMemBuffer only support writing to direct byte buffer.");
|
||||
}
|
||||
nativeWriteToDirectBuffer(mSharedMem.getPointer(), dest, offset, size);
|
||||
try {
|
||||
nativeWriteToDirectBuffer(mSharedMem.getPointer(), dest, offset, size);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private native static void nativeWriteToDirectBuffer(long src, ByteBuffer dest, int offset, int size);
|
||||
|
|
|
@ -133,7 +133,12 @@ public class SharedMemory implements Parcelable {
|
|||
}
|
||||
|
||||
if (!mIsMapped) {
|
||||
mHandle = map(getFD(), mSize);
|
||||
try {
|
||||
mHandle = map(getFD(), mSize);
|
||||
} catch (NullPointerException e) {
|
||||
Log.e(LOGTAG, "SharedMemory#" + mId + " error.", e);
|
||||
throw e;
|
||||
}
|
||||
if (mHandle != 0) {
|
||||
mIsMapped = true;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
* 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/. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
@ -52,6 +54,12 @@ jlong JNICALL
|
|||
Java_org_mozilla_gecko_mozglue_SharedMemory_map(JNIEnv *env, jobject jobj, jint fd, jint length)
|
||||
{
|
||||
void* address = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (address == MAP_FAILED) {
|
||||
char msg[128];
|
||||
snprintf(msg, sizeof(msg), "mmap failed. errno=%d", errno);
|
||||
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), msg);
|
||||
return 0;
|
||||
}
|
||||
return jlong(address);
|
||||
}
|
||||
|
||||
|
@ -62,4 +70,4 @@ Java_org_mozilla_gecko_mozglue_SharedMemory_unmap(JNIEnv *env, jobject jobj, jlo
|
|||
munmap((void*)address, (size_t)size);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,13 +70,11 @@ add_task(async function test_decline_undecline() {
|
|||
await SyncTestingInfrastructure(server);
|
||||
|
||||
try {
|
||||
let bzGuid = "999999999999";
|
||||
await PlacesSyncUtils.bookmarks.insert({
|
||||
kind: PlacesSyncUtils.bookmarks.KINDS.BOOKMARK,
|
||||
syncId: bzGuid,
|
||||
parentSyncId: "menu",
|
||||
let { guid: bzGuid } = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
url: "https://bugzilla.mozilla.org",
|
||||
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
title: "bugzilla",
|
||||
});
|
||||
|
||||
ok(!getBookmarkWBO(server, bzGuid), "Shouldn't have been uploaded yet");
|
||||
|
|
|
@ -478,7 +478,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
|||
if let Some(font_size) = font_size {
|
||||
hints.push(from_declaration(
|
||||
shared_lock,
|
||||
PropertyDeclaration::FontSize(font_size::SpecifiedValue(font_size.into()))))
|
||||
PropertyDeclaration::FontSize(
|
||||
font_size::SpecifiedValue::from_html_size(font_size as u8)
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
let cellspacing = if let Some(this) = self.downcast::<HTMLTableElement>() {
|
||||
|
|
|
@ -18,7 +18,6 @@ use html5ever_atoms::LocalName;
|
|||
use servo_atoms::Atom;
|
||||
use style::attr::AttrValue;
|
||||
use style::str::{HTML_SPACE_CHARACTERS, read_numbers};
|
||||
use style::values::specified;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct HTMLFontElement {
|
||||
|
@ -62,8 +61,7 @@ impl HTMLFontElementMethods for HTMLFontElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-font-size
|
||||
fn SetSize(&self, value: DOMString) {
|
||||
let element = self.upcast::<Element>();
|
||||
let length = parse_length(&value);
|
||||
element.set_attribute(&local_name!("size"), AttrValue::Length(value.into(), length));
|
||||
element.set_attribute(&local_name!("size"), parse_size(&value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,10 +74,7 @@ impl VirtualMethods for HTMLFontElement {
|
|||
match name {
|
||||
&local_name!("face") => AttrValue::from_atomic(value.into()),
|
||||
&local_name!("color") => AttrValue::from_legacy_color(value.into()),
|
||||
&local_name!("size") => {
|
||||
let length = parse_length(&value);
|
||||
AttrValue::Length(value.into(), length)
|
||||
},
|
||||
&local_name!("size") => parse_size(&value),
|
||||
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +83,7 @@ impl VirtualMethods for HTMLFontElement {
|
|||
pub trait HTMLFontElementLayoutHelpers {
|
||||
fn get_color(&self) -> Option<RGBA>;
|
||||
fn get_face(&self) -> Option<Atom>;
|
||||
fn get_size(&self) -> Option<specified::Length>;
|
||||
fn get_size(&self) -> Option<u32>;
|
||||
}
|
||||
|
||||
impl HTMLFontElementLayoutHelpers for LayoutJS<HTMLFontElement> {
|
||||
|
@ -113,18 +108,21 @@ impl HTMLFontElementLayoutHelpers for LayoutJS<HTMLFontElement> {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn get_size(&self) -> Option<specified::Length> {
|
||||
unsafe {
|
||||
fn get_size(&self) -> Option<u32> {
|
||||
let size = unsafe {
|
||||
(*self.upcast::<Element>().unsafe_get())
|
||||
.get_attr_for_layout(&ns!(), &local_name!("size"))
|
||||
.and_then(AttrValue::as_length)
|
||||
.cloned()
|
||||
};
|
||||
match size {
|
||||
Some(&AttrValue::UInt(_, s)) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size
|
||||
fn parse_length(mut input: &str) -> Option<specified::Length> {
|
||||
fn parse_size(mut input: &str) -> AttrValue {
|
||||
let original_input = input;
|
||||
// Steps 1 & 2 are not relevant
|
||||
|
||||
// Step 3
|
||||
|
@ -138,7 +136,7 @@ fn parse_length(mut input: &str) -> Option<specified::Length> {
|
|||
let mut input_chars = input.chars().peekable();
|
||||
let parse_mode = match input_chars.peek() {
|
||||
// Step 4
|
||||
None => return None,
|
||||
None => return AttrValue::String(original_input.into()),
|
||||
|
||||
// Step 5
|
||||
Some(&'+') => {
|
||||
|
@ -155,7 +153,7 @@ fn parse_length(mut input: &str) -> Option<specified::Length> {
|
|||
// Steps 6, 7, 8
|
||||
let mut value = match read_numbers(input_chars) {
|
||||
(Some(v), _) if v >= 0 => v,
|
||||
_ => return None,
|
||||
_ => return AttrValue::String(original_input.into()),
|
||||
};
|
||||
|
||||
// Step 9
|
||||
|
@ -166,5 +164,5 @@ fn parse_length(mut input: &str) -> Option<specified::Length> {
|
|||
}
|
||||
|
||||
// Steps 10, 11, 12
|
||||
Some(specified::Length::from_font_size_int(value as u8))
|
||||
AttrValue::UInt(original_input.into(), value as u32)
|
||||
}
|
||||
|
|
|
@ -112,12 +112,56 @@ pub fn matches<E>(selector_list: &[Selector<E::Impl>],
|
|||
})
|
||||
}
|
||||
|
||||
fn may_match<E>(mut selector: &ComplexSelector<E::Impl>,
|
||||
bf: &BloomFilter)
|
||||
-> bool
|
||||
where E: Element,
|
||||
{
|
||||
// See if the bloom filter can exclude any of the descendant selectors, and
|
||||
// reject if we can.
|
||||
loop {
|
||||
match selector.next {
|
||||
None => break,
|
||||
Some((ref cs, Combinator::Descendant)) => selector = &**cs,
|
||||
Some((ref cs, _)) => {
|
||||
selector = &**cs;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
for ss in selector.compound_selector.iter() {
|
||||
match *ss {
|
||||
SimpleSelector::LocalName(LocalName { ref name, ref lower_name }) => {
|
||||
if !bf.might_contain(name) &&
|
||||
!bf.might_contain(lower_name) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
SimpleSelector::Namespace(ref namespace) => {
|
||||
if !bf.might_contain(&namespace.url) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
SimpleSelector::ID(ref id) => {
|
||||
if !bf.might_contain(id) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
SimpleSelector::Class(ref class) => {
|
||||
if !bf.might_contain(class) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't proven otherwise, it may match.
|
||||
true
|
||||
}
|
||||
|
||||
/// Determines whether the given element matches the given complex selector.
|
||||
///
|
||||
/// NB: If you add support for any new kinds of selectors to this routine, be sure to set
|
||||
/// `shareable` to false unless you are willing to update the style sharing logic. Otherwise things
|
||||
/// will almost certainly break as elements will start mistakenly sharing styles. (See
|
||||
/// `can_share_style_with` in `servo/components/style/matching.rs`.)
|
||||
pub fn matches_complex_selector<E>(selector: &ComplexSelector<E::Impl>,
|
||||
element: &E,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
|
@ -126,7 +170,13 @@ pub fn matches_complex_selector<E>(selector: &ComplexSelector<E::Impl>,
|
|||
-> bool
|
||||
where E: Element
|
||||
{
|
||||
match matches_complex_selector_internal(selector, element, parent_bf, relations, flags) {
|
||||
if let Some(filter) = parent_bf {
|
||||
if !may_match::<E>(selector, filter) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
match matches_complex_selector_internal(selector, element, relations, flags) {
|
||||
SelectorMatchingResult::Matched => {
|
||||
match selector.next {
|
||||
Some((_, Combinator::NextSibling)) |
|
||||
|
@ -190,81 +240,19 @@ enum SelectorMatchingResult {
|
|||
NotMatchedGlobally,
|
||||
}
|
||||
|
||||
/// Quickly figures out whether or not the complex selector is worth doing more
|
||||
/// work on. If the simple selectors don't match, or there's a child selector
|
||||
/// that does not appear in the bloom parent bloom filter, we can exit early.
|
||||
fn can_fast_reject<E>(mut selector: &ComplexSelector<E::Impl>,
|
||||
element: &E,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
relations: &mut StyleRelations,
|
||||
flags: &mut ElementSelectorFlags)
|
||||
-> Option<SelectorMatchingResult>
|
||||
where E: Element
|
||||
{
|
||||
if !selector.compound_selector.iter().all(|simple_selector| {
|
||||
matches_simple_selector(simple_selector, element, parent_bf, relations, flags) }) {
|
||||
return Some(SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling);
|
||||
}
|
||||
|
||||
let bf: &BloomFilter = match parent_bf {
|
||||
None => return None,
|
||||
Some(ref bf) => bf,
|
||||
};
|
||||
|
||||
// See if the bloom filter can exclude any of the descendant selectors, and
|
||||
// reject if we can.
|
||||
loop {
|
||||
match selector.next {
|
||||
None => break,
|
||||
Some((ref cs, Combinator::Descendant)) => selector = &**cs,
|
||||
Some((ref cs, _)) => {
|
||||
selector = &**cs;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
for ss in selector.compound_selector.iter() {
|
||||
match *ss {
|
||||
SimpleSelector::LocalName(LocalName { ref name, ref lower_name }) => {
|
||||
if !bf.might_contain(name) &&
|
||||
!bf.might_contain(lower_name) {
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
SimpleSelector::Namespace(ref namespace) => {
|
||||
if !bf.might_contain(&namespace.url) {
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
SimpleSelector::ID(ref id) => {
|
||||
if !bf.might_contain(id) {
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
SimpleSelector::Class(ref class) => {
|
||||
if !bf.might_contain(class) {
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can't fast reject.
|
||||
None
|
||||
}
|
||||
|
||||
fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
||||
element: &E,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
relations: &mut StyleRelations,
|
||||
flags: &mut ElementSelectorFlags)
|
||||
-> SelectorMatchingResult
|
||||
element: &E,
|
||||
relations: &mut StyleRelations,
|
||||
flags: &mut ElementSelectorFlags)
|
||||
-> SelectorMatchingResult
|
||||
where E: Element
|
||||
{
|
||||
if let Some(result) = can_fast_reject(selector, element, parent_bf, relations, flags) {
|
||||
return result;
|
||||
let matches_all_simple_selectors = selector.compound_selector.iter().all(|simple| {
|
||||
matches_simple_selector(simple, element, relations, flags)
|
||||
});
|
||||
|
||||
if !matches_all_simple_selectors {
|
||||
return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
|
||||
}
|
||||
|
||||
match selector.next {
|
||||
|
@ -287,10 +275,9 @@ fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
|||
Some(next_element) => next_element,
|
||||
};
|
||||
let result = matches_complex_selector_internal(&**next_selector,
|
||||
&element,
|
||||
parent_bf,
|
||||
relations,
|
||||
flags);
|
||||
&element,
|
||||
relations,
|
||||
flags);
|
||||
match (result, combinator) {
|
||||
// Return the status immediately.
|
||||
(SelectorMatchingResult::Matched, _) => return result,
|
||||
|
@ -332,7 +319,6 @@ fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
|||
fn matches_simple_selector<E>(
|
||||
selector: &SimpleSelector<E::Impl>,
|
||||
element: &E,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
relations: &mut StyleRelations,
|
||||
flags: &mut ElementSelectorFlags)
|
||||
-> bool
|
||||
|
@ -466,7 +452,10 @@ fn matches_simple_selector<E>(
|
|||
}
|
||||
SimpleSelector::Negation(ref negated) => {
|
||||
!negated.iter().all(|s| {
|
||||
matches_complex_selector(s, element, parent_bf, relations, flags)
|
||||
match matches_complex_selector_internal(s, element, relations, flags) {
|
||||
SelectorMatchingResult::Matched => true,
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -772,17 +772,22 @@ mod bindings {
|
|||
|
||||
pub fn generate() {
|
||||
use self::common::*;
|
||||
use std::fs;
|
||||
use std::thread;
|
||||
use std::{env, fs, thread};
|
||||
println!("cargo:rerun-if-changed=build_gecko.rs");
|
||||
fs::create_dir_all(&*OUTDIR_PATH).unwrap();
|
||||
bindings::setup_logging();
|
||||
let threads = vec![
|
||||
thread::spawn(|| bindings::generate_structs(BuildType::Debug)),
|
||||
thread::spawn(|| bindings::generate_structs(BuildType::Release)),
|
||||
thread::spawn(|| bindings::generate_bindings()),
|
||||
];
|
||||
for t in threads.into_iter() {
|
||||
t.join().unwrap();
|
||||
if env::var("STYLO_BUILD_LOG").is_ok() {
|
||||
bindings::generate_structs(BuildType::Debug);
|
||||
bindings::generate_structs(BuildType::Release);
|
||||
bindings::generate_bindings();
|
||||
} else {
|
||||
let threads = vec![
|
||||
thread::spawn(|| bindings::generate_structs(BuildType::Debug)),
|
||||
thread::spawn(|| bindings::generate_structs(BuildType::Release)),
|
||||
thread::spawn(|| bindings::generate_bindings()),
|
||||
];
|
||||
for t in threads.into_iter() {
|
||||
t.join().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,6 +341,10 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
let selectors = parser.parse_comma_separated(|input| {
|
||||
ComplexSelector::parse(self, input)
|
||||
})?;
|
||||
// Selectors inside `:-moz-any` may not include combinators.
|
||||
if selectors.iter().any(|s| s.next.is_some()) {
|
||||
return Err(())
|
||||
}
|
||||
NonTSPseudoClass::MozAny(selectors)
|
||||
}
|
||||
_ => return Err(())
|
||||
|
|
|
@ -400,24 +400,129 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
self.0.to_css(dest)
|
||||
match *self {
|
||||
SpecifiedValue::Length(ref lop) => lop.to_css(dest),
|
||||
SpecifiedValue::Keyword(kw) => kw.to_css(dest),
|
||||
SpecifiedValue::Smaller => dest.write_str("smaller"),
|
||||
SpecifiedValue::Larger => dest.write_str("larger"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasViewportPercentage for SpecifiedValue {
|
||||
fn has_viewport_percentage(&self) -> bool {
|
||||
return self.0.has_viewport_percentage()
|
||||
match *self {
|
||||
SpecifiedValue::Length(ref lop) => lop.has_viewport_percentage(),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct SpecifiedValue(pub specified::LengthOrPercentage);
|
||||
pub enum SpecifiedValue {
|
||||
Length(specified::LengthOrPercentage),
|
||||
Keyword(KeywordSize),
|
||||
Smaller,
|
||||
Larger,
|
||||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use app_units::Au;
|
||||
pub type T = Au;
|
||||
}
|
||||
|
||||
/// CSS font keywords
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum KeywordSize {
|
||||
XXSmall = 0,
|
||||
XSmall = 1,
|
||||
Small = 2,
|
||||
Medium = 3,
|
||||
Large = 4,
|
||||
XLarge = 5,
|
||||
XXLarge = 6,
|
||||
// This is not a real font keyword and will not parse
|
||||
// HTML font-size 7 corresponds to this value
|
||||
XXXLarge = 7,
|
||||
}
|
||||
|
||||
pub use self::KeywordSize::*;
|
||||
|
||||
impl KeywordSize {
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
Ok(match_ignore_ascii_case! {&*input.expect_ident()?,
|
||||
"xx-small" => XXSmall,
|
||||
"x-small" => XSmall,
|
||||
"small" => Small,
|
||||
"medium" => Medium,
|
||||
"large" => Large,
|
||||
"x-large" => XLarge,
|
||||
"xx-large" => XXLarge,
|
||||
_ => return Err(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for KeywordSize {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
dest.write_str(match *self {
|
||||
XXSmall => "xx-small",
|
||||
XSmall => "x-small",
|
||||
Small => "small",
|
||||
Medium => "medium",
|
||||
Large => "large",
|
||||
XLarge => "x-large",
|
||||
XXLarge => "xx-large",
|
||||
XXXLarge => unreachable!("We should never serialize \
|
||||
specified values set via
|
||||
HTML presentation attributes"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for KeywordSize {
|
||||
type ComputedValue = Au;
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> computed_value::T {
|
||||
// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
use values::FONT_MEDIUM_PX;
|
||||
match *self {
|
||||
XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5,
|
||||
XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
|
||||
Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
|
||||
Medium => Au::from_px(FONT_MEDIUM_PX),
|
||||
Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
|
||||
XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
|
||||
XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2,
|
||||
XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(_: &computed_value::T) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedValue {
|
||||
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size
|
||||
pub fn from_html_size(size: u8) -> Self {
|
||||
SpecifiedValue::Keyword(match size {
|
||||
// If value is less than 1, let it be 1.
|
||||
0 | 1 => XSmall,
|
||||
2 => Small,
|
||||
3 => Medium,
|
||||
4 => Large,
|
||||
5 => XLarge,
|
||||
6 => XXLarge,
|
||||
// If value is greater than 7, let it be 7.
|
||||
_ => XXXLarge,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
|
@ -426,7 +531,7 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
|
||||
#[inline]
|
||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue(specified::LengthOrPercentage::Length(NoCalcLength::medium()))
|
||||
SpecifiedValue::Keyword(Medium)
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
|
@ -434,45 +539,61 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match self.0 {
|
||||
LengthOrPercentage::Length(NoCalcLength::FontRelative(value)) => {
|
||||
use values::specified::length::FontRelativeLength;
|
||||
match *self {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::FontRelative(value))) => {
|
||||
value.to_computed_value(context, /* use inherited */ true)
|
||||
}
|
||||
LengthOrPercentage::Length(NoCalcLength::ServoCharacterWidth(value)) => {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::ServoCharacterWidth(value))) => {
|
||||
value.to_computed_value(context.inherited_style().get_font().clone_font_size())
|
||||
}
|
||||
LengthOrPercentage::Length(ref l) => {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => {
|
||||
l.to_computed_value(context)
|
||||
}
|
||||
LengthOrPercentage::Percentage(Percentage(value)) => {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Percentage(Percentage(value))) => {
|
||||
context.inherited_style().get_font().clone_font_size().scale_by(value)
|
||||
}
|
||||
LengthOrPercentage::Calc(ref calc) => {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => {
|
||||
let calc = calc.to_computed_value(context);
|
||||
calc.length() + context.inherited_style().get_font().clone_font_size()
|
||||
.scale_by(calc.percentage())
|
||||
}
|
||||
SpecifiedValue::Keyword(ref key) => {
|
||||
key.to_computed_value(context)
|
||||
}
|
||||
SpecifiedValue::Smaller => {
|
||||
FontRelativeLength::Em(0.85).to_computed_value(context,
|
||||
/* use_inherited */ true)
|
||||
}
|
||||
SpecifiedValue::Larger => {
|
||||
FontRelativeLength::Em(1.2).to_computed_value(context,
|
||||
/* use_inherited */ true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
SpecifiedValue(LengthOrPercentage::Length(
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
ToComputedValue::from_computed_value(computed)
|
||||
))
|
||||
}
|
||||
}
|
||||
/// <length> | <percentage> | <absolute-size> | <relative-size>
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
use values::specified::{Length, LengthOrPercentage};
|
||||
|
||||
input.try(specified::LengthOrPercentage::parse_non_negative)
|
||||
.or_else(|()| {
|
||||
let ident = try!(input.expect_ident());
|
||||
NoCalcLength::from_str(&ident as &str)
|
||||
.ok_or(())
|
||||
.map(specified::LengthOrPercentage::Length)
|
||||
}).map(SpecifiedValue)
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
if let Ok(lop) = input.try(specified::LengthOrPercentage::parse_non_negative) {
|
||||
Ok(SpecifiedValue::Length(lop))
|
||||
} else if let Ok(kw) = input.try(KeywordSize::parse) {
|
||||
Ok(SpecifiedValue::Keyword(kw))
|
||||
} else {
|
||||
match_ignore_ascii_case! {&*input.expect_ident()?,
|
||||
"smaller" => Ok(SpecifiedValue::Smaller),
|
||||
"larger" => Ok(SpecifiedValue::Larger),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
|
|
|
@ -1175,7 +1175,9 @@ impl PropertyDeclaration {
|
|||
pub fn value_is_unparsed(&self) -> bool {
|
||||
match *self {
|
||||
PropertyDeclaration::WithVariables(..) => true,
|
||||
PropertyDeclaration::Custom(..) => true,
|
||||
PropertyDeclaration::Custom(_, ref value) => {
|
||||
!matches!(value.borrow(), DeclaredValue::CSSWideKeyword(..))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,38 +276,6 @@ impl Mul<CSSFloat> for NoCalcLength {
|
|||
}
|
||||
|
||||
impl NoCalcLength {
|
||||
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
pub fn from_str(s: &str) -> Option<NoCalcLength> {
|
||||
Some(match_ignore_ascii_case! { s,
|
||||
"xx-small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
|
||||
"x-small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 4),
|
||||
"small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 8 / 9),
|
||||
"medium" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX)),
|
||||
"large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 6 / 5),
|
||||
"x-large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 2),
|
||||
"xx-large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 2),
|
||||
|
||||
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
||||
"smaller" => NoCalcLength::FontRelative(FontRelativeLength::Em(0.85)),
|
||||
"larger" => NoCalcLength::FontRelative(FontRelativeLength::Em(1.2)),
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
pub fn from_font_size_int(i: u8) -> Self {
|
||||
let au = match i {
|
||||
0 | 1 => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
|
||||
2 => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
|
||||
3 => Au::from_px(FONT_MEDIUM_PX),
|
||||
4 => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
|
||||
5 => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
|
||||
6 => Au::from_px(FONT_MEDIUM_PX) * 2,
|
||||
_ => Au::from_px(FONT_MEDIUM_PX) * 3,
|
||||
};
|
||||
NoCalcLength::Absolute(au)
|
||||
}
|
||||
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
|
@ -444,21 +412,11 @@ impl Length {
|
|||
Length::NoCalc(NoCalcLength::zero())
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
pub fn from_str(s: &str) -> Option<Length> {
|
||||
NoCalcLength::from_str(s).map(Length::NoCalc)
|
||||
}
|
||||
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||
NoCalcLength::parse_dimension(value, unit).map(Length::NoCalc)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
pub fn from_font_size_int(i: u8) -> Self {
|
||||
Length::NoCalc(NoCalcLength::from_font_size_int(i))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Length, ()> {
|
||||
match try!(input.next()) {
|
||||
|
|
|
@ -1111,7 +1111,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(declarations:
|
|||
value: i32) {
|
||||
use style::properties::{PropertyDeclaration, LonghandId};
|
||||
use style::properties::longhands;
|
||||
use style::values::specified::{BorderStyle, NoCalcLength};
|
||||
use style::values::specified::BorderStyle;
|
||||
|
||||
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
||||
let long = get_longhand_from_id!(property);
|
||||
|
@ -1127,7 +1127,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(declarations:
|
|||
Clear => longhands::clear::SpecifiedValue::from_gecko_keyword(value),
|
||||
FontSize => {
|
||||
// We rely on Gecko passing in font-size values (0...7) here.
|
||||
longhands::font_size::SpecifiedValue(NoCalcLength::from_font_size_int(value as u8).into())
|
||||
longhands::font_size::SpecifiedValue::from_html_size(value as u8)
|
||||
},
|
||||
ListStyleType => longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value),
|
||||
WhiteSpace => longhands::white_space::SpecifiedValue::from_gecko_keyword(value),
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# except according to those terms.
|
||||
|
||||
import os
|
||||
import site
|
||||
import sys
|
||||
|
||||
from servo_tidy.tidy import LintRunner, filter_file
|
||||
|
||||
|
@ -28,11 +28,13 @@ class Lint(LintRunner):
|
|||
def run(self):
|
||||
if self.stylo:
|
||||
return
|
||||
|
||||
wpt_working_dir = os.path.abspath(os.path.join(WPT_PATH, "web-platform-tests"))
|
||||
for suite in SUITES:
|
||||
files = self._get_wpt_files(suite)
|
||||
site.addsitedir(wpt_working_dir)
|
||||
sys.path.insert(0, wpt_working_dir)
|
||||
from tools.lint import lint
|
||||
sys.path.remove(wpt_working_dir)
|
||||
file_dir = os.path.abspath(os.path.join(WPT_PATH, suite))
|
||||
returncode = lint.lint(file_dir, files, output_json=False, css_mode=False)
|
||||
if returncode:
|
||||
|
|
|
@ -111,11 +111,11 @@ def progress_wrapper(iterator):
|
|||
|
||||
|
||||
class FileList(object):
|
||||
def __init__(self, directory, only_changed_files=False, exclude_dirs=[], progress=True, stylo=False):
|
||||
def __init__(self, directory, only_changed_files=False, exclude_dirs=[], progress=True):
|
||||
self.directory = directory
|
||||
self.excluded = exclude_dirs
|
||||
iterator = self._filter_excluded() if exclude_dirs else self._default_walk()
|
||||
if only_changed_files and not stylo:
|
||||
if only_changed_files:
|
||||
try:
|
||||
# Fall back if git doesn't work
|
||||
newiter = self._git_changed_files()
|
||||
|
@ -168,10 +168,9 @@ def filter_file(file_name):
|
|||
return True
|
||||
|
||||
|
||||
def filter_files(start_dir, only_changed_files, progress, stylo):
|
||||
def filter_files(start_dir, only_changed_files, progress):
|
||||
file_iter = FileList(start_dir, only_changed_files=only_changed_files,
|
||||
exclude_dirs=config["ignore"]["directories"], progress=progress,
|
||||
stylo=stylo)
|
||||
exclude_dirs=config["ignore"]["directories"], progress=progress)
|
||||
for file_name in file_iter:
|
||||
base_name = os.path.basename(file_name)
|
||||
if not any(fnmatch.fnmatch(base_name, pattern) for pattern in FILE_PATTERNS_TO_CHECK):
|
||||
|
@ -1018,20 +1017,22 @@ class LintRunner(object):
|
|||
dir_name, filename = os.path.split(self.path)
|
||||
sys.path.append(dir_name)
|
||||
module = imp.load_source(filename[:-3], self.path)
|
||||
if hasattr(module, 'Lint'):
|
||||
if issubclass(module.Lint, LintRunner):
|
||||
lint = module.Lint(self.path, self.only_changed_files,
|
||||
self.exclude_dirs, self.progress, stylo=self.stylo)
|
||||
for error in lint.run():
|
||||
if not hasattr(error, '__iter__'):
|
||||
yield (self.path, 1, "errors should be a tuple of (path, line, reason)")
|
||||
return
|
||||
yield error
|
||||
else:
|
||||
yield (self.path, 1, "class 'Lint' should inherit from 'LintRunner'")
|
||||
else:
|
||||
yield (self.path, 1, "script should contain a class named 'Lint'")
|
||||
sys.path.remove(dir_name)
|
||||
if not hasattr(module, 'Lint'):
|
||||
yield (self.path, 1, "script should contain a class named 'Lint'")
|
||||
return
|
||||
|
||||
if not issubclass(module.Lint, LintRunner):
|
||||
yield (self.path, 1, "class 'Lint' should inherit from 'LintRunner'")
|
||||
return
|
||||
|
||||
lint = module.Lint(self.path, self.only_changed_files,
|
||||
self.exclude_dirs, self.progress, stylo=self.stylo)
|
||||
for error in lint.run():
|
||||
if type(error) is not tuple or (type(error) is tuple and len(error) != 3):
|
||||
yield (self.path, 1, "errors should be a tuple of (path, line, reason)")
|
||||
return
|
||||
yield error
|
||||
|
||||
def get_files(self, path, **kwargs):
|
||||
args = ['only_changed_files', 'exclude_dirs', 'progress']
|
||||
|
@ -1071,7 +1072,7 @@ def scan(only_changed_files=False, progress=True, stylo=False):
|
|||
# check directories contain expected files
|
||||
directory_errors = check_directory_files(config['check_ext'])
|
||||
# standard checks
|
||||
files_to_check = filter_files('.', only_changed_files, progress, stylo)
|
||||
files_to_check = filter_files('.', only_changed_files and not stylo, progress)
|
||||
checking_functions = (check_flake8, check_lock, check_webidl_spec, check_json, check_yaml)
|
||||
line_checking_functions = (check_license, check_by_line, check_toml, check_shell,
|
||||
check_rust, check_spec, check_modeline)
|
||||
|
|
|
@ -1130,4 +1130,25 @@ mod shorthand_serialization {
|
|||
assert_eq!(serialization, block_text);
|
||||
}
|
||||
}
|
||||
|
||||
mod keywords {
|
||||
pub use super::*;
|
||||
#[test]
|
||||
fn css_wide_keywords_should_be_parsed() {
|
||||
let block_text = "--a:inherit;";
|
||||
let block = parse_declaration_block(block_text);
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
assert_eq!(serialization, "--a: inherit;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_keyword_custom_property_should_be_unparsed() {
|
||||
let block_text = "--main-color: #06c;";
|
||||
let block = parse_declaration_block(block_text);
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
assert_eq!(serialization, block_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,6 +264,23 @@ class MarionetteProtocol(Protocol):
|
|||
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
|
||||
self.marionette.execute_script(script)
|
||||
|
||||
def clear_origin(self, url):
|
||||
self.logger.info("Clearing origin %s" % (url))
|
||||
script = """
|
||||
let url = '%s';
|
||||
let uri = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService)
|
||||
.newURI(url);
|
||||
let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
let principal = ssm.createCodebasePrincipal(uri, {});
|
||||
let qms = Components.classes["@mozilla.org/dom/quota-manager-service;1"]
|
||||
.getService(Components.interfaces.nsIQuotaManagerService);
|
||||
qms.clearStoragesForPrincipal(principal, "default", true);
|
||||
""" % url
|
||||
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
|
||||
self.marionette.execute_script(script)
|
||||
|
||||
|
||||
class RemoteMarionetteProtocol(Protocol):
|
||||
def __init__(self, executor, browser):
|
||||
|
@ -325,6 +342,11 @@ class ExecuteAsyncScriptRun(object):
|
|||
self.result_flag = threading.Event()
|
||||
|
||||
def run(self):
|
||||
index = self.url.rfind("/storage/");
|
||||
if index != -1:
|
||||
# Clear storage
|
||||
self.protocol.clear_origin(self.url)
|
||||
|
||||
timeout = self.timeout
|
||||
|
||||
try:
|
||||
|
|
|
@ -24,7 +24,7 @@ add_task(function* test_default_behavior_host() {
|
|||
yield addBookmark( { uri: uri4, title: "tpbk" } );
|
||||
yield addBookmark( { uri: uri5, title: "title", tags: ["foo"] } );
|
||||
|
||||
yield setFaviconForHref(uri1.spec, "chrome://global/skin/icons/information-16.png");
|
||||
yield setFaviconForHref(uri1.spec, "chrome://global/skin/icons/info.svg");
|
||||
yield setFaviconForHref(uri3.spec, "chrome://global/skin/icons/error-16.png");
|
||||
yield setFaviconForHref(uri6.spec, "chrome://global/skin/icons/question-16.png");
|
||||
|
||||
|
@ -45,7 +45,7 @@ add_task(function* test_default_behavior_host() {
|
|||
yield check_autocomplete({
|
||||
search: "ty",
|
||||
matches: [ { uri: uri1, title: "typed", style: [ "autofill", "heuristic" ],
|
||||
icon: "chrome://global/skin/icons/information-16.png" } ],
|
||||
icon: "chrome://global/skin/icons/info.svg" } ],
|
||||
autofilled: "typed/",
|
||||
completed: "typed/"
|
||||
});
|
||||
|
@ -116,7 +116,7 @@ add_task(function* test_default_behavior_host() {
|
|||
yield check_autocomplete({
|
||||
search: "ty",
|
||||
matches: [ { uri: uri1, title: "typed", style: [ "autofill", "heuristic" ],
|
||||
icon: "chrome://global/skin/icons/information-16.png"} ],
|
||||
icon: "chrome://global/skin/icons/info.svg"} ],
|
||||
autofilled: "typed/",
|
||||
completed: "typed/"
|
||||
});
|
||||
|
@ -223,7 +223,7 @@ add_task(function* test_default_behavior_url() {
|
|||
yield addBookmark( { uri: uri3, title: "bookmarked" } );
|
||||
yield addBookmark( { uri: uri4, title: "tpbk" } );
|
||||
|
||||
yield setFaviconForHref(uri1.spec, "chrome://global/skin/icons/information-16.png");
|
||||
yield setFaviconForHref(uri1.spec, "chrome://global/skin/icons/info.svg");
|
||||
yield setFaviconForHref(uri3.spec, "chrome://global/skin/icons/error-16.png");
|
||||
|
||||
// RESTRICT TO HISTORY.
|
||||
|
@ -245,7 +245,7 @@ add_task(function* test_default_behavior_url() {
|
|||
yield check_autocomplete({
|
||||
search: "typed/t",
|
||||
matches: [ { uri: uri1, title: "typed/ty/", style: [ "autofill", "heuristic" ],
|
||||
icon: "chrome://global/skin/icons/information-16.png"} ],
|
||||
icon: "chrome://global/skin/icons/info.svg"} ],
|
||||
autofilled: "typed/ty/",
|
||||
completed: "http://typed/ty/"
|
||||
});
|
||||
|
|
|
@ -176,7 +176,7 @@ add_task(function* test_import_chromefavicon() {
|
|||
// 9. empty bookmarks db and continue
|
||||
|
||||
const PAGE_URI = NetUtil.newURI("http://example.com/chromefavicon_page");
|
||||
const CHROME_FAVICON_URI = NetUtil.newURI("chrome://global/skin/icons/information-16.png");
|
||||
const CHROME_FAVICON_URI = NetUtil.newURI("chrome://global/skin/icons/info.svg");
|
||||
const CHROME_FAVICON_URI_2 = NetUtil.newURI("chrome://global/skin/icons/error-16.png");
|
||||
|
||||
do_print("Importing from html");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[flake8]
|
||||
# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
|
||||
ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E128, E501, E202, W602, E127, W601
|
||||
ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E501, E202, W602, E127, W601
|
||||
max-line-length = 99
|
||||
filename = *.py, +.lint
|
||||
|
|
|
@ -10462,11 +10462,11 @@
|
|||
},
|
||||
"DOM_SCRIPT_SRC_ENCODING": {
|
||||
"alert_emails": ["dteller@mozilla.com"],
|
||||
"expires_in_version": "never",
|
||||
"expires_in_version": "61",
|
||||
"kind": "count",
|
||||
"keyed": true,
|
||||
"bug_numbers": [1344152],
|
||||
"description": "Encoding used in a <script src>."
|
||||
"description": "Note the encoding (e.g. 'UTF-8', 'windows-1252', 'ASCII') of each external <script> element that is successfully loaded and decoded."
|
||||
},
|
||||
"VIDEO_FASTSEEK_USED": {
|
||||
"alert_emails": ["lchristie@mozilla.com", "cpearce@mozilla.com"],
|
||||
|
|
|
@ -21,16 +21,16 @@ def print_array_entry(output, histogram, name_index, exp_index, label_index, lab
|
|||
if cpp_guard:
|
||||
print("#if defined(%s)" % cpp_guard, file=output)
|
||||
print(" { %s, %s, %s, %s, %d, %d, %s, %d, %d, %s },"
|
||||
% (histogram.low(),
|
||||
histogram.high(),
|
||||
histogram.n_buckets(),
|
||||
histogram.nsITelemetry_kind(),
|
||||
name_index,
|
||||
exp_index,
|
||||
histogram.dataset(),
|
||||
label_index,
|
||||
label_count,
|
||||
"true" if histogram.keyed() else "false"), file=output)
|
||||
% (histogram.low(),
|
||||
histogram.high(),
|
||||
histogram.n_buckets(),
|
||||
histogram.nsITelemetry_kind(),
|
||||
name_index,
|
||||
exp_index,
|
||||
histogram.dataset(),
|
||||
label_index,
|
||||
label_count,
|
||||
"true" if histogram.keyed() else "false"), file=output)
|
||||
if cpp_guard:
|
||||
print("#endif", file=output)
|
||||
|
||||
|
|
|
@ -371,14 +371,14 @@ associated with the histogram. Returns None if no guarding is necessary."""
|
|||
continue
|
||||
if not isinstance(definition[key], key_type):
|
||||
raise ValueError, ('value for key "{0}" in Histogram "{1}" '
|
||||
'should be {2}').format(key, name, nice_type_name(key_type))
|
||||
'should be {2}').format(key, name, nice_type_name(key_type))
|
||||
|
||||
for key, key_type in type_checked_list_fields.iteritems():
|
||||
if key not in definition:
|
||||
continue
|
||||
if not all(isinstance(x, key_type) for x in definition[key]):
|
||||
raise ValueError, ('all values for list "{0}" in Histogram "{1}" '
|
||||
'should be {2}').format(key, name, nice_type_name(key_type))
|
||||
'should be {2}').format(key, name, nice_type_name(key_type))
|
||||
|
||||
@staticmethod
|
||||
def check_keys(name, definition, allowed_keys):
|
||||
|
@ -393,8 +393,8 @@ associated with the histogram. Returns None if no guarding is necessary."""
|
|||
if whitelists is not None and self._n_buckets > 100 and type(self._n_buckets) is int:
|
||||
if self._name not in whitelists['n_buckets']:
|
||||
raise KeyError, ('New histogram "%s" is not permitted to have more than 100 buckets. '
|
||||
'Histograms with large numbers of buckets use disproportionately high amounts of resources. '
|
||||
'Contact the Telemetry team (e.g. in #telemetry) if you think an exception ought to be made.' % self._name)
|
||||
'Histograms with large numbers of buckets use disproportionately high amounts of resources. '
|
||||
'Contact the Telemetry team (e.g. in #telemetry) if you think an exception ought to be made.' % self._name)
|
||||
|
||||
@staticmethod
|
||||
def boolean_flag_bucket_parameters(definition):
|
||||
|
|
|
@ -49,7 +49,7 @@ class ScalarType:
|
|||
for n in [group_name, probe_name]:
|
||||
if len(n) > MAX_NAME_LENGTH:
|
||||
raise ValueError("Name '{}' exceeds maximum name length of {} characters."
|
||||
.format(n, MAX_NAME_LENGTH))
|
||||
.format(n, MAX_NAME_LENGTH))
|
||||
|
||||
def check_name(name, error_msg_prefix, allowed_char_regexp):
|
||||
# Check if we only have the allowed characters.
|
||||
|
@ -60,8 +60,8 @@ class ScalarType:
|
|||
# Don't allow leading/trailing digits, '.' or '_'.
|
||||
if re.search(r'(^[\d\._])|([\d\._])$', name):
|
||||
raise ValueError(error_msg_prefix +
|
||||
" name must not have a leading/trailing digit, a dot or underscore. Got: '{}'"
|
||||
.format(name))
|
||||
" name must not have a leading/trailing digit, a dot or underscore. Got: '{}'"
|
||||
.format(name))
|
||||
|
||||
check_name(group_name, 'Group', r'\.')
|
||||
check_name(probe_name, 'Probe', r'_')
|
||||
|
@ -115,7 +115,7 @@ class ScalarType:
|
|||
|
||||
# Checks the type for all the fields.
|
||||
wrong_type_names = ['{} must be {}'.format(f, ALL_FIELDS[f].__name__)
|
||||
for f in definition.keys() if not isinstance(definition[f], ALL_FIELDS[f])]
|
||||
for f in definition.keys() if not isinstance(definition[f], ALL_FIELDS[f])]
|
||||
if len(wrong_type_names) > 0:
|
||||
raise TypeError(self._name + ' - ' + ', '.join(wrong_type_names))
|
||||
|
||||
|
@ -237,7 +237,7 @@ class ScalarType:
|
|||
release_channel_collection = \
|
||||
self._definition.get('release_channel_collection', 'opt-in')
|
||||
return 'nsITelemetry::' + ('DATASET_RELEASE_CHANNEL_OPTOUT'
|
||||
if release_channel_collection == 'opt-out' else 'DATASET_RELEASE_CHANNEL_OPTIN')
|
||||
if release_channel_collection == 'opt-out' else 'DATASET_RELEASE_CHANNEL_OPTIN')
|
||||
|
||||
@property
|
||||
def cpp_guard(self):
|
||||
|
|
|
@ -155,7 +155,9 @@ this.SafeBrowsing = {
|
|||
throw err;
|
||||
}
|
||||
|
||||
if (!info.list || !info.uri) {
|
||||
// The "Phish" reports are about submitting new phishing URLs to Google so
|
||||
// they don't have an associated list URL
|
||||
if (kind != "Phish" && (!info.list || !info.uri)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
const host_track = "http://trackertest.org/";
|
||||
const path_ping = "tests/toolkit/components/url-classifier/tests/mochitest/ping.sjs";
|
||||
const TP_ENABLE_PREF = "privacy.trackingprotection.enabled";
|
||||
const RETRY_TIMEOUT_MS = 200;
|
||||
|
||||
var testData = [
|
||||
{ url: "trackertest.org/",
|
||||
|
@ -37,9 +38,8 @@
|
|||
ping(id, host_nottrack);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
isPinged(id, expectPing, msg, resolve);
|
||||
}, timeout);
|
||||
// Retry at most 30 seconds.
|
||||
isPingedWithRetry(id, expectPing, msg, resolve, 30 * 1000 / RETRY_TIMEOUT_MS);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -85,19 +85,30 @@
|
|||
document.body.removeChild(elm);
|
||||
}
|
||||
|
||||
function isPinged(id, expected, msg, callback) {
|
||||
function isPingedWithRetry(id, expected, msg, callback, retryCnt) {
|
||||
var url = "http://mochi.test:8888/" + path_ping;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url + "?id=" + id);
|
||||
xhr.onload = function() {
|
||||
var isPinged = xhr.response === "ping";
|
||||
is(expected, isPinged, msg);
|
||||
|
||||
callback();
|
||||
let success = isPinged === expected;
|
||||
if (success || 0 === retryCnt) {
|
||||
is(expected, isPinged, msg);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
// Retry on failure.
|
||||
setTimeout(() => {
|
||||
isPingedWithRetry(id, expected, msg, callback, retryCnt - 1);
|
||||
}, RETRY_TIMEOUT_MS);
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function isPinged(id, expected, msg, callback) {
|
||||
isPingedWithRetry(id, expected, msg, callback, 0);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
SpecialPowers.clearUserPref(TP_ENABLE_PREF);
|
||||
}
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
#include "linux/crash_generation/crash_generation_server.h"
|
||||
#include "linux/crash_generation/client_info.h"
|
||||
#include "linux/handler/exception_handler.h"
|
||||
#include "linux/handler/guid_generator.h"
|
||||
#include "linux/minidump_writer/minidump_writer.h"
|
||||
#include "common/linux/eintr_wrapper.h"
|
||||
#include "common/linux/guid_creator.h"
|
||||
#include "common/linux/safe_readlink.h"
|
||||
|
||||
static const char kCommandQuit = 'x';
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "linux/handler/guid_generator.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//
|
||||
// GUIDGenerator
|
||||
//
|
||||
// This class is used to generate random GUID.
|
||||
// Currently use random number to generate a GUID since Linux has
|
||||
// no native GUID generator. This should be OK since we don't expect
|
||||
// crash to happen very offen.
|
||||
//
|
||||
class GUIDGenerator {
|
||||
public:
|
||||
static uint16_t BytesToUInt16(const uint8_t bytes[]) {
|
||||
return ((uint16_t) bytes[1] << 8) | ((uint16_t) bytes[0]);
|
||||
}
|
||||
|
||||
// The last field in a GUID is 48 bits long so we're converting only 6 bytes
|
||||
static uint64_t BytesToUInt48(const uint8_t bytes[]) {
|
||||
return ((uint64_t) bytes[0] << 40) | ((uint64_t) bytes[1] << 32) |
|
||||
((uint64_t) bytes[2] << 24) | ((uint64_t) bytes[3] << 16) |
|
||||
((uint64_t) bytes[4] << 8) | (uint64_t) bytes[5];
|
||||
}
|
||||
|
||||
static void UInt32ToBytes(uint8_t bytes[], uint32_t n) {
|
||||
bytes[0] = n & 0xff;
|
||||
bytes[1] = (n >> 8) & 0xff;
|
||||
bytes[2] = (n >> 16) & 0xff;
|
||||
bytes[3] = (n >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static bool CreateGUID(GUID *guid) {
|
||||
InitOnce();
|
||||
guid->data1 = random();
|
||||
guid->data2 = (uint16_t)(random());
|
||||
guid->data3 = (uint16_t)(random());
|
||||
UInt32ToBytes(&guid->data4[0], random());
|
||||
UInt32ToBytes(&guid->data4[4], random());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static void InitOnce() {
|
||||
pthread_once(&once_control, &InitOnceImpl);
|
||||
}
|
||||
|
||||
static void InitOnceImpl() {
|
||||
srandom(time(NULL));
|
||||
}
|
||||
|
||||
static pthread_once_t once_control;
|
||||
};
|
||||
|
||||
pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
bool CreateGUID(GUID *guid) {
|
||||
return GUIDGenerator::CreateGUID(guid);
|
||||
}
|
||||
|
||||
// Parse guid to string.
|
||||
bool GUIDToString(const GUID *guid, char *buf, size_t buf_len) {
|
||||
// Should allow more space the the max length of GUID.
|
||||
assert(buf_len > kGUIDStringLength);
|
||||
int num = snprintf(buf, buf_len, kGUIDFormatString,
|
||||
guid->data1, guid->data2, guid->data3,
|
||||
GUIDGenerator::BytesToUInt16(&(guid->data4[0])),
|
||||
GUIDGenerator::BytesToUInt48(&(guid->data4[2])));
|
||||
if (num != kGUIDStringLength)
|
||||
return false;
|
||||
|
||||
buf[num] = '\0';
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef LINUX_HANDLER_GUID_GENERATOR_H__
|
||||
#define LINUX_HANDLER_GUID_GENERATOR_H__
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
typedef MDGUID GUID;
|
||||
|
||||
// Format string for parsing GUID.
|
||||
const char kGUIDFormatString[] = "%08x-%04x-%04x-%04x-%012" PRIx64;
|
||||
// Length of GUID string. Don't count the ending '\0'.
|
||||
const size_t kGUIDStringLength = 36;
|
||||
|
||||
// Create a guid.
|
||||
bool CreateGUID(GUID *guid);
|
||||
|
||||
// Get the string from guid.
|
||||
bool GUIDToString(const GUID *guid, char *buf, size_t buf_len);
|
||||
|
||||
#endif
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче