Merge mozilla-beta to b2g37. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 23 Feb 2015 18:52:38 -0500
changeset 237132 81bcdde1e783755010b61ff422d09645f006016d
parent 237125 d3c42189e867b6ca8b78f133552171a4f2313c0c (current diff)
parent 237131 192f6746dc457023a028a764fd8e1b53d1dd3b56 (diff)
child 237133 be644273958c54f9e45eec6bd7b4d627b3dd452a
push id211
push userryanvm@gmail.com
push dateMon, 23 Feb 2015 23:52:47 +0000
treeherdermozilla-b2g37_v2_2@81bcdde1e783 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone37.0
Merge mozilla-beta to b2g37. a=merge
--- a/browser/devtools/debugger/debugger-panes.js
+++ b/browser/devtools/debugger/debugger-panes.js
@@ -131,19 +131,18 @@ SourcesView.prototype = Heritage.extend(
    *
    * @param object aSource
    *        The source object coming from the active thread.
    * @param object aOptions [optional]
    *        Additional options for adding the source. Supported options:
    *        - staged: true to stage the item to be appended later
    */
   addSource: function(aSource, aOptions = {}) {
-    if (!(aSource.url || aSource.introductionUrl)) {
-      // These would be most likely eval scripts introduced in inline
-      // JavaScript in HTML, and we don't show those yet (bug 1097873)
+    if (!aSource.url) {
+      // We don't show any unnamed eval scripts yet (see bug 1124106)
       return;
     }
 
     let { label, group, unicodeUrl } = this._parseUrl(aSource);
 
     let contents = document.createElement("label");
     contents.className = "plain dbg-source-item";
     contents.setAttribute("value", label);
@@ -165,31 +164,20 @@ SourcesView.prototype = Heritage.extend(
         checkboxState: !aSource.isBlackBoxed,
         checkboxTooltip: this._blackBoxCheckboxTooltip,
         source: aSource
       }
     });
   },
 
   _parseUrl: function(aSource) {
-    let fullUrl = aSource.url || aSource.introductionUrl;
+    let fullUrl = aSource.url;
     let url = fullUrl.split(" -> ").pop();
     let label = aSource.addonPath ? aSource.addonPath : SourceUtils.getSourceLabel(url);
-    let group;
-
-    if (!aSource.url && aSource.introductionUrl) {
-      label += ' > ' + aSource.introductionType;
-      group = 'evals';
-    }
-    else if(aSource.addonID) {
-      group = aSource.addonID;
-    }
-    else {
-      group = SourceUtils.getSourceGroup(url);
-    }
+    let group = aSource.addonID ? aSource.addonID : SourceUtils.getSourceGroup(url);
 
     return {
       label: label,
       group: group,
       unicodeUrl: NetworkHelper.convertToUnicode(unescape(fullUrl))
     };
   },
 
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -401,17 +401,17 @@ skip-if = e10s && debug
 skip-if = e10s && debug
 [browser_dbg_source-maps-03.js]
 skip-if = e10s && debug
 [browser_dbg_source-maps-04.js]
 skip-if = e10s # Bug 1093535
 [browser_dbg_sources-cache.js]
 skip-if = e10s && debug
 [browser_dbg_sources-eval-01.js]
-skip-if = e10s && debug
+skip-if = true # non-named eval sources turned off for now, bug 1124106
 [browser_dbg_sources-eval-02.js]
 skip-if = e10s && debug
 [browser_dbg_sources-labels.js]
 skip-if = e10s && debug
 [browser_dbg_sources-sorting.js]
 skip-if = e10s && debug
 [browser_dbg_split-console-paused-reload.js]
 skip-if = e10s && debug
