Merge inbound to m-c a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2014-10-22 18:46:27 -07:00
Родитель b89b2707cd a1e41d89c8
Коммит a41244e4fd
34 изменённых файлов: 577 добавлений и 366 удалений

Просмотреть файл

@ -1277,7 +1277,6 @@ pref("services.sync.prefs.sync.privacy.clearOnShutdown.passwords", true);
pref("services.sync.prefs.sync.privacy.clearOnShutdown.sessions", true);
pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true);
pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
pref("services.sync.prefs.sync.privacy.donottrackheader.value", true);
pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
pref("services.sync.prefs.sync.security.OCSP.enabled", true);

Просмотреть файл

@ -1369,7 +1369,7 @@ BrowserGlue.prototype = {
},
_migrateUI: function BG__migrateUI() {
const UI_VERSION = 24;
const UI_VERSION = 25;
const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
let currentUIVersion = 0;
try {
@ -1617,6 +1617,20 @@ BrowserGlue.prototype = {
}
}
if (currentUIVersion < 25) {
// Make sure the doNotTrack value conforms to the conversion from
// three-state to two-state. (This reverts a setting of "please track me"
// to the default "don't say anything").
try {
if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled") &&
Services.prefs.getIntPref("privacy.donottrackheader.value") != 1) {
Services.prefs.clearUserPref("privacy.donottrackheader.enabled");
Services.prefs.clearUserPref("privacy.donottrackheader.value");
}
}
catch (ex) {}
}
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
},

Просмотреть файл

