Merge inbound to m-c a=merge CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Wed, 22 Oct 2014 18:46:27 -0700
changeset 238249 88adcf8fef8312a8e801321a13da665db3de838d
parent 238233 34c66dadd802a61cd373f68c6f6910011dd47ea8 (current diff)
parent 238248 f0520d8ed4ede84eec453526230ae4185f56cdc9 (diff)
child 238255 b8ffe4d6c1787c216d8a746bcbb198a90d6ae5f8
child 238318 226e0a5bf59609bfb7f5cdda3f6606ee9d260e9a
child 238377 942d0f8ec515e37a8d158dd82172402aefca2a70
push id660
push userraliiev@mozilla.com
push dateWed, 18 Feb 2015 20:30:48 +0000
treeherdermozilla-release@49e493494178 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
88adcf8fef83 / 36.0a1 / 20141023030203 / files
nightly linux64
88adcf8fef83 / 36.0a1 / 20141023030203 / files
nightly mac
88adcf8fef83 / 36.0a1 / 20141023030203 / files
nightly win32
88adcf8fef83 / 36.0a1 / 20141023030203 / files
nightly win64
88adcf8fef83 / 36.0a1 / 20141023030203 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c a=merge CLOSED TREE
gfx/layers/ipc/CompositorParent.cpp
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1272,17 +1272,16 @@ pref("services.sync.prefs.sync.privacy.c
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.downloads", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.formdata", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.history", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.offlineApps", true);
 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);
 pref("services.sync.prefs.sync.security.OCSP.require", true);
 pref("services.sync.prefs.sync.security.default_personal_cert", true);
 pref("services.sync.prefs.sync.security.tls.version.min", true);
 pref("services.sync.prefs.sync.security.tls.version.max", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1364,17 +1364,17 @@ BrowserGlue.prototype = {
     var notifyBox = win.gBrowser.getNotificationBox();
     var notification = notifyBox.appendNotification(text, title, null,
                                                     notifyBox.PRIORITY_CRITICAL_MEDIUM,
                                                     buttons);
     notification.persistence = -1; // Until user closes it
   },
 
   _migrateUI: function BG__migrateUI() {
-    const UI_VERSION = 24;
+    const UI_VERSION = 25;
     const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
     let currentUIVersion = 0;
     try {
       currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
     } catch(ex) {}
     if (currentUIVersion >= UI_VERSION)
       return;
 
@@ -1612,16 +1612,30 @@ BrowserGlue.prototype = {
       let uri = Services.prefs.getComplexValue(HOMEPAGE_PREF,
                                                Ci.nsIPrefLocalizedString).data;
       if (uri && (uri.startsWith("http://start.mozilla.org") ||
                   /^https?:\/\/(www\.)?google\.[a-z.]+\/firefox/i.test(uri))) {
         Services.prefs.clearUserPref(HOMEPAGE_PREF);
       }
     }
 
+    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);
   },
 
   // ------------------------------
   // public nsIBrowserGlue members
   // ------------------------------
 
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -158,53 +158,16 @@ var gPrivacyPane = {
     case "custom":
       selectedIndex = 2;
       break;
     }
     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
    */
   updateHistoryModePrefs: function PPP_updateHistoryModePrefs()
   {
     let pref = document.getElementById("browser.privatebrowsing.autostart");
     switch (document.getElementById("historyMode").value) {
     case "remember":
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -8,19 +8,16 @@
         src="chrome://browser/content/preferences/in-content/privacy.js"/>
 
 <preferences id="privacyPreferences">
 
   <!-- Tracking -->
   <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"
               name="pref.privacy.disable_button.cookie_exceptions"
               type="bool"/>
   <preference id="pref.privacy.disable_button.view_cookies"
               name="pref.privacy.disable_button.view_cookies"
               type="bool"/>
@@ -69,31 +66,30 @@
       hidden="true"
       data-category="panePrivacy">
   <label class="header-name">&panePrivacy.title;</label>
 </hbox>
 
 <!-- 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 -->
 <groupbox id="historyGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&history.label;</label></caption>
   <hbox align="center">
     <label id="historyModeLabel"
            control="historyMode"
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -120,52 +120,16 @@ var gPrivacyPane = {
     case "custom":
       selectedIndex = 2;
       break;
     }
     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
    */
   updateHistoryModePrefs: function PPP_updateHistoryModePrefs()
   {
     let pref = document.getElementById("browser.privatebrowsing.autostart");
     switch (document.getElementById("historyMode").value) {
     case "remember":
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -21,19 +21,16 @@
             helpTopic="prefs-privacy">
 
     <preferences id="privacyPreferences">
   
       <!-- Tracking -->
       <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"
                   name="pref.privacy.disable_button.cookie_exceptions"
                   type="bool"/>
       <preference id="pref.privacy.disable_button.view_cookies"
                   name="pref.privacy.disable_button.view_cookies"
                   type="bool"/>
@@ -79,30 +76,29 @@
     
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
     
     <script type="application/javascript" src="chrome://browser/content/preferences/privacy.js"/>
 
     <!-- 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>
 
     <!-- History -->
     <groupbox id="historyGroup">
       <caption label="&history.label;"/>
 
       <hbox align="center">
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -1,20 +1,16 @@
 <!-- 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/. -->
 
 <!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">
 <!ENTITY doNotTrackInfo.label           "Learn More">
 
 <!ENTITY  history.label                 "History">
 
 <!ENTITY  locationBar.label             "Location Bar">
--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -132,18 +132,17 @@ let DirectoryLinksProvider = {
   /**
    * Set appropriate default ping behavior controlled by enhanced pref
    */
   _setDefaultEnhanced: function DirectoryLinksProvider_setDefaultEnhanced() {
     if (!Services.prefs.prefHasUserValue(PREF_NEWTAB_ENHANCED)) {
       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;
         }
       }
       catch(ex) {}
       Services.prefs.setBoolPref(PREF_NEWTAB_ENHANCED, enhanced);
     }
   },
 
--- a/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
+++ b/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
@@ -609,28 +609,23 @@ add_task(function test_DirectoryLinksPro
 });
 
 add_task(function test_DirectoryLinksProvider_setDefaultEnhanced() {
   function checkDefault(expected) {
     Services.prefs.clearUserPref(kNewtabEnhancedPref);
     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);
 
   // Clean up
   Services.prefs.clearUserPref("privacy.donottrackheader.value");
 });
--- a/content/base/src/nsCSPParser.cpp
+++ b/content/base/src/nsCSPParser.cpp
@@ -817,41 +817,32 @@ nsCSPParser::directive()
   // one directive and one src.
   if (mCurDir.Length() < 1) {
     const char16_t* params[] = { NS_LITERAL_STRING("directive missing").get() };
     logWarningErrorToConsole(nsIScriptError::warningFlag, "failedToParseUnrecognizedSource",
                              params, ArrayLength(params));
     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) {
     // if we can not create a CSPDirective, we can skip parsing the srcs for that array
     return;
   }
 
   // Try to parse all the srcs by handing the array off to directiveValue
   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
   cspDir->addSrcs(srcs);
   mPolicy->addDirective(cspDir);
 }
 
 // policy = [ directive *( ";" [ directive ] ) ]
--- a/content/base/test/TestCSPParser.cpp
+++ b/content/base/test/TestCSPParser.cpp
@@ -433,66 +433,88 @@ nsresult TestSimplePolicies() {
     { "script-src 1",
       "script-src http://1" }
   };
 
   uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
   return runTestSuite(policies, policyCount, 1);
 }
 