--- a/browser/devtools/debugger/test/browser_dbg_breakpoints-eval.js
+++ b/browser/devtools/debugger/test/browser_dbg_breakpoints-eval.js
@@ -23,24 +23,24 @@ function test() {
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function run() {
     return Task.spawn(function*() {
       let newSource = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.NEW_SOURCE);
-      callInTab(gTab, "evalSource");
+      callInTab(gTab, "evalSourceWithSourceURL");
       yield newSource;
 
-      yield gPanel.addBreakpoint({ actor: gSources.values[1], line: 2 });
+      yield gPanel.addBreakpoint({ actor: gSources.values[0], line: 2 });
       yield ensureThreadClientState(gPanel, "resumed");
 
       const paused = waitForThreadEvents(gPanel, "paused");
       callInTab(gTab, "bar");
       let frame = (yield paused).frame;
-      is(frame.where.source.actor, gSources.values[1], "Should have broken on the eval'ed source");
+      is(frame.where.source.actor, gSources.values[0], "Should have broken on the eval'ed source");
       is(frame.where.line, 2, "Should break on line 2");
 
       yield resumeDebuggerThenCloseAndFinish(gPanel);
     });
   }
 }
--- a/dom/bindings/test/mochitest.ini
+++ b/dom/bindings/test/mochitest.ini
@@ -51,8 +51,9 @@ skip-if = debug == false
 [test_throwing_method_noDCE.html]
 [test_treat_non_object_as_null.html]
 [test_traceProtos.html]
 [test_sequence_detection.html]
 skip-if = debug == false
 [test_exception_options_from_jsimplemented.html]
 skip-if = debug == false
 [test_worker_UnwrapArg.html]
+[test_crossOriginWindowSymbolAccess.html]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_crossOriginWindowSymbolAccess.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for accessing symbols on a cross-origin window</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="http://www1.w3c-test.org/common/blank.html"></iframe>
+<script>
+async_test(function (t) {
+  window.addEventListener("load", t.step_func(
+    function() {
+      assert_equals(document.querySelector("iframe").contentDocument, null, "Should have a crossorigin frame");
+      assert_throws(new Error(), function() {
+        frames[0][Symbol.iterator];
+      }, "Should throw exception on cross-origin Window symbol-named get");
+      assert_throws(new Error(), function() {
+        frames[0].location[Symbol.iterator];
+      }, "Should throw exception on cross-origin Location symbol-named get");
+      t.done();
+    }
+  ));
+}, "Check Symbol access on load");
+</script>
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -153,16 +153,26 @@ GetBackendName(mozilla::gfx::BackendType
       case mozilla::gfx::BackendType::DIRECT2D1_1:
         return "direct2d 1.1";
       case mozilla::gfx::BackendType::NONE:
         return "none";
   }
   MOZ_CRASH("Incomplete switch");
 }
 
+enum class DeviceResetReason
+{
+  OK = 0,
+  HUNG,
+  REMOVED,
+  RESET,
+  DRIVER_ERROR,
+  INVALID_CALL
+};
+
 class gfxPlatform {
 public:
     typedef mozilla::gfx::Color Color;
     typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
     typedef mozilla::gfx::DrawTarget DrawTarget;
     typedef mozilla::gfx::IntSize IntSize;
     typedef mozilla::gfx::SourceSurface SourceSurface;
 
@@ -427,17 +437,17 @@ public:
      * Whether to use the SIL Graphite rendering engine
      * (for fonts that include Graphite tables)
      */
     bool UseGraphiteShaping();
 
     // check whether format is supported on a platform or not (if unclear, returns true)
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) { return false; }
 