@ -162,43 +162,6 @@ var gPrivacyPane = {
document.getElementById("historyPane").selectedIndex = selectedIndex;
},
/**
* Update the Tracking preferences based on controls.
*/
setTrackingPrefs: function PPP_setTrackingPrefs()
{
let dntRadioGroup = document.getElementById("doNotTrackSelection"),
dntValuePref = document.getElementById("privacy.donottrackheader.value"),
dntEnabledPref = document.getElementById("privacy.donottrackheader.enabled");
// if the selected radio button says "no preference", set on/off pref to
// false and don't change the value pref.
if (dntRadioGroup.selectedItem.value == -1) {
dntEnabledPref.value = false;
return dntValuePref.value;
}
dntEnabledPref.value = true;
return dntRadioGroup.selectedItem.value;
},
/**
* Obtain the tracking preference value and reflect it in the UI.
*/
getTrackingPrefs: function PPP_getTrackingPrefs()
{
// XXX avoid using bindings that might not be attached, see bug 859982
let dntValue = Services.prefs.getIntPref("privacy.donottrackheader.value"),
dntEnabled = Services.prefs.getBoolPref("privacy.donottrackheader.enabled");
// if DNT is enbaled, select the value from the selected radio
// button, otherwise choose the "no preference" radio button
if (dntEnabled)
return dntValue;
return document.getElementById("dntnopref").value;
},
/**
* Update the private browsing auto-start pref and the history mode
* micro-management prefs based on the history mode menulist

Просмотреть файл

@ -13,9 +13,6 @@
<preference id="privacy.donottrackheader.enabled"
name="privacy.donottrackheader.enabled"
type="bool"/>
<preference id="privacy.donottrackheader.value"
name="privacy.donottrackheader.value"
type="int"/>
<!-- XXX button prefs -->
<preference id="pref.privacy.disable_button.cookie_exceptions"
@ -74,21 +71,20 @@
<!-- Tracking -->
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" align="start">
<caption><label>&tracking.label;</label></caption>
<radiogroup id="doNotTrackSelection" orient="vertical" align="start"
preference="privacy.donottrackheader.value"
onsynctopreference="return gPrivacyPane.setTrackingPrefs()"
onsyncfrompreference="return gPrivacyPane.getTrackingPrefs()">
<radio id="dntnotrack" value="1" label="&dntTrackingNotOkay.label2;"
accesskey="&dntTrackingNotOkay.accesskey;" />
<radio id="dntdotrack" value="0" label="&dntTrackingOkay.label2;"
accesskey="&dntTrackingOkay.accesskey;" />
<radio id="dntnopref" value="-1" label="&dntTrackingNopref.label2;"
accesskey="&dntTrackingNopref.accesskey;" />
</radiogroup>
<label class="text-link" id="doNotTrackInfo"
href="https://www.mozilla.org/dnt">
&doNotTrackInfo.label;
</label>
<checkbox id="privacyDoNotTrackCheckbox"
label="&dntTrackingNotOkay.label2;"
accesskey="&dntTrackingNotOkay.accesskey;"
preference="privacy.donottrackheader.enabled"/>
<separator class="thin"/>
<vbox>
<hbox pack="end">
<spacer flex="1"/>
<label class="text-link" id="doNotTrackInfo"
href="https://www.mozilla.org/dnt">
&doNotTrackInfo.label;
</label>
</hbox>
</vbox>
</groupbox>
<!-- History -->

Просмотреть файл

@ -124,42 +124,6 @@ var gPrivacyPane = {
document.getElementById("historyPane").selectedIndex = selectedIndex;
},
/**
* Update the Tracking preferences based on controls.
*/
setTrackingPrefs: function PPP_setTrackingPrefs()
{
let dntRadioGroup = document.getElementById("doNotTrackSelection"),
dntValuePref = document.getElementById("privacy.donottrackheader.value"),
dntEnabledPref = document.getElementById("privacy.donottrackheader.enabled");
// if the selected radio button says "no preference", set on/off pref to
// false and don't change the value pref.
if (dntRadioGroup.selectedItem.value == -1) {
dntEnabledPref.value = false;
return dntValuePref.value;
}
dntEnabledPref.value = true;
return dntRadioGroup.selectedItem.value;
},
/**
* Obtain the tracking preference value and reflect it in the UI.
*/
getTrackingPrefs: function PPP_getTrackingPrefs()
{
let dntValuePref = document.getElementById("privacy.donottrackheader.value"),
dntEnabledPref = document.getElementById("privacy.donottrackheader.enabled");
// if DNT is enbaled, select the value from the selected radio
// button, otherwise choose the "no preference" radio button
if (dntEnabledPref.value)
return dntValuePref.value;
return document.getElementById("dntnopref").value;
},
/**
* Update the private browsing auto-start pref and the history mode
* micro-management prefs based on the history mode menulist

Просмотреть файл

@ -26,9 +26,6 @@
<preference id="privacy.donottrackheader.enabled"
name="privacy.donottrackheader.enabled"
type="bool"/>
<preference id="privacy.donottrackheader.value"
name="privacy.donottrackheader.value"
type="int"/>
<!-- XXX button prefs -->
<preference id="pref.privacy.disable_button.cookie_exceptions"
@ -84,20 +81,19 @@
<!-- Tracking -->
<groupbox id="trackingGroup" align="start">
<caption label="&tracking.label;"/>
<radiogroup id="doNotTrackSelection" orient="vertical"
preference="privacy.donottrackheader.value"
onsynctopreference="return gPrivacyPane.setTrackingPrefs()"
onsyncfrompreference="return gPrivacyPane.getTrackingPrefs()">
<radio id="dntnotrack" value="1" label="&dntTrackingNotOkay.label2;"
accesskey="&dntTrackingNotOkay.accesskey;" />
<radio id="dntdotrack" value="0" label="&dntTrackingOkay.label2;"
accesskey="&dntTrackingOkay.accesskey;" />
<radio id="dntnopref" value="-1" label="&dntTrackingNopref.label2;"
accesskey="&dntTrackingNopref.accesskey;" />
</radiogroup>
<label class="text-link" id="doNotTrackInfo"
href="https://www.mozilla.org/dnt"
value="&doNotTrackInfo.label;"/>
<checkbox id="privacyDoNotTrackCheckbox"
label="&dntTrackingNotOkay.label2;"
accesskey="&dntTrackingNotOkay.accesskey;"
preference="privacy.donottrackheader.enabled"/>
<separator class="thin"/>
<vbox>
<hbox pack="end">
<spacer flex="1"/>
<label class="text-link" id="doNotTrackInfo"
href="https://www.mozilla.org/dnt"
value="&doNotTrackInfo.label;"/>
</hbox>
</vbox>
</groupbox>

Просмотреть файл

@ -4,12 +4,8 @@
<!ENTITY tracking.label "Tracking">
<!ENTITY dntTrackingNopref.label2 "Do not tell sites anything about my tracking preferences">
<!ENTITY dntTrackingNopref.accesskey "o">
<!ENTITY dntTrackingNotOkay.label2 "Tell sites that I do not want to be tracked">
<!ENTITY dntTrackingNotOkay.accesskey "n">
<!ENTITY dntTrackingOkay.label2 "Tell sites that I want to be tracked">
<!ENTITY dntTrackingOkay.accesskey "h">
<!ENTITY trackingProtection.label "Prevent sites from tracking me">
<!ENTITY trackingProtection.accesskey "m">
<!ENTITY trackingProtectionLearnMore.label "Learn more">

Просмотреть файл

@ -137,8 +137,7 @@ let DirectoryLinksProvider = {
let enhanced = true;
try {
// Default to not enhanced if DNT is set to tell websites to not track
if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled") &&
Services.prefs.getIntPref("privacy.donottrackheader.value") == 1) {
if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled")) {
enhanced = false;
}
}

Просмотреть файл

@ -614,19 +614,14 @@ add_task(function test_DirectoryLinksProvider_setDefaultEnhanced() {
do_check_eq(Services.prefs.getBoolPref(kNewtabEnhancedPref), expected);
}
// Use the default donottrack prefs (enabled = false, value = 1)
// Use the default donottrack prefs (enabled = false)
Services.prefs.clearUserPref("privacy.donottrackheader.enabled");
Services.prefs.clearUserPref("privacy.donottrackheader.value");
checkDefault(true);
// Turn on DNT - no track
Services.prefs.setBoolPref("privacy.donottrackheader.enabled", true);
checkDefault(false);
// Set DNT - do track
Services.prefs.setIntPref("privacy.donottrackheader.value", 0);
checkDefault(true);
// Turn off DNT header
Services.prefs.clearUserPref("privacy.donottrackheader.enabled");
checkDefault(true);

Просмотреть файл

@ -822,13 +822,6 @@ nsCSPParser::directive()
return;
}
if (mCurDir.Length() < 2) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "failedToParseUnrecognizedSource",
params, ArrayLength(params));
return;
}
// Try to create a new CSPDirective
nsCSPDirective* cspDir = directiveName();
if (!cspDir) {
@ -840,13 +833,11 @@ nsCSPParser::directive()
nsTArray<nsCSPBaseSrc*> srcs;
directiveValue(srcs);
// If we can not parse any srcs; it's not worth having a directive; delete and return
// If we can not parse any srcs; we let the source expression be the empty set ('none')
// see, http://www.w3.org/TR/CSP11/#source-list-parsing
if (srcs.Length() == 0) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "failedToParseUnrecognizedSource",
params, ArrayLength(params));
delete cspDir;
return;
nsCSPKeywordSrc *keyword = new nsCSPKeywordSrc(CSP_NONE);
srcs.AppendElement(keyword);
}
// Add the newly created srcs to the directive and add the directive to the policy

Просмотреть файл

@ -438,9 +438,9 @@ nsresult TestSimplePolicies() {
return runTestSuite(policies, policyCount, 1);
}
// ============================= TestPoliciesThatLogWarning ========================
// ============================= TestPoliciesWithInvalidSrc ========================
nsresult TestPoliciesThatLogWarning() {
nsresult TestPoliciesWithInvalidSrc() {
static const PolicyTest policies[] =
{
@ -448,6 +448,50 @@ nsresult TestPoliciesThatLogWarning() {
"script-src http://www.selfuri.com" },
{ "script-src 'none' test.com; script-src example.com",
"script-src http://test.com" },
{ "default-src **",
"default-src 'none'" },
{ "default-src 'self",
"default-src 'none'" },
{ "default-src 'unsafe-inlin' ",
"default-src 'none'" },
{ "default-src */",
"default-src 'none'" },
{ "default-src",
"default-src 'none'" },
{ "default-src 'unsafe-inlin' ",
"default-src 'none'" },
{ "default-src :88",
"default-src 'none'" },
{ "script-src abc::::::88",
"script-src 'none'" },
{ "script-src *.*:*",
"script-src 'none'" },
{ "img-src *::88",
"img-src 'none'" },
{ "object-src http://localhost:",
"object-src 'none'" },
{ "script-src test..com",
"script-src 'none'" },
{ "script-src sub1.sub2.example+",
"script-src 'none'" },
{ "script-src http://www.example.com//",
"script-src 'none'" },
{ "script-src http://www.example.com:88path-1/",
"script-src 'none'" },
{ "script-src http://www.example.com:88//",
"script-src 'none'" },
{ "script-src http://www.example.com:88//path-1",
"script-src 'none'" },
{ "script-src http://www.example.com:88//path-1",
"script-src 'none'" },
{ "script-src http://www.example.com:88/.js",
"script-src 'none'" },
{ "script-src http://www.example.com:88.js",
"script-src 'none'" },
{ "script-src http://www.example.com:*.js",
"script-src 'none'" },
{ "script-src http://www.example.com:*.",
"script-src 'none'" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -460,34 +504,12 @@ nsresult TestBadPolicies() {
static const PolicyTest policies[] =
{
{ "default-src **", "" },
{ "default-src 'self", "" },
{ "script-sr 'self", "" },
{ "default-src 'unsafe-inlin' ", "" },
{ "default-src */", "" },
{ "default-src", "" },
{ "", "" },
{ "; ; ; ; ; ; ;", "" },
{ "defaut-src asdf", "" },
{ "default-src: aaa", "" },
{ "default-src 'unsafe-inlin' ", "" },
{ "default-src :88", "" },
{ "script-src abc::::::88", "" },
{ "asdf http://test.com", ""},
{ "script-src *.*:*", "" },
{ "img-src *::88", "" },
{ "object-src http://localhost:", "" },
{ "script-src test..com", "" },
{ "script-src sub1.sub2.example+", "" },
{ "script-src http://www.example.com//", "" },
{ "script-src http://www.example.com:88path-1/", "" },
{ "script-src http://www.example.com:88//", "" },
{ "script-src http://www.example.com:88//path-1", "" },
{ "script-src http://www.example.com:88//path-1", "" },
{ "script-src http://www.example.com:88/.js", "" },
{ "script-src http://www.example.com:88.js", "" },
{ "script-src http://www.example.com:*.js", "" },
{ "script-src http://www.example.com:*.", "" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -748,8 +770,6 @@ nsresult TestBadGeneratedPolicies() {
{ "http://other:pass1@self.com/foo", ""},
{ "http://user1:pass1@self.com/foo", ""},
{ "http://username:password@self.com/bar", ""},
{ "default-src ", ""},
{ "img-src ", ""}
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -884,17 +904,24 @@ nsresult TestBadGeneratedPoliciesForPathHandling() {
static const PolicyTest policies[] =
{
{ "img-src test1.example.com:88path-1/", "" },
{ "img-src test1.example.com:80.js", "" },
{ "img-src test1.example.com:*.js", "" },
{ "img-src test1.example.com:*.", "" },
{ "img-src http://test1.example.com//", "" },
{ "img-src http://test1.example.com:80//", "" },
{ "img-src http://test1.example.com:80abc", "" },
{ "img-src test1.example.com:88path-1/",
"img-src 'none'" },
{ "img-src test1.example.com:80.js",
"img-src 'none'" },
{ "img-src test1.example.com:*.js",
"img-src 'none'" },
{ "img-src test1.example.com:*.",
"img-src 'none'" },
{ "img-src http://test1.example.com//",
"img-src 'none'" },
{ "img-src http://test1.example.com:80//",
"img-src 'none'" },
{ "img-src http://test1.example.com:80abc",
"img-src 'none'" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
return runTestSuite(policies, policyCount, 0);
return runTestSuite(policies, policyCount, 1);
}
// ============================= TestFuzzyPolicies ========================
@ -1058,7 +1085,7 @@ int main(int argc, char** argv) {
if (NS_FAILED(TestIgnoreUpperLowerCasePolicies())) { return 1; }
if (NS_FAILED(TestIgnorePaths())) { return 1; }
if (NS_FAILED(TestSimplePolicies())) { return 1; }
if (NS_FAILED(TestPoliciesThatLogWarning())) { return 1; }
if (NS_FAILED(TestPoliciesWithInvalidSrc())) { return 1; }
if (NS_FAILED(TestBadPolicies())) { return 1; }
if (NS_FAILED(TestGoodGeneratedPolicies())) { return 1; }
if (NS_FAILED(TestBadGeneratedPolicies())) { return 1; }

Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1086612 - CSP: Let source expression be the empty set in case no valid source can be parsed</title>
</head>
<body>
<div id="testdiv">blocked</div>
<!-- Note, we reuse file_csp_path_matching.js which only updates the testdiv to 'allowed' if loaded !-->
<script src="http://test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js"></script>
</body>
</html>

Просмотреть файл

@ -36,6 +36,7 @@ support-files =
file_CSP_inlinestyle_main.html^headers^
file_CSP_inlinestyle_main_allowed.html
file_CSP_inlinestyle_main_allowed.html^headers^
file_csp_invalid_source_expression.html
file_CSP_main.html
file_CSP_main.html^headers^
file_CSP_main.js
@ -111,6 +112,7 @@ support-files =
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' # Times out, not sure why (bug 1008445)
[test_CSP_inlinescript.html]
[test_CSP_inlinestyle.html]
[test_csp_invalid_source_expression.html]
[test_bug836922_npolicies.html]
[test_bug886164.html]
[test_csp_redirects.html]

Просмотреть файл

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1086612 - CSP: Let source expression be the empty set in case no valid source can be parsed</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>
<p id="display"></p>
<div id="content" style="visibility: hidden">
<iframe style="width:100%;" id="testframe"></iframe>
</div>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
/* Description of the test:
* We try to parse a policy:
* script-src bankid:/*
* where the source expression (bankid:/*) is invalid. In that case the source-expression
* should be the empty set ('none'), see: http://www.w3.org/TR/CSP11/#source-list-parsing
* We confirm that the script is blocked by CSP.
*/
const policy = "script-src bankid:/*";
function runTest() {
var src = "file_csp_testserver.sjs";
// append the file that should be served
src += "?file=" + escape("tests/content/base/test/csp/file_csp_invalid_source_expression.html");
// append the CSP that should be used to serve the file
src += "&csp=" + escape(policy);
document.getElementById("testframe").addEventListener("load", test, false);
document.getElementById("testframe").src = src;
}
function test() {
try {
document.getElementById("testframe").removeEventListener('load', test, false);
var testframe = document.getElementById("testframe");
var divcontent = testframe.contentWindow.document.getElementById('testdiv').innerHTML;
is(divcontent, "blocked", "should be 'blocked'!");
}
catch (e) {
ok(false, "ERROR: could not access content!");
}
SimpleTest.finish();
}
runTest();
</script>
</body>
</html>

Просмотреть файл

@ -112,7 +112,6 @@ namespace mozilla {
namespace dom {
static bool sDoNotTrackEnabled = false;
static uint32_t sDoNotTrackValue = 1;
static bool sVibratorEnabled = false;
static uint32_t sMaxVibrateMS = 0;
static uint32_t sMaxVibrateListLen = 0;
@ -124,9 +123,6 @@ Navigator::Init()
Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
"privacy.donottrackheader.enabled",
false);
Preferences::AddUintVarCache(&sDoNotTrackValue,
"privacy.donottrackheader.value",
1);
Preferences::AddBoolVarCache(&sVibratorEnabled,
"dom.vibrator.enabled", true);
Preferences::AddUintVarCache(&sMaxVibrateMS,
@ -628,11 +624,7 @@ NS_IMETHODIMP
Navigator::GetDoNotTrack(nsAString &aResult)
{
if (sDoNotTrackEnabled) {
if (sDoNotTrackValue == 0) {
aResult.AssignLiteral("0");
} else {
aResult.AssignLiteral("1");
}
aResult.AssignLiteral("1");
} else {
aResult.AssignLiteral("unspecified");
}

Просмотреть файл

@ -14,7 +14,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=629535
<script type="application/javascript">
const dntPref = 'privacy.donottrackheader.enabled';
const dntValuePref = 'privacy.donottrackheader.value';
SimpleTest.waitForExplicitFinish();
@ -39,8 +38,6 @@ tests.push(function testDefaultValues() {
'DNT should be disabled by default');
is(navigator.doNotTrack, 'unspecified',
'navigator.doNotTrack should initially be "unspecified".');
is(SpecialPowers.getIntPref(dntValuePref), isB2G ? -1 : 1,
'DNT value should be "1" by default');
nextTest();
});
@ -59,34 +56,6 @@ tests.push(function setEnabled() {
});
});
tests.push(function clearedValue() {
SpecialPowers.pushPrefEnv({"clear": [[dntValuePref]]}, function() {
is(navigator.doNotTrack, "1", 'after clearing value pref');
nextTest();
});
});
tests.push(function setValue0() {
SpecialPowers.pushPrefEnv({"set": [[dntValuePref, 0]]}, function() {
is(navigator.doNotTrack, "0", 'after setting value pref');
nextTest();
});
});
tests.push(function setValue42() {
SpecialPowers.pushPrefEnv({"set": [[dntValuePref, 42]]}, function() {
is(navigator.doNotTrack, "1", 'after setting value pref');
nextTest();
});
});
tests.push(function clearValueAgain() {
SpecialPowers.pushPrefEnv({"clear": [[dntValuePref]]}, function() {
is(navigator.doNotTrack, "1", 'after clearing value pref');
nextTest();
});
});
tests.push(function setDisabled() {
SpecialPowers.pushPrefEnv({"set": [[dntPref, false]]}, function() {
is(navigator.doNotTrack, "unspecified", 'after setting pref to false');

Просмотреть файл

@ -66,6 +66,50 @@ LayerHasCheckerboardingAPZC(Layer* aLayer, gfxRGBA* aOutColor)
return false;
}
/**
* Returns a rectangle of content painted opaquely by aLayer. Very consertative;
* bails by returning an empty rect in any tricky situations.
*/
static nsIntRect
GetOpaqueRect(Layer* aLayer)
{
nsIntRect result;
gfx::Matrix matrix;
bool is2D = aLayer->AsLayerComposite()->GetShadowTransform().Is2D(&matrix);
// Just bail if there's anything difficult to handle.
if (!is2D || aLayer->GetMaskLayer() ||
aLayer->GetIsFixedPosition() ||
aLayer->GetIsStickyPosition() ||
aLayer->GetEffectiveOpacity() != 1.0f ||
matrix.HasNonIntegerTranslation()) {
return result;
}
if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) {
result = aLayer->GetEffectiveVisibleRegion().GetLargestRectangle();
} else {
// Drill down into RefLayers because that's what we particularly care about;
// layer construction for aLayer will not have known about the opaqueness
// of any RefLayer subtrees.
RefLayer* refLayer = aLayer->AsRefLayer();
if (refLayer && refLayer->GetFirstChild()) {
result = GetOpaqueRect(refLayer->GetFirstChild());
}
}
// Translate our opaque region to cover the child
gfx::Point point = matrix.GetTranslation();
result.MoveBy(static_cast<int>(point.x), static_cast<int>(point.y));
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
if (clipRect) {
result.IntersectRect(result, *clipRect);
}
return result;
}
static void DrawLayerInfo(const RenderTargetIntRect& aClipRect,
LayerManagerComposite* aManager,
Layer* aLayer)
@ -118,10 +162,12 @@ static void PrintUniformityInfo(Layer* aLayer)
/* all of the per-layer prepared data we need to maintain */
struct PreparedLayer
{
PreparedLayer(LayerComposite *aLayer, RenderTargetIntRect aClipRect) :
mLayer(aLayer), mClipRect(aClipRect) {}
PreparedLayer(LayerComposite *aLayer, RenderTargetIntRect aClipRect, bool aRestoreVisibleRegion, nsIntRegion &aVisibleRegion) :
mLayer(aLayer), mClipRect(aClipRect), mRestoreVisibleRegion(aRestoreVisibleRegion), mSavedVisibleRegion(aVisibleRegion) {}
LayerComposite* mLayer;
RenderTargetIntRect mClipRect;
bool mRestoreVisibleRegion;
nsIntRegion mSavedVisibleRegion;
};
/* all of the prepared data that we need in RenderLayer() */
@ -177,8 +223,38 @@ ContainerPrepare(ContainerT* aContainer,
CULLING_LOG("Preparing sublayer %p\n", layerToRender->GetLayer());
nsIntRegion savedVisibleRegion;
bool restoreVisibleRegion = false;
gfx::Matrix matrix;
bool is2D = layerToRender->GetLayer()->GetBaseTransform().Is2D(&matrix);
if (i + 1 < children.Length() &&
is2D && !matrix.HasNonIntegerTranslation()) {
LayerComposite* nextLayer = static_cast<LayerComposite*>(children.ElementAt(i + 1)->ImplData());
CULLING_LOG("Culling against %p\n", nextLayer->GetLayer());
nsIntRect nextLayerOpaqueRect;
if (nextLayer && nextLayer->GetLayer()) {
nextLayerOpaqueRect = GetOpaqueRect(nextLayer->GetLayer());
gfx::Point point = matrix.GetTranslation();
nextLayerOpaqueRect.MoveBy(static_cast<int>(-point.x), static_cast<int>(-point.y));
CULLING_LOG(" point %i, %i\n", static_cast<int>(-point.x), static_cast<int>(-point.y));
CULLING_LOG(" opaque rect %i, %i, %i, %i\n", nextLayerOpaqueRect.x, nextLayerOpaqueRect.y, nextLayerOpaqueRect.width, nextLayerOpaqueRect.height);
}
if (!nextLayerOpaqueRect.IsEmpty()) {
CULLING_LOG(" draw\n");
savedVisibleRegion = layerToRender->GetShadowVisibleRegion();
nsIntRegion visibleRegion;
visibleRegion.Sub(savedVisibleRegion, nextLayerOpaqueRect);
if (visibleRegion.IsEmpty()) {
continue;
}
layerToRender->SetShadowVisibleRegion(visibleRegion);
restoreVisibleRegion = true;
} else {
CULLING_LOG(" skip\n");
}
}
layerToRender->Prepare(clipRect);
aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender, clipRect));
aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender, clipRect, restoreVisibleRegion, savedVisibleRegion));
}
CULLING_LOG("Preparing container layer %p\n", aContainer->GetLayer());
@ -249,6 +325,11 @@ RenderLayers(ContainerT* aContainer,
layerToRender->RenderLayer(RenderTargetPixel::ToUntyped(clipRect));
}
if (preparedData.mRestoreVisibleRegion) {
// Restore the region in case it's not covered by opaque content next time
layerToRender->SetShadowVisibleRegion(preparedData.mSavedVisibleRegion);
}
if (gfxPrefs::UniformityInfo()) {
PrintUniformityInfo(layer);
}

Просмотреть файл

@ -197,55 +197,6 @@ LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget, const
mTargetBounds = aRect;
}
void
LayerManagerComposite::ApplyOcclusionCulling(Layer* aLayer, nsIntRegion& aOpaqueRegion)
{
nsIntRegion localOpaque;
Matrix transform2d;
bool isTranslation = false;
// If aLayer has a simple transform (only an integer translation) then we
// can easily convert aOpaqueRegion into pre-transform coordinates and include
// that region.
if (aLayer->GetLocalTransform().Is2D(&transform2d)) {
if (transform2d.IsIntegerTranslation()) {
isTranslation = true;
localOpaque = aOpaqueRegion;
localOpaque.MoveBy(-transform2d._31, -transform2d._32);
}
}
// Subtract any areas that we know to be opaque from our
// visible region.
LayerComposite *composite = aLayer->AsLayerComposite();
if (!localOpaque.IsEmpty()) {
nsIntRegion visible = composite->GetShadowVisibleRegion();
visible.Sub(visible, localOpaque);
composite->SetShadowVisibleRegion(visible);
}
// Compute occlusions for our descendants (in front-to-back order) and allow them to
// contribute to localOpaque.
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
ApplyOcclusionCulling(child, localOpaque);
}
// If we have a simple transform, then we can add our opaque area into
// aOpaqueRegion.
if (isTranslation &&
!aLayer->GetMaskLayer() &&
aLayer->GetLocalOpacity() == 1.0f) {
if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) {
localOpaque.Or(localOpaque, composite->GetShadowVisibleRegion());
}
localOpaque.MoveBy(transform2d._31, transform2d._32);
const nsIntRect* clip = aLayer->GetEffectiveClipRect();
if (clip) {
localOpaque.And(localOpaque, *clip);
}
aOpaqueRegion.Or(aOpaqueRegion, localOpaque);
}
}
bool
LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags)
{
@ -306,9 +257,6 @@ LayerManagerComposite::EndTransaction(DrawPaintedLayerCallback aCallback,
// so we don't need to pass any global transform here.
mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
nsIntRegion opaque;
ApplyOcclusionCulling(mRoot, opaque);
Render();
mGeometryChanged = false;
} else {

Просмотреть файл

@ -165,13 +165,6 @@ public:
virtual const char* Name() const MOZ_OVERRIDE { return ""; }
/**
* Restricts the shadow visible region of layers that are covered with
* opaque content. aOpaqueRegion is the region already known to be covered
* with opaque content, in the post-transform coordinate space of aLayer.
*/
void ApplyOcclusionCulling(Layer* aLayer, nsIntRegion& aOpaqueRegion);
/**
* RAII helper class to add a mask effect with the compositable from aMaskLayer
* to the EffectChain aEffect and notify the compositable when we are done.

Просмотреть файл

@ -792,26 +792,6 @@ CompositorParent::CompositeCallback(TimeStamp aScheduleTime)
CompositeToTarget(nullptr);
}
// Go down the composite layer tree, setting properties to match their
// content-side counterparts.
static void
SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
LayerComposite* layerComposite = aLayer->AsLayerComposite();
// Set the layerComposite's base transform to the layer's base transform.
layerComposite->SetShadowTransform(aLayer->GetBaseTransform());
layerComposite->SetShadowTransformSetByAnimation(false);
layerComposite->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
layerComposite->SetShadowClipRect(aLayer->GetClipRect());
layerComposite->SetShadowOpacity(aLayer->GetOpacity());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
SetShadowProperties(child);
}
}
void
CompositorParent::CompositeToTarget(DrawTarget* aTarget, const nsIntRect* aRect)
{
@ -837,7 +817,6 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const nsIntRect* aRect)
}
AutoResolveRefLayers resolve(mCompositionManager);
SetShadowProperties(mLayerManager->GetRoot());
if (aTarget) {
mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect);
@ -925,6 +904,26 @@ CompositorParent::CanComposite()
!mPaused;
}
// Go down the composite layer tree, setting properties to match their
// content-side counterparts.
static void
SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
LayerComposite* layerComposite = aLayer->AsLayerComposite();
// Set the layerComposite's base transform to the layer's base transform.
layerComposite->SetShadowTransform(aLayer->GetBaseTransform());
layerComposite->SetShadowTransformSetByAnimation(false);
layerComposite->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
layerComposite->SetShadowClipRect(aLayer->GetClipRect());
layerComposite->SetShadowOpacity(aLayer->GetOpacity());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
SetShadowProperties(child);
}
}
void
CompositorParent::ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
bool aIsFirstPaint)
@ -972,6 +971,9 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
MOZ_ASSERT(aTransactionId > mPendingTransaction);
mPendingTransaction = aTransactionId;
if (root) {
SetShadowProperties(root);
}
if (aScheduleComposite) {
ScheduleComposition();
if (mPaused) {
@ -989,7 +991,6 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
mCompositorVsyncObserver->NeedsComposite()));
if (needTestComposite) {
AutoResolveRefLayers resolve(mCompositionManager);
SetShadowProperties(mLayerManager->GetRoot());
bool requestNextFrame =
mCompositionManager->TransformShadowTree(mTestTime);
if (!requestNextFrame) {
@ -1026,7 +1027,6 @@ CompositorParent::SetTestSampleTime(LayerTransactionParent* aLayerTree,
// Update but only if we were already scheduled to animate
if (testComposite) {
AutoResolveRefLayers resolve(mCompositionManager);
SetShadowProperties(mLayerManager->GetRoot());
bool requestNextFrame = mCompositionManager->TransformShadowTree(aTime);
if (!requestNextFrame) {
CancelCurrentCompositeTask();
@ -1589,6 +1589,9 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
state->mParent->ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint);
Layer* shadowRoot = aLayerTree->GetRoot();
if (shadowRoot) {
SetShadowProperties(shadowRoot);
}
UpdateIndirectTree(id, shadowRoot, aTargetConfig);
state->mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite,

Просмотреть файл

@ -100,7 +100,7 @@ function ToLength(v) {
return 0;
// Math.pow(2, 53) - 1 = 0x1fffffffffffff
return v < 0x1fffffffffffff ? v : 0x1fffffffffffff;
return std_Math_min(v, 0x1fffffffffffff);
}
/********** Testing code **********/

Просмотреть файл

@ -5571,9 +5571,11 @@ CodeGenerator::visitIsNullOrLikeUndefined(LIsNullOrLikeUndefined *lir)
}
Register tag = masm.splitTagForTest(value);
masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined);
masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined);
MDefinition *input = lir->mir()->lhs();
if (input->mightBeType(MIRType_Null))
masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined);
if (input->mightBeType(MIRType_Undefined))
masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined);
if (ool) {
// Check whether it's a truthy object or a falsy object that emulates
@ -5652,8 +5654,11 @@ CodeGenerator::visitIsNullOrLikeUndefinedAndBranch(LIsNullOrLikeUndefinedAndBran
Label *ifTrueLabel = getJumpLabelForBranch(ifTrue);
Label *ifFalseLabel = getJumpLabelForBranch(ifFalse);
masm.branchTestNull(Assembler::Equal, tag, ifTrueLabel);
masm.branchTestUndefined(Assembler::Equal, tag, ifTrueLabel);
MDefinition *input = lir->cmpMir()->lhs();
if (input->mightBeType(MIRType_Null))
masm.branchTestNull(Assembler::Equal, tag, ifTrueLabel);
if (input->mightBeType(MIRType_Undefined))
masm.branchTestUndefined(Assembler::Equal, tag, ifTrueLabel);
if (ool) {
masm.branchTestObject(Assembler::NotEqual, tag, ifFalseLabel);

Просмотреть файл

@ -1147,31 +1147,64 @@ IonBuilder::inlineMathFRound(CallInfo &callInfo)
IonBuilder::InliningStatus
IonBuilder::inlineMathMinMax(CallInfo &callInfo, bool max)
{
if (callInfo.argc() < 2 || callInfo.constructing())
if (callInfo.argc() < 1 || callInfo.constructing())
return InliningStatus_NotInlined;
MIRType returnType = getInlineReturnType();
if (!IsNumberType(returnType))
return InliningStatus_NotInlined;
MDefinitionVector int32_cases(alloc());
for (unsigned i = 0; i < callInfo.argc(); i++) {
MIRType argType = callInfo.getArg(i)->type();
if (!IsNumberType(argType))
return InliningStatus_NotInlined;
MDefinition *arg = callInfo.getArg(i);
// When one of the arguments is double, do a double MMinMax.
if (returnType == MIRType_Int32 && IsFloatingPointType(argType))
switch (arg->type()) {
case MIRType_Int32:
if (!int32_cases.append(arg))
return InliningStatus_Error;
break;
case MIRType_Double:
case MIRType_Float32:
// Don't force a double MMinMax for arguments that would be a NOP
// when doing an integer MMinMax.
if (arg->isConstant()) {
double cte = arg->toConstant()->value().toDouble();
// min(int32, cte >= INT32_MAX) = int32
if (cte >= INT32_MAX && !max)
break;
// max(int32, cte <= INT32_MIN) = int32
if (cte <= INT32_MIN && max)
break;
}
// Force double MMinMax if argument is a "effectfull" double.
returnType = MIRType_Double;
break;
default:
return InliningStatus_NotInlined;
}
}
if (int32_cases.length() == 0)
returnType = MIRType_Double;
callInfo.setImplicitlyUsedUnchecked();
MDefinitionVector &cases = (returnType == MIRType_Int32) ? int32_cases : callInfo.argv();
if (cases.length() == 1) {
MLimitedTruncate *limit = MLimitedTruncate::New(alloc(), cases[0], MDefinition::NoTruncate);
current->add(limit);
current->push(limit);
return InliningStatus_Inlined;
}
// Chain N-1 MMinMax instructions to compute the MinMax.
MMinMax *last = MMinMax::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), returnType, max);
MMinMax *last = MMinMax::New(alloc(), cases[0], cases[1], returnType, max);
current->add(last);
for (unsigned i = 2; i < callInfo.argc(); i++) {
MMinMax *ins = MMinMax::New(alloc(), last, callInfo.getArg(i), returnType, max);
for (unsigned i = 2; i < cases.length(); i++) {
MMinMax *ins = MMinMax::New(alloc(), last, cases[2], returnType, max);
current->add(ins);
last = ins;
}

Просмотреть файл

@ -1830,6 +1830,41 @@ MMinMax::trySpecializeFloat32(TempAllocator &alloc)
setResultType(MIRType_Float32);
}
MDefinition *
MMinMax::foldsTo(TempAllocator &alloc)
{
if (!lhs()->isConstant() && !rhs()->isConstant())
return this;
MDefinition *operand = lhs()->isConstant() ? rhs() : lhs();
MConstant *constant = lhs()->isConstant() ? lhs()->toConstant() : rhs()->toConstant();
if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) {
const js::Value &val = constant->value();
// min(int32, cte >= INT32_MAX) = int32
if (val.isDouble() && val.toDouble() >= INT32_MAX && !isMax()) {
MLimitedTruncate *limit =
MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
block()->insertBefore(this, limit);
MToDouble *toDouble = MToDouble::New(alloc, limit);
block()->insertBefore(this, toDouble);
return toDouble;
}
// max(int32, cte <= INT32_MIN) = int32
if (val.isDouble() && val.toDouble() < INT32_MIN && isMax()) {
MLimitedTruncate *limit =
MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
block()->insertBefore(this, limit);
MToDouble *toDouble = MToDouble::New(alloc, limit);
block()->insertBefore(this, toDouble);
return toDouble;
}
}
return this;
}
bool
MAbs::fallible() const
{
@ -2976,7 +3011,7 @@ MCompare::tryFold(bool *result)
}
bool
MCompare::evaluateConstantOperands(bool *result)
MCompare::evaluateConstantOperands(TempAllocator &alloc, bool *result)
{
if (type() != MIRType_Boolean && type() != MIRType_Int32)
return false;
@ -2984,6 +3019,73 @@ MCompare::evaluateConstantOperands(bool *result)
MDefinition *left = getOperand(0);
MDefinition *right = getOperand(1);
if (compareType() == Compare_Double) {
// Optimize "MCompare MConstant (MToDouble SomethingInInt32Range).
// In most cases the MToDouble was added, because the constant is
// a double.
// e.g. v < 9007199254740991, where v is an int32 is always true.
if (!lhs()->isConstant() && !rhs()->isConstant())
return false;
MDefinition *operand = left->isConstant() ? right : left;
MConstant *constant = left->isConstant() ? left->toConstant() : right->toConstant();
MOZ_ASSERT(constant->value().isDouble());
double cte = constant->value().toDouble();
if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) {
bool replaced = false;
switch (jsop_) {
case JSOP_LT:
if (cte > INT32_MAX || cte < INT32_MIN) {
*result = !((constant == lhs()) ^ (cte < INT32_MIN));
replaced = true;
}
break;
case JSOP_LE:
if (cte >= INT32_MAX || cte <= INT32_MIN) {
*result = !((constant == lhs()) ^ (cte <= INT32_MIN));
replaced = true;
}
break;
case JSOP_GT:
if (cte > INT32_MAX || cte < INT32_MIN) {
*result = !((constant == rhs()) ^ (cte < INT32_MIN));
replaced = true;
}
break;
case JSOP_GE:
if (cte >= INT32_MAX || cte <= INT32_MIN) {
*result = !((constant == rhs()) ^ (cte <= INT32_MIN));
replaced = true;
}
break;
case JSOP_STRICTEQ: // Fall through.
case JSOP_EQ:
if (cte > INT32_MAX || cte < INT32_MIN) {
*result = false;
replaced = true;
}
break;
case JSOP_STRICTNE: // Fall through.
case JSOP_NE:
if (cte > INT32_MAX || cte < INT32_MIN) {
*result = true;
replaced = true;
}
break;
default:
MOZ_CRASH("Unexpected op.");
}
if (replaced) {
MLimitedTruncate *limit =
MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
limit->setGuardUnchecked();
block()->insertBefore(this, limit);
return true;
}
}
}
if (!left->isConstant() || !right->isConstant())
return false;
@ -3092,7 +3194,7 @@ MCompare::foldsTo(TempAllocator &alloc)
{
bool result;
if (tryFold(&result) || evaluateConstantOperands(&result)) {
if (tryFold(&result) || evaluateConstantOperands(alloc, &result)) {
if (type() == MIRType_Int32)
return MConstant::New(alloc, Int32Value(result));

Просмотреть файл

@ -3643,7 +3643,7 @@ class MCompare
CompareType compareType);
bool tryFold(bool *result);
bool evaluateConstantOperands(bool *result);
bool evaluateConstantOperands(TempAllocator &alloc, bool *result);
MDefinition *foldsTo(TempAllocator &alloc);
void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
bool *filtersNull);
@ -5008,6 +5008,7 @@ class MMinMax
AliasSet getAliasSet() const {
return AliasSet::None();
}
MDefinition *foldsTo(TempAllocator &alloc);
void computeRange(TempAllocator &alloc);
bool writeRecoverData(CompactBufferWriter &writer) const;
bool canRecoverOnBailout() const {

Просмотреть файл

@ -947,40 +947,47 @@ nsCSSRendering::PaintFocus(nsPresContext* aPresContext,
//----------------------------------------------------------------------
/**
* Computes the placement of a background image.
*
* @param aOriginBounds is the box to which the tiling position should be
* relative
* This should correspond to 'background-origin' for the frame,
* except when painting on the canvas, in which case the origin bounds
* should be the bounds of the root element's frame.
* @param aTopLeft the top-left corner where an image tile should be drawn
* @param aAnchorPoint a point which should be pixel-aligned by
* nsLayoutUtils::DrawImage. This is the same as aTopLeft, unless CSS
* specifies a percentage (including 'right' or 'bottom'), in which case
* it's that percentage within of aOriginBounds. So 'right' would set
* aAnchorPoint.x to aOriginBounds.XMost().
*
* Points are returned relative to aOriginBounds.
* Helper for ComputeObjectAnchorPoint; parameters are the same as for
* that function, except they're for a single coordinate / a single size
* dimension. (so, x/width vs. y/height)
*/
typedef nsStyleBackground::Position::PositionCoord PositionCoord;
static void
ComputeBackgroundAnchorPoint(const nsStyleBackground::Layer& aLayer,
const nsSize& aOriginBounds,
const nsSize& aImageSize,
nsPoint* aTopLeft,
nsPoint* aAnchorPoint)
ComputeObjectAnchorCoord(const PositionCoord& aCoord,
const nscoord aOriginBounds,
const nscoord aImageSize,
nscoord* aTopLeftCoord,
nscoord* aAnchorPointCoord)
{
double percentX = aLayer.mPosition.mXPosition.mPercent;
nscoord lengthX = aLayer.mPosition.mXPosition.mLength;
aAnchorPoint->x = lengthX + NSToCoordRound(percentX*aOriginBounds.width);
aTopLeft->x = lengthX +
NSToCoordRound(percentX*(aOriginBounds.width - aImageSize.width));
*aAnchorPointCoord = aCoord.mLength;
*aTopLeftCoord = aCoord.mLength;
double percentY = aLayer.mPosition.mYPosition.mPercent;
nscoord lengthY = aLayer.mPosition.mYPosition.mLength;
aAnchorPoint->y = lengthY + NSToCoordRound(percentY*aOriginBounds.height);
aTopLeft->y = lengthY +
NSToCoordRound(percentY*(aOriginBounds.height - aImageSize.height));
if (aCoord.mHasPercent) {
// Adjust aTopLeftCoord by the specified % of the extra space.
nscoord extraSpace = aOriginBounds - aImageSize;
*aTopLeftCoord += NSToCoordRound(aCoord.mPercent * extraSpace);
// The anchor-point doesn't care about our image's size; just the size
// of the region we're rendering into.
*aAnchorPointCoord += NSToCoordRound(aCoord.mPercent * aOriginBounds);
}
}
void
nsImageRenderer::ComputeObjectAnchorPoint(
const nsStyleBackground::Position& aPos,
const nsSize& aOriginBounds,
const nsSize& aImageSize,
nsPoint* aTopLeft,
nsPoint* aAnchorPoint)
{
ComputeObjectAnchorCoord(aPos.mXPosition,
aOriginBounds.width, aImageSize.width,
&aTopLeft->x, &aAnchorPoint->x);
ComputeObjectAnchorCoord(aPos.mYPosition,
aOriginBounds.height, aImageSize.height,
&aTopLeft->y, &aAnchorPoint->y);
}
nsIFrame*
@ -3167,8 +3174,9 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
// Compute the position of the background now that the background's size is
// determined.
ComputeBackgroundAnchorPoint(aLayer, bgPositionSize, imageSize,
&imageTopLeft, &state.mAnchor);
nsImageRenderer::ComputeObjectAnchorPoint(aLayer.mPosition,
bgPositionSize, imageSize,
&imageTopLeft, &state.mAnchor);
imageTopLeft += bgPositioningArea.TopLeft();
state.mAnchor += bgPositioningArea.TopLeft();

Просмотреть файл

@ -138,6 +138,33 @@ public:
*/
mozilla::CSSSizeOrRatio ComputeIntrinsicSize();
/**
* Computes the placement for a background image, or for the image data
* inside of a replaced element.
*
* @param aPos The CSS <position> value that specifies the image's position.
* @param aOriginBounds The box to which the tiling position should be
* relative. For background images, this should correspond to
* 'background-origin' for the frame, except when painting on the
* canvas, in which case the origin bounds should be the bounds
* of the root element's frame. For a replaced element, this should
* be the element's content-box.
* @param aTopLeft [out] The top-left corner where an image tile should be
* drawn.
* @param aAnchorPoint [out] A point which should be pixel-aligned by
* nsLayoutUtils::DrawImage. This is the same as aTopLeft, unless
* CSS specifies a percentage (including 'right' or 'bottom'), in
* which case it's that percentage within of aOriginBounds. So
* 'right' would set aAnchorPoint.x to aOriginBounds.XMost().
*
* Points are returned relative to aOriginBounds.
*/
static void ComputeObjectAnchorPoint(const nsStyleBackground::Position& aPos,
const nsSize& aOriginBounds,
const nsSize& aImageSize,
nsPoint* aTopLeft,
nsPoint* aAnchorPoint);
/**
* Compute the size of the rendered image using either the 'cover' or
* 'contain' constraints (aFitType).

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<style>
.container {
border: 1px solid black;
}
</style>
</head>
<body>
<div class="container">
<div>T</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<style>
.container {
display: flex;
overflow-y: auto;
border: 1px solid black;
}
</style>
<script type='text/javascript'>
window.addEventListener("MozReftestInvalidate", startTest);
function startTest() {
// NOTE: setTimeout in tests is evil, but it's necessary here -- we need
// to wait until the scrollbars have finished fading, and there's no
// event we can listen for to signal that, AFAIK. Fortunately, there
// shouldn't be *visible* scrollbars in this testcase, so even if our
// setTimeout fires too early/late, the test will still pass. (So, there
// shouldn't be spurious failures; any failures that happen will be real.)
setTimeout(endTest, 800);
}
function endTest() {
document.documentElement.removeAttribute("class");
}
</script>
</head>
<body>
<div class="container">
<div>T</div>
</div>
</body>
</html>

Просмотреть файл

@ -1837,4 +1837,5 @@ fails-if(Android) == 1062792-1.html 1062792-1-ref.html
test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html
== 1069716-1.html 1069716-1-ref.html
== 1078262-1.html about:blank
== 1081072-1.html 1081072-1-ref.html
== 1081185-1.html 1081185-1-ref.html

Просмотреть файл

@ -940,11 +940,8 @@ pref("content.sink.pending_event_mode", 0);
// 2 = openAbused
pref("privacy.popups.disable_from_plugins", 2);
// "do not track" HTTP header, disabled by default
// send "do not track" HTTP header, disabled by default
pref("privacy.donottrackheader.enabled", false);
// 0 = tracking is acceptable
// 1 = tracking is unacceptable
pref("privacy.donottrackheader.value", 1);
// Enforce tracking protection
pref("privacy.trackingprotection.enabled", false);

Просмотреть файл

@ -83,8 +83,6 @@ extern PRThread *gSocketThread;
#define INTL_ACCEPT_LANGUAGES "intl.accept_languages"
#define BROWSER_PREF_PREFIX "browser.cache."
#define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
#define DONOTTRACK_HEADER_VALUE "privacy.donottrackheader.value"
#define DONOTTRACK_VALUE_UNSET 2
#define TELEMETRY_ENABLED "toolkit.telemetry.enabled"
#define ALLOW_EXPERIMENTS "network.allow-experiments"
#define SAFE_HINT_HEADER_VALUE "safeHint.enabled"
@ -175,7 +173,6 @@ nsHttpHandler::nsHttpHandler()
, mSendSecureXSiteReferrer(true)
, mEnablePersistentHttpsCaching(false)
, mDoNotTrackEnabled(false)
, mDoNotTrackValue(1)
, mSafeHintEnabled(false)
, mParentalControlEnabled(false)
, mTelemetryEnabled(false)
@ -274,7 +271,6 @@ nsHttpHandler::Init()
prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true);
prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
prefBranch->AddObserver(DONOTTRACK_HEADER_VALUE, this, true);
prefBranch->AddObserver(TELEMETRY_ENABLED, this, true);
prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.short_lived_connections"), this, true);
prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.long_lived_connections"), this, true);
@ -427,8 +423,7 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request)
// Add the "Do-Not-Track" header
if (mDoNotTrackEnabled) {
rv = request->SetHeader(nsHttp::DoNotTrack,
nsPrintfCString("%d", mDoNotTrackValue));
rv = request->SetHeader(nsHttp::DoNotTrack, NS_LITERAL_CSTRING("1"));
if (NS_FAILED(rv)) return rv;
}
@ -1356,14 +1351,6 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
mDoNotTrackEnabled = cVar;
}
}
if (PREF_CHANGED(DONOTTRACK_HEADER_VALUE)) {
val = 1;
rv = prefs->GetIntPref(DONOTTRACK_HEADER_VALUE, &val);
if (NS_SUCCEEDED(rv)) {
mDoNotTrackValue = val;
}
}
// Hint option
if (PREF_CHANGED(SAFE_HINT_HEADER_VALUE)) {
cVar = false;
@ -1860,9 +1847,9 @@ nsHttpHandler::Observe(nsISupports *subject,
mSessionStartTime = NowInSeconds();
if (!mDoNotTrackEnabled) {
Telemetry::Accumulate(Telemetry::DNT_USAGE, DONOTTRACK_VALUE_UNSET);
Telemetry::Accumulate(Telemetry::DNT_USAGE, 2);
} else {
Telemetry::Accumulate(Telemetry::DNT_USAGE, mDoNotTrackValue);
Telemetry::Accumulate(Telemetry::DNT_USAGE, 1);
}
} else if (!strcmp(topic, "profile-change-net-restore")) {
// initialize connection manager

Просмотреть файл

@ -450,7 +450,6 @@ private:
// For broadcasting tracking preference
bool mDoNotTrackEnabled;
uint8_t mDoNotTrackValue;
// for broadcasting safe hint;
bool mSafeHintEnabled;

Просмотреть файл

@ -589,6 +589,9 @@ void
RegisterAnnotator(Annotator& aAnnotator)
{
#ifdef REPORT_CHROME_HANGS
if (GeckoProcessType_Default != XRE_GetProcessType()) {
return;
}
MonitorAutoLock lock(*gMonitor);
MOZ_ASSERT(gAnnotators);
gAnnotators->insert(&aAnnotator);
@ -599,6 +602,9 @@ void
UnregisterAnnotator(Annotator& aAnnotator)
{
#ifdef REPORT_CHROME_HANGS
if (GeckoProcessType_Default != XRE_GetProcessType()) {
return;
}
MonitorAutoLock lock(*gMonitor);
MOZ_ASSERT(gAnnotators);
gAnnotators->erase(&aAnnotator);