-// ============================= TestPoliciesThatLogWarning ========================
+// ============================= TestPoliciesWithInvalidSrc ========================
 
-nsresult TestPoliciesThatLogWarning() {
+nsresult TestPoliciesWithInvalidSrc() {
 
   static const PolicyTest policies[] =
   {
     { "script-src 'self'; SCRIPT-SRC http://www.example.com",
       "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);
   return runTestSuite(policies, policyCount, 1);
 }
 
 // ============================= TestBadPolicies ========================
 
 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);
   return runTestSuite(policies, policyCount, 0);
 }
 
 // ============================= TestGoodGeneratedPolicies ========================
 
@@ -743,18 +765,16 @@ nsresult TestBadGeneratedPolicies() {
     { "ht!ps://f-oo.bar", ""},
     { "https://f-oo.bar:3f", ""},
     { "**", ""},
     { "*a", ""},
     { "http://username:password@self.com/foo", ""},
     { "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);
   return runTestSuite(policies, policyCount, 0);
 }
 
 // ============ TestGoodGeneratedPoliciesForPathHandling ============
 
@@ -879,27 +899,34 @@ nsresult TestGoodGeneratedPoliciesForPat
 }
 
 // ============ TestBadGeneratedPoliciesForPathHandling ============
 
 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 ========================
 
 // Use a policy, eliminate one character at a time,
 // and feed it as input to the parser.
 
 nsresult TestShorteningPolicies() {
@@ -1053,17 +1080,17 @@ int main(int argc, char** argv) {
     return 1;
   }
 
   if (NS_FAILED(TestDirectives()))                           { return 1; }
   if (NS_FAILED(TestKeywords()))                             { return 1; }
   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; }
   if (NS_FAILED(TestGoodGeneratedPoliciesForPathHandling())) { return 1; }
   if (NS_FAILED(TestBadGeneratedPoliciesForPathHandling()))  { return 1; }
   if (NS_FAILED(TestShorteningPolicies()))                   { return 1; }
 
 #if RUN_OFFLINE_TESTS
new file mode 100644
--- /dev/null
+++ b/content/base/test/csp/file_csp_invalid_source_expression.html
@@ -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>
--- a/content/base/test/csp/mochitest.ini
+++ b/content/base/test/csp/mochitest.ini
@@ -31,16 +31,17 @@ support-files =
   file_CSP_inlinescript_main.html
   file_CSP_inlinescript_main.html^headers^
   file_CSP_inlinescript_main_allowed.html
   file_CSP_inlinescript_main_allowed.html^headers^
   file_CSP_inlinestyle_main.html
   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
   file_bug836922_npolicies.html
   file_bug836922_npolicies.html^headers^
   file_bug836922_npolicies_ro_violation.sjs
   file_bug836922_npolicies_violation.sjs
   file_bug886164.html
@@ -106,16 +107,17 @@ support-files =
 [test_CSP_bug802872.html]
 [test_CSP_bug885433.html]
 [test_CSP_bug888172.html]
 [test_CSP_evalscript.html]
 [test_CSP_frameancestors.html]
 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]
 [test_CSP_bug910139.html]
 [test_CSP_bug909029.html]
 [test_policyuri_regression_from_multipolicy.html]
 [test_nonce_source.html]
 [test_CSP_bug941404.html]