-    virtual bool DidRenderingDeviceReset() { return false; }
+    virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) { return false; }
 
     void GetPrefFonts(nsIAtom *aLanguage, nsString& array, bool aAppendUnicode = true);
 
     // in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
     void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
     
     /**
      * Iterate over pref fonts given a list of lang groups.  For a single lang
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -13,16 +13,17 @@
 #include "gfxWindowsSurface.h"
 
 #include "nsUnicharUtils.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
+#include "mozilla/Telemetry.h"
 
 #include "nsIWindowsRegKey.h"
 #include "nsIFile.h"
 #include "plbase64.h"
 #include "nsIXULRuntime.h"
 #include "imgLoader.h"
 
 #include "nsIGfxInfo.h"
@@ -459,17 +460,19 @@ gfxWindowsPlatform::GetDPIScale()
 
 void
 gfxWindowsPlatform::UpdateRenderMode()
 {
 /* Pick the default render mode for
  * desktop.
  */
     bool didReset = false;
-    if (DidRenderingDeviceReset()) {
+    DeviceResetReason resetReason = DeviceResetReason::OK;
+    if (DidRenderingDeviceReset(&resetReason)) {
+      Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
       mD3D11DeviceInitialized = false;
       mD3D11Device = nullptr;
       mD3D11ContentDevice = nullptr;
       mAdapter = nullptr;
 
       imgLoader::Singleton()->ClearCache(true);
       imgLoader::Singleton()->ClearCache(false);
       Factory::SetDirect3D11Device(nullptr);
@@ -1128,20 +1131,45 @@ gfxWindowsPlatform::IsFontFormatSupporte
         return false;
     }
 
     // no format hint set, need to look at data
     return true;
 }
 
 bool
-gfxWindowsPlatform::DidRenderingDeviceReset()
+gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason)
 {
+  if (aResetReason) {
+    *aResetReason = DeviceResetReason::OK;
+  }
+
   if (mD3D11Device) {
-    if (mD3D11Device->GetDeviceRemovedReason() != S_OK) {
+    HRESULT hr = mD3D11Device->GetDeviceRemovedReason();
+    if (hr != S_OK) {
+      if (aResetReason) {
+        switch (hr) {
+        case DXGI_ERROR_DEVICE_HUNG:
+          *aResetReason = DeviceResetReason::HUNG;
+          break;
+        case DXGI_ERROR_DEVICE_REMOVED:
+          *aResetReason = DeviceResetReason::REMOVED;
+          break;
+        case DXGI_ERROR_DEVICE_RESET:
+          *aResetReason = DeviceResetReason::RESET;
+          break;
+        case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
+          *aResetReason = DeviceResetReason::DRIVER_ERROR;
+          break;
+        case DXGI_ERROR_INVALID_CALL:
+          *aResetReason = DeviceResetReason::INVALID_CALL;
+        default:
+          MOZ_ASSERT(false);
+        }
+      }
       return true;
     }
   }
   if (mD3D11ContentDevice) {
     if (mD3D11ContentDevice->GetDeviceRemovedReason() != S_OK) {
       return true;
     }
   }
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -205,17 +205,17 @@ public:
                                            const uint8_t* aFontData,
                                            uint32_t aLength);
 
     /**
      * Check whether format is supported on a platform or not (if unclear, returns true)
      */
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags);
 
-    virtual bool DidRenderingDeviceReset();
+    virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr);
 
     /* Find a FontFamily/FontEntry object that represents a font on your system given a name */
     gfxFontFamily *FindFontFamily(const nsAString& aName);
     gfxFontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
 
     // ClearType is not always enabled even when available (e.g. Windows XP)
     // if either of these prefs are enabled and apply, use ClearType rendering
     bool UseClearTypeForDownloadableFonts();
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1742,17 +1742,18 @@ TypedObject::obj_lookupElement(JSContext
     return true;
 }
 
 static bool
 ReportPropertyError(JSContext *cx,
                     const unsigned errorNumber,
                     HandleId id)
 {
-    RootedString str(cx, IdToString(cx, id));
+    RootedValue idVal(cx, IdToValue(id));
+    RootedString str(cx, ValueToSource(cx, idVal));
     if (!str)
         return false;
 
     char *propName = JS_EncodeString(cx, str);
     if (!propName)
         return false;
 
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -137,17 +137,17 @@ MSG_DEF(JSMSG_NO_REST_NAME,            0
 MSG_DEF(JSMSG_PARAMETER_AFTER_REST,    0, JSEXN_SYNTAXERR, "parameter after rest parameter")
 MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
 
 // CSP
 MSG_DEF(JSMSG_CSP_BLOCKED_EVAL,        0, JSEXN_ERR, "call to eval() blocked by CSP")
 MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION,    0, JSEXN_ERR, "call to Function() blocked by CSP")
 
 // Wrappers
-MSG_DEF(JSMSG_ACCESSOR_DEF_DENIED,     1, JSEXN_ERR, "Permission denied to define accessor property '{0}'")
+MSG_DEF(JSMSG_ACCESSOR_DEF_DENIED,     1, JSEXN_ERR, "Permission denied to define accessor property {0}")
 MSG_DEF(JSMSG_DEAD_OBJECT,             0, JSEXN_TYPEERR, "can't access dead object")
 MSG_DEF(JSMSG_UNWRAP_DENIED,           0, JSEXN_ERR, "permission denied to unwrap object")
 
 // JSAPI-only (Not thrown as JS exceptions)
 MSG_DEF(JSMSG_BAD_CHAR,                1, JSEXN_INTERNALERR, "invalid format character {0}")
 MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE,  0, JSEXN_TYPEERR, "bad cloned function scope chain")
 MSG_DEF(JSMSG_BAD_NEW_RESULT,          1, JSEXN_TYPEERR, "invalid new expression result {0}")
 MSG_DEF(JSMSG_BAD_TYPE,                1, JSEXN_TYPEERR, "unknown type {0}")
@@ -341,17 +341,17 @@ MSG_DEF(JSMSG_CANT_REPORT_NEW,         0
 MSG_DEF(JSMSG_CANT_REPORT_NE_AS_NC,    0, JSEXN_TYPEERR, "proxy can't report a non-existent property as non-configurable")
 MSG_DEF(JSMSG_CANT_SET_NW_NC,          0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property")
 MSG_DEF(JSMSG_CANT_SET_WO_SETTER,      0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter")
 MSG_DEF(JSMSG_CANT_SKIP_NC,            0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property")
 MSG_DEF(JSMSG_INVALID_TRAP_RESULT,     2, JSEXN_TYPEERR, "trap {1} for {0} returned an invalid result")
 MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE,  0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property")
 MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED,   0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter")
 MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED,    0, JSEXN_ERR, "Permission denied to access object")
-MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED,  1, JSEXN_ERR, "Permission denied to access property '{0}'")
+MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED,  1, JSEXN_ERR, "Permission denied to access property {0}")
 MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT,  0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object")
 MSG_DEF(JSMSG_PROXY_EXTENSIBILITY,     0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target")
 MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined")
 MSG_DEF(JSMSG_PROXY_REVOKED,           0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy")
 
 // Structured cloning
 MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION,    0, JSEXN_ERR, "unsupported structured clone version")
 MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA,  1, JSEXN_INTERNALERR, "bad serialized structured data ({0})")
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -468,17 +468,18 @@ PropDesc::complete()
     }
 }
 
 bool
 js::Throw(JSContext *cx, jsid id, unsigned errorNumber)
 {
     MOZ_ASSERT(js_ErrorFormatString[errorNumber].argCount == 1);
 
-    JSString *idstr = IdToString(cx, id);
+    RootedValue idVal(cx, IdToValue(id));
+    JSString *idstr = ValueToSource(cx, idVal);
     if (!idstr)
        return false;
     JSAutoByteString bytes(cx, idstr);
     if (!bytes)
         return false;
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, errorNumber, bytes.ptr());
     return false;
 }
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -33,17 +33,21 @@ js::AutoEnterPolicy::reportErrorIfExcept
 {
     if (JS_IsExceptionPending(cx))
         return;
 
     if (JSID_IS_VOID(id)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_OBJECT_ACCESS_DENIED);
     } else {
-        JSString *str = IdToString(cx, id);
+        RootedValue idVal(cx, IdToValue(id));
+        JSString *str = ValueToSource(cx, idVal);
+        if (!str) {
+            return;
+        }
         AutoStableStringChars chars(cx);
         const char16_t *prop = nullptr;
         if (str->ensureFlat(cx) && chars.initTwoByte(cx, str))
             prop = chars.twoByteChars();
 
         JS_ReportErrorNumberUC(cx, js_GetErrorMessage, nullptr, JSMSG_PROPERTY_ACCESS_DENIED,
                                prop);
     }