new file mode 100644
--- /dev/null
+++ b/content/base/test/csp/test_csp_invalid_source_expression.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>
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -107,31 +107,27 @@
 #include "mozilla/dom/ContentChild.h"
 
 #include "mozilla/dom/FeatureList.h"
 
 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;
 
 /* static */
 void
 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,
                                "dom.vibrator.max_vibrate_ms", 10000);
   Preferences::AddUintVarCache(&sMaxVibrateListLen,
                                "dom.vibrator.max_vibrate_list_len", 128);
 }
 
@@ -623,21 +619,17 @@ Navigator::GetBuildID(nsAString& aBuildI
   AppendASCIItoUTF16(buildID, aBuildID);
   return NS_OK;
 }
 
 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");
   }
 
   return NS_OK;
 }
 
 bool
--- a/dom/tests/mochitest/general/test_donottrack.html
+++ b/dom/tests/mochitest/general/test_donottrack.html
@@ -9,17 +9,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=629535">Mozilla Bug 629535</a>
 
 <script type="application/javascript">
 
 const dntPref = 'privacy.donottrackheader.enabled';
-const dntValuePref = 'privacy.donottrackheader.value';
 
 SimpleTest.waitForExplicitFinish();
 
 var currentTestIdx = -1;
 var tests = [];
 function nextTest() {
   currentTestIdx++;
   if (currentTestIdx >= tests.length) {
@@ -34,18 +33,16 @@ tests.push(function testDefaultValues() 
   // The default pref values depend on the OS it seems.
   var isAndroid = !!navigator.userAgent.contains("Android");
   var isB2G = !isAndroid && /Mobile|Tablet/.test(navigator.userAgent);
 
   is(SpecialPowers.getBoolPref(dntPref), false,
      '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();
 });
 
 tests.push(function clearedEnabled() {
   SpecialPowers.pushPrefEnv({"clear": [[dntPref]]}, function() {
     is(navigator.doNotTrack, "unspecified", 'after clearing pref');
     nextTest();
@@ -54,44 +51,16 @@ tests.push(function clearedEnabled() {
 
 tests.push(function setEnabled() {
   SpecialPowers.pushPrefEnv({"set": [[dntPref, true]]}, function() {
     is(navigator.doNotTrack, "1", 'after setting pref to true');
     nextTest();
   });
 });
 
-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');
     nextTest();
   });
 });
 
 nextTest();
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -61,16 +61,60 @@ LayerHasCheckerboardingAPZC(Layer* aLaye
       }
       return true;
     }
     break;
   }
   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)
 {
 
   if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
     // XXX - should figure out a way to render this, but for now this
     // is hard to do, since it will often get superimposed over the first
@@ -113,20 +157,22 @@ static void PrintUniformityInfo(Layer* a
   LayerTranslationPayload* payload = new LayerTranslationPayload(aLayer, translation);
   PROFILER_MARKER_PAYLOAD("LayerTranslation", payload);
 #endif
 }
 
 /* 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() */
 struct PreparedData
 {
   RefPtr<CompositingRenderTarget> mTmpTarget;
   nsAutoTArray<PreparedLayer, 12> mLayers;
   bool mNeedsSurfaceCopy;
@@ -172,18 +218,48 @@ ContainerPrepare(ContainerT* aContainer,
         !quad.Intersects(compositor->ClipRectInLayersCoordinates(layerToRender->GetLayer(), clipRect)) &&
         !LayerHasCheckerboardingAPZC(layerToRender->GetLayer(), nullptr)) {
       CULLING_LOG("Sublayer %p is clipped entirely\n", layerToRender->GetLayer());
       continue;
     }
 
     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());
 
   /**
    * Setup our temporary surface for rendering the contents of this container.
    */
 
@@ -244,16 +320,21 @@ RenderLayers(ContainerT* aContainer,
         gfx::Rect fbRect(clearRect.x, clearRect.y, clearRect.width, clearRect.height);
         compositor->ClearRect(fbRect);
         layerToRender->SetClearRect(nsIntRect(0, 0, 0, 0));
       }
     } else {
       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);
     }
 
     if (gfxPrefs::DrawLayerInfo()) {
       DrawLayerInfo(clipRect, aManager, layer);
     }
 
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -192,65 +192,16 @@ LayerManagerComposite::BeginTransactionW
   }
 
   mIsCompositorReady = true;
   mCompositor->SetTargetContext(aTarget, aRect);
   mTarget = aTarget;
   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)
 {
   NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
   if (!mRoot) {
     mInTransaction = false;
     mIsCompositorReady = false;
     return false;
@@ -301,19 +252,16 @@ LayerManagerComposite::EndTransaction(Dr
       // properties.
       mRoot->ApplyPendingUpdatesToSubtree();
     }
 
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
 
-    nsIntRegion opaque;
-    ApplyOcclusionCulling(mRoot, opaque);
-
     Render();
     mGeometryChanged = false;
   } else {
     // Modified layer tree
     mGeometryChanged = true;
   }
 
   mCompositor->ClearTargetContext();
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -161,23 +161,16 @@ public:
   virtual bool AreComponentAlphaLayersEnabled() MOZ_OVERRIDE;
 
   virtual TemporaryRef<DrawTarget>
     CreateOptimalMaskDrawTarget(const IntSize &aSize) MOZ_OVERRIDE;
 
   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.
    */
   class AutoAddMaskEffect
   {
   public:
     AutoAddMaskEffect(Layer* aMaskLayer,
                       EffectChain& aEffect,
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -787,36 +787,16 @@ CompositorParent::CompositeCallback(Time
   } else {
     mLastCompose = TimeStamp::Now();
   }
 
   mCurrentCompositeTask = nullptr;
   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)
 {
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
   PROFILER_LABEL("CompositorParent", "Composite",
     js::ProfileEntry::Category::GRAPHICS);
 
   MOZ_ASSERT(IsInCompositorThread(),
@@ -832,17 +812,16 @@ CompositorParent::CompositeToTarget(Draw
 #endif
 
   if (!CanComposite()) {
     DidComposite();
     return;
   }
 
   AutoResolveRefLayers resolve(mCompositionManager);
-  SetShadowProperties(mLayerManager->GetRoot());
 
   if (aTarget) {
     mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect);
   } else {
     mLayerManager->BeginTransaction();
   }
 
   if (mForceCompositionTask && !mOverrideComposeReadiness) {
@@ -920,16 +899,36 @@ CompositorParent::ForceComposeToTarget(D
 bool
 CompositorParent::CanComposite()
 {
   return mLayerManager &&
          mLayerManager->GetRoot() &&
          !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)
 {
   MOZ_ASSERT(IsInCompositorThread());
 
   if (!aIsFirstPaint &&
       !mCompositionManager->IsFirstPaint() &&
@@ -967,16 +966,19 @@ CompositorParent::ShadowLayersUpdated(La
     AutoResolveRefLayers resolve(mCompositionManager);
     mApzcTreeManager->UpdatePanZoomControllerTree(this, root, aIsFirstPaint,
         mRootLayerTreeID, aPaintSequenceNumber);
   }
 
   MOZ_ASSERT(aTransactionId > mPendingTransaction);
   mPendingTransaction = aTransactionId;
 
+  if (root) {
+    SetShadowProperties(root);
+  }
   if (aScheduleComposite) {
     ScheduleComposition();
     if (mPaused) {
       DidComposite();
     }
     // When testing we synchronously update the shadow tree with the animated
     // values to avoid race conditions when calling GetAnimationTransform etc.
     // (since the above SetShadowProperties will remove animation effects).
@@ -984,17 +986,16 @@ CompositorParent::ShadowLayersUpdated(La
     // scheduled in order to better match the behavior under regular sampling
     // conditions.
     bool needTestComposite = mIsTesting && root &&
                              (mCurrentCompositeTask ||
                              (gfxPrefs::VsyncAlignedCompositor() &&
                               mCompositorVsyncObserver->NeedsComposite()));
     if (needTestComposite) {
       AutoResolveRefLayers resolve(mCompositionManager);
-      SetShadowProperties(mLayerManager->GetRoot());
       bool requestNextFrame =
         mCompositionManager->TransformShadowTree(mTestTime);
       if (!requestNextFrame) {
         CancelCurrentCompositeTask();
         // Pretend we composited in case someone is waiting for this event.
         DidComposite();
       }
     }
@@ -1021,17 +1022,16 @@ CompositorParent::SetTestSampleTime(Laye
 
   bool testComposite = mCompositionManager && (mCurrentCompositeTask ||
                                                (gfxPrefs::VsyncAlignedCompositor()
                                                && mCompositorVsyncObserver->NeedsComposite()));
 
   // 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();
       // Pretend we composited in case someone is wating for this event.
       DidComposite();
     }
   }
 
@@ -1584,16 +1584,19 @@ CrossProcessCompositorParent::ShadowLaye
   const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(id);
   if (!state) {
     return;
   }
   MOZ_ASSERT(state->mParent);
   state->mParent->ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint);
 
   Layer* shadowRoot = aLayerTree->GetRoot();
+  if (shadowRoot) {
+    SetShadowProperties(shadowRoot);
+  }
   UpdateIndirectTree(id, shadowRoot, aTargetConfig);
 
   state->mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite,
       aPaintSequenceNumber, aIsRepeatTransaction);
 
   // Send the 'remote paint ready' message to the content thread if it has already asked.
   if(mNotifyAfterRemotePaint)  {
     unused << SendRemotePaintIsReady();
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -95,17 +95,17 @@ function CheckObjectCoercible(v) {
 /* Spec: ECMAScript Draft, 6 edition May 22, 2014, 7.1.15 */
 function ToLength(v) {
     v = ToInteger(v);
 
     if (v <= 0)
         return 0;
 
     // Math.pow(2, 53) - 1 = 0x1fffffffffffff
-    return v < 0x1fffffffffffff ? v : 0x1fffffffffffff;
+    return std_Math_min(v, 0x1fffffffffffff);
 }
 
 /********** Testing code **********/
 
 #ifdef ENABLE_PARALLEL_JS
 
 /**
  * Internal debugging tool: checks that the given `mode` permits
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5566,19 +5566,21 @@ CodeGenerator::visitIsNullOrLikeUndefine
         } else {
             label1.emplace();
             label2.emplace();
             nullOrLikeUndefined = label1.ptr();
             notNullOrLikeUndefined = label2.ptr();
         }
 
         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
             // undefined.
             masm.branchTestObject(Assembler::NotEqual, tag, notNullOrLikeUndefined);
 
             Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox()));
             branchTestObjectEmulatesUndefined(objreg, nullOrLikeUndefined, notNullOrLikeUndefined,
@@ -5647,18 +5649,21 @@ CodeGenerator::visitIsNullOrLikeUndefine
                 return false;
         }
 
         Register tag = masm.splitTagForTest(value);
 
         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);
 
             // Objects that emulate undefined are loosely equal to null/undefined.
             Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox()));
             Register scratch = ToRegister(lir->temp());
             testObjectEmulatesUndefined(objreg, ifTrueLabel, ifFalseLabel, scratch, ool);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -1142,41 +1142,74 @@ IonBuilder::inlineMathFRound(CallInfo &c
     current->add(ins);
     current->push(ins);
     return InliningStatus_Inlined;
 }
 
 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;
     }
 
     current->push(last);
     return InliningStatus_Inlined;
 }
 
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -1825,16 +1825,51 @@ MMinMax::trySpecializeFloat32(TempAlloca
             ConvertDefinitionToDouble<1>(alloc, right, this);
         return;
     }
 
     specialization_ = MIRType_Float32;
     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
 {
     return !implicitTruncate_ && (!range() || !range()->hasInt32Bounds());
 }
 
 void
 MAbs::trySpecializeFloat32(TempAllocator &alloc)
@@ -2971,24 +3006,91 @@ MCompare::tryFold(bool *result)
             MOZ_CRASH("Unexpected type");
         }
     }
 
     return false;
 }
 
 bool
-MCompare::evaluateConstantOperands(bool *result)
+MCompare::evaluateConstantOperands(TempAllocator &alloc, bool *result)
 {
     if (type() != MIRType_Boolean && type() != MIRType_Int32)
         return false;
 
     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;
 
     Value lhs = left->toConstant()->value();
     Value rhs = right->toConstant()->value();
 
     // Fold away some String equality comparisons.
     if (lhs.isString() && rhs.isString()) {
@@ -3087,17 +3189,17 @@ MCompare::evaluateConstantOperands(bool 
     return true;
 }
 
 MDefinition *
 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));
 
         MOZ_ASSERT(type() == MIRType_Boolean);
         return MConstant::New(alloc, BooleanValue(result));
     }
 
     return this;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3638,17 +3638,17 @@ class MCompare
 
   public:
     INSTRUCTION_HEADER(Compare)
     static MCompare *New(TempAllocator &alloc, MDefinition *left, MDefinition *right, JSOp op);
     static MCompare *NewAsmJS(TempAllocator &alloc, MDefinition *left, MDefinition *right, JSOp op,
                               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);
 
     void infer(BaselineInspector *inspector, jsbytecode *pc);
     CompareType compareType() const {
         return compareType_;
     }
@@ -5003,16 +5003,17 @@ class MMinMax
         if (isMax() != ins->toMinMax()->isMax())
             return false;
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
+    MDefinition *foldsTo(TempAllocator &alloc);
     void computeRange(TempAllocator &alloc);
     bool writeRecoverData(CompactBufferWriter &writer) const;
     bool canRecoverOnBailout() const {
         return true;
     }
 
     bool isFloat32Commutative() const { return true; }
     void trySpecializeFloat32(TempAllocator &alloc);
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -942,50 +942,57 @@ nsCSSRendering::PaintFocus(nsPresContext
 
 // Thebes Border Rendering Code End
 //----------------------------------------------------------------------
 
 
 //----------------------------------------------------------------------
 
 /**
- * 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));
-
-  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));
+  *aAnchorPointCoord = aCoord.mLength;
+  *aTopLeftCoord = aCoord.mLength;
+
+  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*
 nsCSSRendering::FindNonTransparentBackgroundFrame(nsIFrame* aFrame,
                                                   bool aStartAtParent /*= false*/)
 {
   NS_ASSERTION(aFrame, "Cannot find NonTransparentBackgroundFrame in a null frame");
 
@@ -3162,18 +3169,19 @@ nsCSSRendering::PrepareBackgroundLayer(n
   if (imageSize.width <= 0 || imageSize.height <= 0)
     return state;
 
   state.mImageRenderer.SetPreferredSize(intrinsicSize,
                                         imageSize);
 
   // 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();
 
   state.mDestArea = nsRect(imageTopLeft + aBorderArea.TopLeft(), imageSize);
   state.mFillArea = state.mDestArea;
   int repeatX = aLayer.mRepeat.mXRepeat;
   int repeatY = aLayer.mRepeat.mYRepeat;
   if (repeatX == NS_STYLE_BG_REPEAT_REPEAT) {
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -134,16 +134,43 @@ public:
   /**
    * Compute the intrinsic size of the image as defined in the CSS Image Values
    * spec. The intrinsic size is the unscaled size which the image would ideally
    * like to be in app units.
    */
   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).
    * aIntrinsicRatio may be an invalid ratio, that is one or both of its
    * dimensions can be less than or equal to zero.
    */
   static nsSize ComputeConstrainedSize(const nsSize& aConstrainingSize,
                                        const nsSize& aIntrinsicRatio,
                                        FitType aFitType);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1081072-1-ref.html
@@ -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>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1081072-1.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>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1832,9 +1832,10 @@ test-pref(layout.css.grid.enabled,true) 
 == 1059498-1.html 1059498-1-ref.html
 == 1059498-2.html 1059498-1-ref.html
 == 1059498-3.html 1059498-1-ref.html
 fails-if(Android) == 1062792-1.html 1062792-1-ref.html
 == 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-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
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -935,21 +935,18 @@ pref("content.sink.pending_event_mode", 
 #endif
 
 // Disable popups from plugins by default
 //   0 = openAllowed
 //   1 = openControlled
 //   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);
 
 pref("dom.event.contextmenu.enabled",       true);
 pref("dom.event.clipboardevents.enabled",   true);
 #if defined(XP_WIN) && !defined(RELEASE_BUILD)
 pref("dom.event.highrestimestamp.enabled",  true);
 #else
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -78,18 +78,16 @@ extern PRThread *gSocketThread;
 #ifdef XP_WIN
 #define UA_SPARE_PLATFORM
 #endif
 
 #define HTTP_PREF_PREFIX        "network.http."
 #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"
 
 #define UA_PREF(_pref) UA_PREF_PREFIX _pref
 #define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
 #define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
 
@@ -170,17 +168,16 @@ nsHttpHandler::nsHttpHandler()
     , mLegacyAppVersion("5.0")
     , mProduct("Gecko")
     , mUserAgentIsDirty(true)
     , mUseCache(true)
     , mPromptTempRedirect(true)
     , mSendSecureXSiteReferrer(true)
     , mEnablePersistentHttpsCaching(false)
     , mDoNotTrackEnabled(false)
-    , mDoNotTrackValue(1)
     , mSafeHintEnabled(false)
     , mParentalControlEnabled(false)
     , mTelemetryEnabled(false)
     , mAllowExperiments(true)
     , mHandlerActive(false)
     , mEnableSpdy(false)
     , mSpdyV3(true)
     , mSpdyV31(true)
@@ -269,17 +266,16 @@ nsHttpHandler::Init()
     // monitor some preference changes
     nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (prefBranch) {
         prefBranch->AddObserver(HTTP_PREF_PREFIX, this, true);
         prefBranch->AddObserver(UA_PREF_PREFIX, this, true);
         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);
         prefBranch->AddObserver(SAFE_HINT_HEADER_VALUE, this, true);
         PrefsChanged(prefBranch, nullptr);
     }
 
     mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
@@ -422,18 +418,17 @@ nsHttpHandler::AddStandardRequestHeaders
     }
 
     // Add the "Accept-Encoding" header
     rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
     if (NS_FAILED(rv)) return rv;
 
     // 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;
     }
 
     // add the "Send Hint" header
     if (mSafeHintEnabled || mParentalControlEnabled) {
       rv = request->SetHeader(nsHttp::Prefer, NS_LITERAL_CSTRING("safe"));
       if (NS_FAILED(rv)) return rv;
     }
@@ -1351,24 +1346,16 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
 
     if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED)) {
         cVar = false;
         rv = prefs->GetBoolPref(DONOTTRACK_HEADER_ENABLED, &cVar);
         if (NS_SUCCEEDED(rv)) {
             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;
         rv = prefs->GetBoolPref(SAFE_HINT_HEADER_VALUE, &cVar);
         if (NS_SUCCEEDED(rv)) {
             mSafeHintEnabled = cVar;
         }
     }
@@ -1855,19 +1842,19 @@ nsHttpHandler::Observe(nsISupports *subj
         if (mConnMgr)
             mConnMgr->Shutdown();
 
         // need to reset the session start time since cache validation may
         // depend on this value.
         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
         InitConnectionMgr();
     } else if (!strcmp(topic, "net:clear-active-logins")) {
         mAuthCache.ClearAll();
         mPrivateAuthCache.ClearAll();
     } else if (!strcmp(topic, "net:prune-dead-connections")) {
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -445,17 +445,16 @@ private:
     // if true allow referrer headers between secure non-matching hosts
     bool           mSendSecureXSiteReferrer;
 
     // Persistent HTTPS caching flag
     bool           mEnablePersistentHttpsCaching;
 
     // For broadcasting tracking preference
     bool           mDoNotTrackEnabled;
-    uint8_t        mDoNotTrackValue;
 
     // for broadcasting safe hint;
     bool           mSafeHintEnabled;
     bool           mParentalControlEnabled;
 
     // Whether telemetry is reported or not
     uint32_t           mTelemetryEnabled : 1;
 
--- a/xpcom/threads/HangMonitor.cpp
+++ b/xpcom/threads/HangMonitor.cpp
@@ -584,26 +584,32 @@ Suspend()
     mozilla::BackgroundHangMonitor().NotifyWait();
   }
 }
 
 void
 RegisterAnnotator(Annotator& aAnnotator)
 {
 #ifdef REPORT_CHROME_HANGS
+  if (GeckoProcessType_Default != XRE_GetProcessType()) {
+    return;
+  }
   MonitorAutoLock lock(*gMonitor);
   MOZ_ASSERT(gAnnotators);
   gAnnotators->insert(&aAnnotator);
 #endif
 }
 
 void
 UnregisterAnnotator(Annotator& aAnnotator)
 {
 #ifdef REPORT_CHROME_HANGS
+  if (GeckoProcessType_Default != XRE_GetProcessType()) {
+    return;
+  }
   MonitorAutoLock lock(*gMonitor);
   MOZ_ASSERT(gAnnotators);
   gAnnotators->erase(&aAnnotator);
 #endif
 }
 
 } // namespace HangMonitor
 } // namespace mozilla