--- a/js/src/proxy/SecurityWrapper.cpp
+++ b/js/src/proxy/SecurityWrapper.cpp
@@ -103,17 +103,20 @@ SecurityWrapper<Base>::boxedValue_unbox(
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper,
                                       HandleId id, MutableHandle<PropertyDescriptor> desc) const
 {
     if (desc.getter() || desc.setter()) {
-        JSString *str = IdToString(cx, id);
+        RootedValue idVal(cx, IdToValue(id));
+        JSString *str = ValueToSource(cx, idVal);
+        if (!str)
+            return false;
         AutoStableStringChars chars(cx);
         const char16_t *prop = nullptr;
         if (str->ensureFlat(cx) && chars.initTwoByte(cx, str))
             prop = chars.twoByteChars();
         JS_ReportErrorNumberUC(cx, js_GetErrorMessage, nullptr,
                                JSMSG_ACCESSOR_DEF_DENIED, prop);
         return false;
     }
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -171,16 +171,20 @@ public class Tab {
     public String getDisplayTitle() {
         if (mTitle != null && mTitle.length() > 0) {
             return mTitle;
         }
 
         return mUrl;
     }
 
+    /**
+     * Returns the base domain of the loaded uri. Note that if the page is
+     * a Reader mode uri, the base domain returned is that of the original uri.
+     */
     public String getBaseDomain() {
         return mBaseDomain;
     }
 
     public Bitmap getFavicon() {
         return mFavicon;
     }
 
--- a/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
+++ b/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
@@ -62,17 +62,17 @@
             android:persistent="false"
             android:title="@string/fxaccount_status_needs_finish_migrating" />
 
         <Preference
             android:editable="false"
             android:key="sync_now"
             android:defaultValue=""
             android:persistent="false"
-            android:title="Sync now"
+            android:title="@string/fxaccount_status_sync_now"
             android:summary="" />
 
         <CheckBoxPreference
             android:key="bookmarks"
             android:persistent="false"
             android:title="@string/fxaccount_status_bookmarks" />
         <CheckBoxPreference
             android:key="history"
--- a/mobile/android/base/toolbar/ToolbarDisplayLayout.java
+++ b/mobile/android/base/toolbar/ToolbarDisplayLayout.java
@@ -9,16 +9,17 @@ import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.List;
 
 import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.NewTabletUI;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.ReaderModeUtils;
 import org.mozilla.gecko.SiteIdentity;
 import org.mozilla.gecko.SiteIdentity.SecurityMode;
 import org.mozilla.gecko.SiteIdentity.MixedMode;
 import org.mozilla.gecko.SiteIdentity.TrackingMode;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.animation.PropertyAnimator;
 import org.mozilla.gecko.animation.ViewHelper;
 import org.mozilla.gecko.favicons.Favicons;
@@ -358,21 +359,24 @@ public class ToolbarDisplayLayout extend
         }
 
         // If the pref to show the title is set, use the tab's display title.
         if (!mPrefs.shouldShowUrl(mActivity) || url == null) {
             setTitle(tab.getDisplayTitle());
             return;
         }
 
-        CharSequence title = url;
+        String strippedURL = stripAboutReaderURL(url);
+
         if (mPrefs.shouldTrimUrls()) {
-            title = StringUtils.stripCommonSubdomains(StringUtils.stripScheme(url));
+            strippedURL = StringUtils.stripCommonSubdomains(StringUtils.stripScheme(strippedURL));
         }
 
+        CharSequence title = strippedURL;
+
         final String baseDomain = tab.getBaseDomain();
         if (!TextUtils.isEmpty(baseDomain)) {
             final SpannableStringBuilder builder = new SpannableStringBuilder(title);
 
             int index = title.toString().indexOf(baseDomain);
             if (index > -1) {
                 builder.setSpan(mUrlColor, 0, title.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                 builder.setSpan(tab.isPrivate() ? mPrivateDomainColor : mDomainColor,
@@ -380,16 +384,24 @@ public class ToolbarDisplayLayout extend
 
                 title = builder;
             }
         }
 
         setTitle(title);
     }
 
+    private String stripAboutReaderURL(final String url) {
+        if (!AboutPages.isAboutReader(url)) {
+            return url;
+        }
+
+        return ReaderModeUtils.getUrlFromAboutReader(url);
+    }
+
     private void updateFavicon(Tab tab) {
         if (NewTabletUI.isEnabled(getContext())) {
             // We don't display favicons in the toolbar for the new Tablet UI.
             return;
         }
 
         if (tab == null) {
             mFavicon.setImageDrawable(null);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -4420,17 +4420,21 @@ Tab.prototype = {
 
     // Reset state of click-to-play plugin notifications.
     clearTimeout(this.pluginDoorhangerTimeout);
     this.pluginDoorhangerTimeout = null;
     this.shouldShowPluginDoorhanger = true;
     this.clickToPlayPluginsActivated = false;
     // Borrowed from desktop Firefox: http://mxr.mozilla.org/mozilla-central/source/browser/base/content/urlbarBindings.xml#174
     let documentURI = contentWin.document.documentURIObject.spec
-    let matchedURL = documentURI.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
+
+    // If reader mode, get the base domain for the original url.
+    let strippedURI = this._stripAboutReaderURL(documentURI);
+
+    let matchedURL = strippedURI.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
     let baseDomain = "";
     if (matchedURL) {
       var domain = "";
       [, , domain] = matchedURL;
 
       try {
         baseDomain = Services.eTLD.getBaseDomainFromHost(domain);
         if (!domain.endsWith(baseDomain)) {
@@ -4478,16 +4482,29 @@ Tab.prototype = {
 
       this.contentDocumentIsDisplayed = false;
       this.hasTouchListener = false;
     } else {
       this.sendViewportUpdate();
     }
   },
 
+  _stripAboutReaderURL: function (url) {
+    if (!url.startsWith("about:reader")) {
+      return url;
+    }
+
+    // From ReaderParent._getOriginalUrl (browser/modules/ReaderParent.jsm).
+    let searchParams = new URLSearchParams(url.substring("about:reader?".length));
+    if (!searchParams.has("url")) {
+        return url;
+    }
+    return decodeURIComponent(searchParams.get("url"));
+  },
+
   // Properties used to cache security state used to update the UI
   _state: null,
   _hostChanged: false, // onLocationChange will flip this bit
 
   onSecurityChange: function(aWebProgress, aRequest, aState) {
     // Don't need to do anything if the data we use to update the UI hasn't changed
     if (this._state == aState && !this._hostChanged)
       return;
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -205,16 +205,22 @@
   },
   "CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 50,
     "description": "Time spent on one asynchronous SnowWhite freeing (ms)"
   },
+  "DEVICE_RESET_REASON": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 10,
+    "description": "GPU Device Reset Reason (ok, hung, removed, reset, internal error, invalid call)"
+  },
   "FORGET_SKIPPABLE_MAX": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 50,
     "description": "Max time spent on one forget skippable (ms)"
   },
   "GC_REASON_2": {