merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sun, 09 Apr 2017 20:32:42 +0200
changeset 559364 60fe200cb8dbd21695eae5775bec9305a9c900b6
parent 559349 f51bf8ee1e7b5be7442ae5fa57dd3f09699032ae (current diff)
parent 559363 0dbe18767bbf6fa8594aaba16df8472062a4e5c9 (diff)
child 559365 45692c884fdd5136a64fb2f8a61a0c8183b69331
child 562147 335e5d02ec76b4183383a1badfa1c691edda0693
child 562149 d7f6cb79c01991fcc362ea91ddba57cb9657aad1
push id53058
push userarchaeopteryx@coole-files.de
push dateSun, 09 Apr 2017 21:36:26 +0000
reviewersmerge, merge
milestone55.0a1
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: 3xAWLzLkoZ3
gfx/2d/InlineTranslator.cpp
gfx/2d/InlineTranslator.h
toolkit/components/social/test/xpcshell/.eslintrc.js
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -1,14 +1,41 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Document Navigation')
+
+with Files('crashtests/430628*'):
+    BUG_COMPONENT = ('Core', 'Editor')
+
+with Files('crashtests/432114*'):
+    BUG_COMPONENT = ('Core', 'Editor')
+
+with Files('crashtests/500328*'):
+    BUG_COMPONENT = ('Firefox', 'Bookmarks & History')
+
+with Files('IHistory.h'):
+    BUG_COMPONENT = ('Toolkit', 'Places')
+
+with Files('*LoadContext.*'):
+    BUG_COMPONENT = ('Core', 'Networking')
+
+with Files('nsAboutRedirector.*'):
+    BUG_COMPONENT = ('Core', 'General')
+
+with Files('nsILinkHandler.*'):
+    BUG_COMPONENT = ('Core', 'DOM: Core & HTML')
+
+with Files('nsIScrollObserver.*'):
+    BUG_COMPONENT = ('Core', 'Panning and Zooming')
+
 DIRS += [
     'timeline',
 ]
 
 XPIDL_SOURCES += [
     'nsCDefaultURIFixup.idl',
     'nsIClipboardCommands.idl',
     'nsIContentViewer.idl',
--- a/docshell/base/timeline/moz.build
+++ b/docshell/base/timeline/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'Developer Tools: Performance Tools (Profiler/Timeline)')
+
 EXPORTS.mozilla += [
     'AbstractTimelineMarker.h',
     'AutoGlobalTimelineMarker.h',
     'AutoTimelineMarker.h',
     'CompositeTimelineMarker.h',
     'ConsoleTimelineMarker.h',
     'DocLoadingTimelineMarker.h',
     'EventTimelineMarker.h',
--- a/docshell/moz.build
+++ b/docshell/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Document Navigation')
+
 DIRS += [
     'base',
     'shistory',
     'build',
     'resources/content',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += [
new file mode 100644
--- /dev/null
+++ b/docshell/test/moz.build
@@ -0,0 +1,146 @@
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Document Navigation')
+
+with Files('browser/*_bug234628*'):
+    BUG_COMPONENT = ('Core', 'Internationalization')
+
+with Files('browser/*_bug349769*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('browser/*_bug388121*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('browser/*_bug655270*'):
+    BUG_COMPONENT = ('Toolkit', 'Places')
+
+with Files('browser/*_bug655273*'):
+    BUG_COMPONENT = ('Firefox', 'Menus')
+
+with Files('browser/*_bug852909*'):
+    BUG_COMPONENT = ('Firefox', 'Menus')
+
+with Files('browser/*bug92473*'):
+    BUG_COMPONENT = ('Core', 'Internationalization')
+
+with Files('browser/*loadDisallowInherit*'):
+    BUG_COMPONENT = ('Firefox', 'Location Bar')
+
+with Files('browser/*tab_touch_events*'):
+    BUG_COMPONENT = ('Core', 'DOM: Events')
+
+with Files('browser/*timelineMarkers*'):
+    BUG_COMPONENT = ('Firefox', 'Developer Tools: Performance Tools (Profiler/Timeline)')
+
+with Files('browser/*ua_emulation*'):
+    BUG_COMPONENT = ('Firefox', 'Developer Tools')
+
+with Files('chrome/*112564*'):
+    BUG_COMPONENT = ('Core', 'Networking: HTTP')
+
+with Files('chrome/*303267*'):
+    BUG_COMPONENT = ('Core', 'DOM: Core & HTML')
+
+with Files('chrome/*453650*'):
+    BUG_COMPONENT = ('Core', 'Layout')
+
+with Files('chrome/*565388*'):
+    BUG_COMPONENT = ('Core', 'Widget')
+
+with Files('chrome/*582176*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('chrome/*608669*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('chrome/*690056*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('chrome/*92598*'):
+    BUG_COMPONENT = ('Core', 'Networking: HTTP')
+
+with Files('chrome/*private_hidden_window*'):
+    BUG_COMPONENT = ('Firefox', 'Private Browsing')
+
+
+with Files('iframesandbox/**'):
+    BUG_COMPONENT = ('Core', 'Security')
+
+with Files('iframesandbox/*marquee_event_handlers*'):
+    BUG_COMPONENT = ('Core', 'DOM: Security')
+
+
+with Files('navigation/*13871.html'):
+    BUG_COMPONENT = ('Core', 'Security')
+
+with Files('navigation/*386782*'):
+    BUG_COMPONENT = ('Core', 'Editor')
+
+with Files('navigation/*430624*'):
+    BUG_COMPONENT = ('Core', 'Editor')
+
+with Files('navigation/*430723*'):
+    BUG_COMPONENT = ('Core', 'Keyboard: Navigation')
+
+with Files('navigation/*child*'):
+    BUG_COMPONENT = ('Core', 'Security')
+
+with Files('navigation/*opener*'):
+    BUG_COMPONENT = ('Core', 'Security')
+
+with Files('navigation/*reserved*'):
+    BUG_COMPONENT = ('Core', 'Security')
+
+with Files('navigation/*triggering*'):
+    BUG_COMPONENT = ('Core', 'DOM: Security')
+
+
+with Files('unit/*442584*'):
+    BUG_COMPONENT = ('Core', 'Networking: Cache')
+
+with Files('unit/*setUsePrivateBrowsing*'):
+    BUG_COMPONENT = ('Firefox', 'Extension Compatibility')
+
+with Files('*1045096*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('*1151421*'):
+    BUG_COMPONENT = ('Core', 'DOM: Core & HTML')
+
+with Files('*369814*'):
+    BUG_COMPONENT = ('Core', 'Networking: JAR')
+
+with Files('*402210*'):
+    BUG_COMPONENT = ('Core', 'DOM: Security')
+
+with Files('*509055*'):
+    BUG_COMPONENT = ('Core', 'History: Global')
+
+with Files('*511449*'):
+    BUG_COMPONENT = ('Core', 'Widget: Cocoa')
+
+with Files('*551225*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('*570341*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('*580069*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('*637644*'):
+    BUG_COMPONENT = ('Core', 'DOM: Core & HTML')
+
+with Files('*640387*'):
+    BUG_COMPONENT = ('Core', 'DOM: Events')
+
+with Files('*668513*'):
+    BUG_COMPONENT = ('Core', 'DOM')
+
+with Files('*713825*'):
+    BUG_COMPONENT = ('Core', 'Internationalization')
+
+with Files('*797909*'):
+    BUG_COMPONENT = ('Core', 'DOM: Core & HTML')
+
+with Files('*forceinheritprincipal*'):
+    BUG_COMPONENT = ('Core', 'DOM: Security')
--- a/dom/base/WindowNamedPropertiesHandler.cpp
+++ b/dom/base/WindowNamedPropertiesHandler.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "WindowNamedPropertiesHandler.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/WindowBinding.h"
+#include "mozilla/Preferences.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMWindowList.h"
 #include "nsGlobalWindow.h"
 #include "nsHTMLDocument.h"
 #include "nsJSUtils.h"
 #include "xpcprivate.h"
 
@@ -233,20 +234,65 @@ WindowNamedPropertiesHandler::delete_(JS
                                       JS::Handle<JSObject*> aProxy,
                                       JS::Handle<jsid> aId,
                                       JS::ObjectOpResult &aResult) const
 {
   return aResult.failCantDeleteWindowNamedProperty();
 }
 
 static bool
+IsWebExtensionContentScript(JSContext* aCx)
+{
+  auto* priv = xpc::CompartmentPrivate::Get(JS::CurrentGlobalOrNull(aCx));
+  return priv->isWebExtensionContentScript;
+}
+
+static const int32_t kAlwaysAllowNamedPropertiesObject = 0;
+static const int32_t kDisallowNamedPropertiesObjectForContentScripts = 1;
+static const int32_t kDisallowNamedPropertiesObjectForXrays = 2;
+
+static bool
+AllowNamedPropertiesObject(JSContext* aCx)
+{
+  static int32_t sAllowed;
+  static bool sAllowedCached = false;
+  if (!sAllowedCached) {
+    Preferences::AddIntVarCache(&sAllowed,
+                                "dom.allow_named_properties_object_for_xrays",
+                                kDisallowNamedPropertiesObjectForContentScripts);
+    sAllowedCached = true;
+  }
+
+  if (sAllowed == kDisallowNamedPropertiesObjectForXrays) {
+    return false;
+  }
+
+  if (sAllowed == kAlwaysAllowNamedPropertiesObject) {
+    return true;
+  }
+
+  if (sAllowed == kDisallowNamedPropertiesObjectForContentScripts) {
+    return !IsWebExtensionContentScript(aCx);
+  }
+
+  NS_WARNING("Unknown value for dom.allow_named_properties_object_for_xrays");
+  // Fail open for now.
+  return true;
+}
+
+
+static bool
 ResolveWindowNamedProperty(JSContext* aCx, JS::Handle<JSObject*> aWrapper,
                            JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId,
                            JS::MutableHandle<JS::PropertyDescriptor> aDesc)
 {
+  if (!AllowNamedPropertiesObject(aCx)) {
+    return true;
+  }
+
   {
     JSAutoCompartment ac(aCx, aObj);
     if (!js::GetProxyHandler(aObj)->getOwnPropertyDescriptor(aCx, aObj, aId,
                                                              aDesc)) {
       return false;
     }
   }
 
@@ -259,16 +305,20 @@ ResolveWindowNamedProperty(JSContext* aC
   return true;
 }
 
 static bool
 EnumerateWindowNamedProperties(JSContext* aCx, JS::Handle<JSObject*> aWrapper,
                                JS::Handle<JSObject*> aObj,
                                JS::AutoIdVector& aProps)
 {
+  if (!AllowNamedPropertiesObject(aCx)) {
+    return true;
+  }
+
   JSAutoCompartment ac(aCx, aObj);
   return js::GetProxyHandler(aObj)->ownPropertyKeys(aCx, aObj, aProps);
 }
 
 const NativePropertyHooks sWindowNamedPropertiesNativePropertyHooks[] = { {
   ResolveWindowNamedProperty,
   EnumerateWindowNamedProperties,
   nullptr,
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -289,16 +289,19 @@ bool nsContentUtils::sIsFrameTimingPrefE
 bool nsContentUtils::sIsPerformanceTimingEnabled = false;
 bool nsContentUtils::sIsResourceTimingEnabled = false;
 bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
 bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
 bool nsContentUtils::sIsWebComponentsEnabled = false;
 bool nsContentUtils::sPrivacyResistFingerprinting = false;
 bool nsContentUtils::sSendPerformanceTimingNotifications = false;
 bool nsContentUtils::sUseActivityCursor = false;
+bool nsContentUtils::sAnimationsAPICoreEnabled = false;
+bool nsContentUtils::sAnimationsAPIElementAnimateEnabled = false;
+bool nsContentUtils::sGetBoxQuadsEnabled = false;
 
 int32_t nsContentUtils::sPrivacyMaxInnerWidth = 1000;
 int32_t nsContentUtils::sPrivacyMaxInnerHeight = 1000;
 
 uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
 
 uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
 uint32_t nsContentUtils::sCookiesBehavior = nsICookieService::BEHAVIOR_ACCEPT;
@@ -625,16 +628,25 @@ nsContentUtils::Init()
 #endif
 
   Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
                                "privacy.donottrackheader.enabled", false);
 
   Preferences::AddBoolVarCache(&sUseActivityCursor,
                                "ui.use_activity_cursor", false);
 
+  Preferences::AddBoolVarCache(&sAnimationsAPICoreEnabled,
+                               "dom.animations-api.core.enabled", false);
+
+  Preferences::AddBoolVarCache(&sAnimationsAPIElementAnimateEnabled,
+                               "dom.animations-api.element-animate.enabled", false);
+
+  Preferences::AddBoolVarCache(&sGetBoxQuadsEnabled,
+                               "layout.css.getBoxQuads.enabled", false);
+
   Element::InitCCCallbacks();
 
   nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
     do_GetService("@mozilla.org/uuid-generator;1", &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   uuidGenerator.forget(&sUUIDGenerator);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2142,16 +2142,40 @@ public:
    * Returns true if the browser should show busy cursor when loading page.
    */
   static bool UseActivityCursor()
   {
     return sUseActivityCursor;
   }
 
   /**
+   * Returns true if the DOM Animations API should be enabled.
+   */
+  static bool AnimationsAPICoreEnabled()
+  {
+    return sAnimationsAPICoreEnabled;
+  }
+
+  /*
+   * Returns true if the DOM Animations Element.animate() API should be enabled.
+   */
+  static bool AnimationsAPIElementAnimateEnabled()
+  {
+    return sAnimationsAPIElementAnimateEnabled;
+  }
+
+  /**
+   * Returns true if the getBoxQuads API should be enabled.
+   */
+  static bool GetBoxQuadsEnabled()
+  {
+    return sGetBoxQuadsEnabled;
+  }
+
+  /**
    * Return true if this doc is controlled by a ServiceWorker.
    */
   static bool IsControlledByServiceWorker(nsIDocument* aDocument);
 
   /**
    * Fire mutation events for changes caused by parsing directly into a
    * context node.
    *
@@ -2942,16 +2966,19 @@ private:
   static bool sIsResourceTimingEnabled;
   static bool sIsUserTimingLoggingEnabled;
   static bool sIsFrameTimingPrefEnabled;
   static bool sIsExperimentalAutocompleteEnabled;
   static bool sIsWebComponentsEnabled;
   static bool sPrivacyResistFingerprinting;
   static bool sSendPerformanceTimingNotifications;
   static bool sUseActivityCursor;
+  static bool sAnimationsAPICoreEnabled;
+  static bool sAnimationsAPIElementAnimateEnabled;
+  static bool sGetBoxQuadsEnabled;
   static uint32_t sCookiesLifetimePolicy;
   static uint32_t sCookiesBehavior;
 
   static int32_t sPrivacyMaxInnerWidth;
   static int32_t sPrivacyMaxInnerHeight;
 
   static nsHtml5StringParser* sHTMLFragmentParser;
   static nsIParser* sXMLFragmentParser;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3157,27 +3157,27 @@ nsDocument::GetAllowPlugins()
 }
 
 bool
 nsDocument::IsElementAnimateEnabled(JSContext* aCx, JSObject* /*unused*/)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
-         Preferences::GetBool("dom.animations-api.core.enabled") ||
-         Preferences::GetBool("dom.animations-api.element-animate.enabled");
+         nsContentUtils::AnimationsAPICoreEnabled() ||
+         nsContentUtils::AnimationsAPIElementAnimateEnabled();
 }
 
 bool
 nsDocument::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
-         Preferences::GetBool("dom.animations-api.core.enabled");
+         nsContentUtils::AnimationsAPICoreEnabled();
 }
 
 DocumentTimeline*
 nsDocument::Timeline()
 {
   if (!mDocumentTimeline) {
     mDocumentTimeline = new DocumentTimeline(this, TimeDuration(0));
   }
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -2979,17 +2979,17 @@ nsINode::GetParentElementCrossingShadowR
 
   return nullptr;
 }
 
 bool
 nsINode::HasBoxQuadsSupport(JSContext* aCx, JSObject* /* unused */)
 {
   return xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx)) ||
-         Preferences::GetBool("layout.css.getBoxQuads.enabled");
+         nsContentUtils::GetBoxQuadsEnabled();
 }
 
 nsINode*
 nsINode::GetScopeChainParent() const
 {
   return nullptr;
 }
 
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -897,26 +897,37 @@ TrackBuffersManager::AppendDataToCurrent
   mCurrentInputBuffer->AppendData(aData);
   mInputDemuxer->NotifyDataArrived();
 }
 
 void
 TrackBuffersManager::InitializationSegmentReceived()
 {
   MOZ_ASSERT(mParser->HasCompleteInitData());
+
+  int64_t endInit = mParser->InitSegmentRange().mEnd;
+  if (mInputBuffer->Length() > mProcessedInput ||
+      int64_t(mProcessedInput - mInputBuffer->Length()) > endInit) {
+    // Something is not quite right with the data appended. Refuse it.
+    RejectAppend(MediaResult(NS_ERROR_FAILURE,
+                             "Invalid state following initialization segment"),
+                 __func__);
+    return;
+  }
+
   mCurrentInputBuffer = new SourceBufferResource(mType);
   // The demuxer isn't initialized yet ; we don't want to notify it
   // that data has been appended yet ; so we simply append the init segment
   // to the resource.
   mCurrentInputBuffer->AppendData(mParser->InitData());
-  uint32_t length =
-    mParser->InitSegmentRange().mEnd - (mProcessedInput - mInputBuffer->Length());
+  uint32_t length = endInit - (mProcessedInput - mInputBuffer->Length());
   if (mInputBuffer->Length() == length) {
     mInputBuffer = nullptr;
   } else {
+    MOZ_RELEASE_ASSERT(length <= mInputBuffer->Length());
     mInputBuffer->RemoveElementsAt(0, length);
   }
   CreateDemuxerforMIMEType();
   if (!mInputDemuxer) {
     NS_WARNING("TODO type not supported");
     RejectAppend(NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
     return;
   }
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -229,17 +229,17 @@ private:
   // Temporary input buffer to handle partial media segment header.
   // We store the current input buffer content into it should we need to
   // reinitialize the demuxer once we have some samples and a discontinuity is
   // detected.
   RefPtr<MediaByteBuffer> mPendingInputBuffer;
   RefPtr<SourceBufferResource> mCurrentInputBuffer;
   RefPtr<MediaDataDemuxer> mInputDemuxer;
   // Length already processed in current media segment.
-  uint32_t mProcessedInput;
+  uint64_t mProcessedInput;
   Maybe<media::TimeUnit> mLastParsedEndTime;
 
   void OnDemuxerInitDone(nsresult);
   void OnDemuxerInitFailed(const MediaResult& aFailure);
   void OnDemuxerResetDone(nsresult);
   MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
 
   void OnDemuxFailed(TrackType aTrack, const MediaResult& aError);
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -249,17 +249,17 @@ skip-if = toolkit == 'android' # Times o
 [test_subframe_run_js_if_allowed.html]
 [test_leading_wildcard.html]
 [test_multi_policy_injection_bypass.html]
 [test_null_baseuri.html]
 [test_referrerdirective.html]
 [test_dual_header.html]
 [test_upgrade_insecure.html]
 # no ssl support as well as websocket tests do not work (see test_websocket.html)
-skip-if = toolkit == 'android'
+skip-if = (toolkit == 'android') || (os != 'linux' && !debug) # Bug 1183300
 [test_upgrade_insecure_reporting.html]
 skip-if = toolkit == 'android'
 [test_upgrade_insecure_referrer.html]
 skip-if = toolkit == 'android'
 [test_upgrade_insecure_cors.html]
 skip-if = toolkit == 'android'
 [test_report_for_import.html]
 [test_blocked_uri_in_reports.html]
--- a/gfx/2d/DrawTargetRecording.cpp
+++ b/gfx/2d/DrawTargetRecording.cpp
@@ -70,16 +70,41 @@ EnsureSurfaceStored(DrawEventRecorderPri
   RecordingSourceSurfaceUserData *userData = new RecordingSourceSurfaceUserData;
   userData->refPtr = aSurface;
   userData->recorder = aRecorder;
   aSurface->AddUserData(reinterpret_cast<UserDataKey*>(aRecorder),
                         userData, &RecordingSourceSurfaceUserDataFunc);
   return;
 }
 
+class SourceSurfaceRecording : public SourceSurface
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording)
+  SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder)
+    : mFinalSurface(aFinalSurface), mRecorder(aRecorder)
+  {
+    mRecorder->AddStoredObject(this);
+  }
+
+  ~SourceSurfaceRecording()
+  {
+    mRecorder->RemoveStoredObject(this);
+    mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
+  }
+
+  virtual SurfaceType GetType() const { return SurfaceType::RECORDING; }
+  virtual IntSize GetSize() const { return mFinalSurface->GetSize(); }
+  virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); }
+  virtual already_AddRefed<DataSourceSurface> GetDataSurface() { return mFinalSurface->GetDataSurface(); }
+
+  RefPtr<SourceSurface> mFinalSurface;
+  RefPtr<DrawEventRecorderPrivate> mRecorder;
+};
+
 class GradientStopsRecording : public GradientStops
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording)
   GradientStopsRecording(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder)
     : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder)
   {
     mRecorder->AddStoredObject(this);
--- a/gfx/2d/DrawTargetRecording.h
+++ b/gfx/2d/DrawTargetRecording.h
@@ -326,37 +326,12 @@ private:
   Path *GetPathForPathRecording(const Path *aPath) const;
   already_AddRefed<PathRecording> EnsurePathStored(const Path *aPath);
   void EnsurePatternDependenciesStored(const Pattern &aPattern);
 
   RefPtr<DrawEventRecorderPrivate> mRecorder;
   RefPtr<DrawTarget> mFinalDT;
 };
 
-class SourceSurfaceRecording : public SourceSurface
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording)
-  SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder)
-    : mFinalSurface(aFinalSurface), mRecorder(aRecorder)
-  {
-    mRecorder->AddStoredObject(this);
-  }
-
-  ~SourceSurfaceRecording()
-  {
-    mRecorder->RemoveStoredObject(this);
-    mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
-  }
-
-  virtual SurfaceType GetType() const { return SurfaceType::RECORDING; }
-  virtual IntSize GetSize() const { return mFinalSurface->GetSize(); }
-  virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); }
-  virtual already_AddRefed<DataSourceSurface> GetDataSurface() { return mFinalSurface->GetDataSurface(); }
-
-  RefPtr<SourceSurface> mFinalSurface;
-  RefPtr<DrawEventRecorderPrivate> mRecorder;
-};
-
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_DRAWTARGETRECORDING_H_ */
deleted file mode 100644
--- a/gfx/2d/InlineTranslator.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#include "InlineTranslator.h"
-
-#include "gfxContext.h"
-#include "nsDeviceContext.h"
-#include "mozilla/gfx/RecordedEvent.h"
-#include "mozilla/gfx/RecordingTypes.h"
-#include "mozilla/UniquePtr.h"
-
-using namespace mozilla::gfx;
-
-namespace mozilla {
-namespace gfx {
-
-InlineTranslator::InlineTranslator(DrawTarget* aDT, Matrix aMatrix)
-{
-  mBaseDT = aDT;
-  mBaseTransform = aMatrix;
-}
-
-bool
-InlineTranslator::TranslateRecording(std::istream& aRecording)
-{
-  uint32_t magicInt;
-  ReadElement(aRecording, magicInt);
-  if (magicInt != mozilla::gfx::kMagicInt) {
-    return false;
-  }
-
-  uint16_t majorRevision;
-  ReadElement(aRecording, majorRevision);
-  if (majorRevision != kMajorRevision) {
-    return false;
-  }
-
-  uint16_t minorRevision;
-  ReadElement(aRecording, minorRevision);
-  if (minorRevision > kMinorRevision) {
-    return false;
-  }
-
-  int32_t eventType;
-  ReadElement(aRecording, eventType);
-  while (aRecording.good()) {
-    UniquePtr<RecordedEvent> recordedEvent(
-      RecordedEvent::LoadEventFromStream(aRecording,
-      static_cast<RecordedEvent::EventType>(eventType)));
-
-    // Make sure that the whole event was read from the stream successfully.
-    if (!aRecording.good() || !recordedEvent) {
-      return false;
-    }
-
-    if (recordedEvent->GetType() == RecordedEvent::SETTRANSFORM) {
-      RecordedSetTransform* event = static_cast<RecordedSetTransform*>(recordedEvent.get());
-      mBaseDT->SetTransform(event->mTransform * mBaseTransform);
-    } else {
-      if (!recordedEvent->PlayEvent(this)) {
-        return false;
-      }
-    }
-
-    ReadElement(aRecording, eventType);
-  }
-
-  return true;
-}
-
-already_AddRefed<DrawTarget>
-InlineTranslator::CreateDrawTarget(ReferencePtr aRefPtr,
-                                  const gfx::IntSize &aSize,
-                                  gfx::SurfaceFormat aFormat)
-{
-  RefPtr<DrawTarget> drawTarget = mBaseDT;
-  return drawTarget.forget();
-}
-
-FontType
-InlineTranslator::GetDesiredFontType()
-{
-  switch (mBaseDT->GetBackendType()) {
-    case BackendType::DIRECT2D:
-      return FontType::DWRITE;
-    case BackendType::CAIRO:
-      return FontType::CAIRO;
-    case BackendType::SKIA:
-      return FontType::SKIA;
-    default:
-      return FontType::CAIRO;
-  }
-}
-
-} // namespace gfx
-} // namespace mozilla
deleted file mode 100644
--- a/gfx/2d/InlineTranslator.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#ifndef mozilla_layout_InlineTranslator_h
-#define mozilla_layout_InlineTranslator_h
-
-#include <istream>
-
-#include "mozilla/gfx/2D.h"
-#include "mozilla/gfx/Filters.h"
-#include "mozilla/gfx/RecordedEvent.h"
-#include "nsRefPtrHashtable.h"
-
-namespace mozilla {
-namespace gfx {
-
-using gfx::Translator;
-using gfx::ReferencePtr;
-using gfx::DrawTarget;
-using gfx::Path;
-using gfx::SourceSurface;
-using gfx::FilterNode;
-using gfx::GradientStops;
-using gfx::ScaledFont;
-using gfx::NativeFontResource;
-
-class InlineTranslator final : public Translator
-{
-public:
-  explicit InlineTranslator(DrawTarget* aDT, Matrix aMatrix);
-
-  bool TranslateRecording(std::istream& aRecording);
-
-  DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final
-  {
-    return mBaseDT;
-  }
-
-  Path* LookupPath(ReferencePtr aRefPtr) final
-  {
-    Path* result = mPaths.GetWeak(aRefPtr);
-    MOZ_ASSERT(result);
-    return result;
-  }
-
-  SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) final
-  {
-    SourceSurface* result = mSourceSurfaces.GetWeak(aRefPtr);
-    MOZ_ASSERT(result);
-    return result;
-  }
-
-  FilterNode* LookupFilterNode(ReferencePtr aRefPtr) final
-  {
-    FilterNode* result = mFilterNodes.GetWeak(aRefPtr);
-    MOZ_ASSERT(result);
-    return result;
-  }
-
-  GradientStops* LookupGradientStops(ReferencePtr aRefPtr) final
-  {
-    GradientStops* result =  mGradientStops.GetWeak(aRefPtr);
-    MOZ_ASSERT(result);
-    return result;
-  }
-
-  ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final
-  {
-    ScaledFont* result = mScaledFonts.GetWeak(aRefPtr);
-    MOZ_ASSERT(result);
-    return result;
-  }
-
-  NativeFontResource* LookupNativeFontResource(uint64_t aKey) final
-  {
-    NativeFontResource* result = mNativeFontResources.GetWeak(aKey);
-    MOZ_ASSERT(result);
-    return result;
-  }
-
-  void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final { }
-
-  void AddPath(ReferencePtr aRefPtr, Path *aPath) final
-  {
-    mPaths.Put(aRefPtr, aPath);
-  }
-
-  void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aSurface) final
-  {
-    mSourceSurfaces.Put(aRefPtr, aSurface);
-  }
-
-  void AddFilterNode(ReferencePtr aRefPtr, FilterNode *aFilter) final
-  {
-    mFilterNodes.Put(aRefPtr, aFilter);
-  }
-
-  void AddGradientStops(ReferencePtr aRefPtr, GradientStops *aStops) final
-  {
-    mGradientStops.Put(aRefPtr, aStops);
-  }
-
-  void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) final
-  {
-    mScaledFonts.Put(aRefPtr, aScaledFont);
-  }
-
-  void AddNativeFontResource(uint64_t aKey,
-                             NativeFontResource *aScaledFontResouce) final
-  {
-    mNativeFontResources.Put(aKey, aScaledFontResouce);
-  }
-
-  void RemoveDrawTarget(ReferencePtr aRefPtr) final { }
-
-  void RemovePath(ReferencePtr aRefPtr) final
-  {
-    mPaths.Remove(aRefPtr);
-  }
-
-  void RemoveSourceSurface(ReferencePtr aRefPtr) final
-  {
-    mSourceSurfaces.Remove(aRefPtr);
-  }
-
-  void RemoveFilterNode(ReferencePtr aRefPtr) final
-  {
-    mFilterNodes.Remove(aRefPtr);
-  }
-
-  void RemoveGradientStops(ReferencePtr aRefPtr) final
-  {
-    mGradientStops.Remove(aRefPtr);
-  }
-
-  void RemoveScaledFont(ReferencePtr aRefPtr) final
-  {
-    mScaledFonts.Remove(aRefPtr);
-  }
-
-  already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
-                                                const gfx::IntSize &aSize,
-                                                gfx::SurfaceFormat aFormat) final;
-
-  mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
-
-  mozilla::gfx::FontType GetDesiredFontType() final;
-
-private:
-  RefPtr<DrawTarget> mBaseDT;
-  Matrix             mBaseTransform;
-
-  nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
-  nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
-  nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
-  nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
-  nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
-  nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif // mozilla_layout_InlineTranslator_h
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -694,22 +694,22 @@ public:
   }
 
   virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SetTransform"; }
-
-  Matrix mTransform;
 private:
   friend class RecordedEvent;
 
    MOZ_IMPLICIT RecordedSetTransform(std::istream &aStream);
+
+  Matrix mTransform;
 };
 
 class RecordedDrawSurface : public RecordedDrawingEvent {
 public:
   RecordedDrawSurface(DrawTarget *aDT, ReferencePtr aRefSource, const Rect &aDest,
                       const Rect &aSource, const DrawSurfaceOptions &aDSOptions,
                       const DrawOptions &aOptions)
     : RecordedDrawingEvent(DRAWSURFACE, aDT), mRefSource(aRefSource), mDest(aDest)
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -19,22 +19,20 @@ EXPORTS.mozilla.gfx += [
     'BaseSize.h',
     'BezierUtils.h',
     'Blur.h',
     'BorrowedContext.h',
     'Coord.h',
     'CriticalSection.h',
     'DataSurfaceHelpers.h',
     'DrawEventRecorder.h',
-    'DrawTargetRecording.h',
     'DrawTargetTiled.h',
     'Filters.h',
     'Helpers.h',
     'HelpersCairo.h',
-    'InlineTranslator.h',
     'IterableArena.h',
     'JobScheduler.h',
     'JobScheduler_posix.h',
     'JobScheduler_win32.h',
     'Logging.h',
     'LoggingConstants.h',
     'Matrix.h',
     'MatrixFwd.h',
@@ -190,17 +188,16 @@ UNIFIED_SOURCES += [
     'SFNTNameTable.cpp',
     'SourceSurfaceCairo.cpp',
     'SourceSurfaceRawData.cpp',
     'Swizzle.cpp',
 ]
 
 SOURCES += [
     'Factory.cpp', # Need to suppress warnings in Skia header files.
-    'InlineTranslator.cpp',
 ]
 
 if CONFIG['CLANG_CXX']:
     SOURCES['Factory.cpp'].flags += ['-Wno-implicit-fallthrough']
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
 
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -105,18 +105,18 @@ BasicCanvasLayer::Paint(DrawTarget* aDT,
   }
 
   const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
 
   Matrix oldTM;
   if (needsYFlip) {
     oldTM = aDT->GetTransform();
     aDT->SetTransform(Matrix(oldTM).
-                      PreTranslate(0.0f, mBounds.height).
-                      PreScale(1.0f, -1.0f));
+                        PreTranslate(0.0f, mBounds.height).
+                        PreScale(1.0f, -1.0f));
   }
 
   FillRectWithMask(aDT, aDeviceOffset,
                    Rect(0, 0, mBounds.width, mBounds.height),
                    surface, mSamplingFilter,
                    DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
                    aMaskLayer);
 
--- a/gfx/layers/basic/BasicLayersImpl.cpp
+++ b/gfx/layers/basic/BasicLayersImpl.cpp
@@ -7,18 +7,16 @@
 #include <new>                          // for operator new
 #include "Layers.h"                     // for Layer, etc
 #include "basic/BasicImplData.h"        // for BasicImplData
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "AutoMaskData.h"
-#include "mozilla/gfx/InlineTranslator.h"
-#include "mozilla/gfx/DrawTargetRecording.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 bool
 GetMaskData(Layer* aMaskLayer,
@@ -119,19 +117,16 @@ FillRectWithMask(DrawTarget* aDT,
                  SourceSurface* aSurface,
                  SamplingFilter aSamplingFilter,
                  const DrawOptions& aOptions,
                  ExtendMode aExtendMode,
                  SourceSurface* aMaskSource,
                  const Matrix* aMaskTransform,
                  const Matrix* aSurfaceTransform)
 {
-  MOZ_ASSERT(!aMaskSource || (aMaskSource && aMaskTransform),
-             "aMaskSource must not be passed without a transform");
-
   if (aMaskSource && aMaskTransform) {
     aDT->PushClipRect(aRect);
     Matrix oldTransform = aDT->GetTransform();
 
     Matrix inverseMask = *aMaskTransform;
     inverseMask.Invert();
 
     Matrix transform = oldTransform * inverseMask;
@@ -144,39 +139,16 @@ FillRectWithMask(DrawTarget* aDT,
     aDT->SetTransform(*aMaskTransform);
     aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions);
 
     aDT->SetTransform(oldTransform);
     aDT->PopClip();
     return;
   }
 
-  if (aSurface->GetType() == SurfaceType::RECORDING) {
-    MOZ_ASSERT(aOptions.mAlpha == 1.0 &&
-               aOptions.mCompositionOp == CompositionOp::OP_OVER);
-
-    aDT->PushClipRect(aRect);
-    Matrix oldTransform = aDT->GetTransform();
-
-    Matrix transform = oldTransform;
-    if (aSurfaceTransform) {
-      transform = (*aSurfaceTransform) * transform;
-    }
-
-    InlineTranslator* translator = new InlineTranslator(aDT, transform);
-    SourceSurfaceRecording* ss = static_cast<SourceSurfaceRecording*>(aSurface);
-    DrawEventRecorderMemory* mr = static_cast<DrawEventRecorderMemory*>(ss->mRecorder.get());
-
-    translator->TranslateRecording(mr->GetInputStream());
-
-    aDT->SetTransform(oldTransform);
-    aDT->PopClip();
-    return;
-  }
-
   aDT->FillRect(aRect,
                 SurfacePattern(aSurface, aExtendMode,
                                aSurfaceTransform ? (*aSurfaceTransform) : Matrix(),
                                aSamplingFilter), aOptions);
 }
 
 void
 FillRectWithMask(DrawTarget* aDT,
--- a/image/test/mochitest/mochitest.ini
+++ b/image/test/mochitest/mochitest.ini
@@ -126,17 +126,16 @@ skip-if = os == 'android'
 [test_bug1217571.html]
 [test_bullet_animation.html]
 skip-if = os == 'android'
 [test_changeOfSource.html]
 skip-if = os == 'android'
 [test_changeOfSource2.html]
 skip-if = os == 'android'
 [test_discardAnimatedImage.html]
-disabled = bug 1354499
 [test_drawDiscardedImage.html]
 [test_error_events.html]
 [test_image_crossorigin_data_url.html]
 [test_ImageContentLoaded.html]
 [test_has_transparency.html]
 skip-if = os == 'android'
 [test_net_failedtoprocess.html]
 skip-if = os == 'android'
--- a/js/src/gc/Tracer.cpp
+++ b/js/src/gc/Tracer.cpp
@@ -284,16 +284,47 @@ CountDecimalDigits(size_t num)
     do {
         num /= 10;
         numDigits++;
     } while (num > 0);
 
     return numDigits;
 }
 
+static const char*
+StringKindHeader(JSString* str)
+{
+    MOZ_ASSERT(str->isLinear());
+
+    if (str->isAtom()) {
+        if (str->isPermanentAtom())
+            return "permanent atom: ";
+        return "atom: ";
+    }
+
+    if (str->isFlat()) {
+        if (str->isExtensible())
+            return "extensible: ";
+        if (str->isUndepended())
+            return "undepended: ";
+        if (str->isInline()) {
+            if (str->isFatInline())
+                return "fat inline: ";
+            return "inline: ";
+        }
+        return "flat: ";
+    }
+
+    if (str->isDependent())
+        return "dependent: ";
+    if (str->isExternal())
+        return "external: ";
+    return "linear: ";
+}
+
 JS_PUBLIC_API(void)
 JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, void* thing,
                      JS::TraceKind kind, bool details)
 {
     const char* name = nullptr; /* silence uninitialized warning */
     size_t n;
 
     if (bufsize == 0)
@@ -382,22 +413,23 @@ JS_GetTraceThingInfo(char* buf, size_t b
 
           case JS::TraceKind::String:
           {
             *buf++ = ' ';
             bufsize--;
             JSString* str = (JSString*)thing;
 
             if (str->isLinear()) {
-                bool willFit = str->length() + strlen("<length > ") +
+                const char* header = StringKindHeader(str);
+                bool willFit = str->length() + strlen("<length > ") + strlen(header) +
                                CountDecimalDigits(str->length()) < bufsize;
 
-                n = snprintf(buf, bufsize, "<length %" PRIuSIZE "%s> ",
-                                str->length(),
-                                willFit ? "" : " (truncated)");
+                n = snprintf(buf, bufsize, "<%slength %" PRIuSIZE "%s> ",
+                             header, str->length(),
+                             willFit ? "" : " (truncated)");
                 buf += n;
                 bufsize -= n;
 
                 PutEscapedString(buf, bufsize, &str->asLinear(), 0);
             } else {
                 snprintf(buf, bufsize, "<rope: length %" PRIuSIZE ">", str->length());
             }
             break;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/inlining/call-apply-non-singletons.js
@@ -0,0 +1,22 @@
+var arr1 = [];
+var arr2 = [];
+for (let i = 0; i < 10; i++) {
+    arr1.push(function f(x) {
+        if (x === 350)
+            bailout();
+        assertEq(f, arr1[i]);
+        return x + i;
+    });
+    arr2.push(function() {
+        return arr1[i].apply(null, arguments);
+    });
+}
+
+function test() {
+    for (var i = 0; i < 400; i++) {
+        for (var j = 0; j < arr2.length; j++) {
+            assertEq(arr2[j].call(null, i), i + j);
+        }
+    }
+}
+test();
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -253,21 +253,27 @@ IonBuilder::spew(const char* message)
 }
 
 JSFunction*
 IonBuilder::getSingleCallTarget(TemporaryTypeSet* calleeTypes)
 {
     if (!calleeTypes)
         return nullptr;
 
-    JSObject* obj = calleeTypes->maybeSingleton();
-    if (!obj || !obj->is<JSFunction>())
+    TemporaryTypeSet::ObjectKey* key = calleeTypes->maybeSingleObject();
+    if (!key || key->clasp() != &JSFunction::class_)
         return nullptr;
 
-    return &obj->as<JSFunction>();
+    if (key->isSingleton())
+        return &key->singleton()->as<JSFunction>();
+
+    if (JSFunction* fun = key->group()->maybeInterpretedFunction())
+        return fun;
+
+    return nullptr;
 }
 
 AbortReasonOr<Ok>
 IonBuilder::getPolyCallTargets(TemporaryTypeSet* calleeTypes, bool constructing,
                                ObjectVector& targets, uint32_t maxTargets)
 {
     MOZ_ASSERT(targets.empty());
 
@@ -5488,21 +5494,21 @@ IonBuilder::jsop_eval(uint32_t argc)
     int calleeDepth = -((int)argc + 2);
     TemporaryTypeSet* calleeTypes = current->peek(calleeDepth)->resultTypeSet();
 
     // Emit a normal call if the eval has never executed. This keeps us from
     // disabling compilation for the script when testing with --ion-eager.
     if (calleeTypes && calleeTypes->empty())
         return jsop_call(argc, /* constructing = */ false, false);
 
-    JSFunction* singleton = getSingleCallTarget(calleeTypes);
-    if (!singleton)
-        return abort(AbortReason::Disable, "No singleton callee for eval()");
-
-    if (script()->global().valueIsEval(ObjectValue(*singleton))) {
+    JSFunction* target = getSingleCallTarget(calleeTypes);
+    if (!target)
+        return abort(AbortReason::Disable, "No single callee for eval()");
+
+    if (script()->global().valueIsEval(ObjectValue(*target))) {
         if (argc != 1)
             return abort(AbortReason::Disable, "Direct eval with more than one argument");
 
         if (!info().funMaybeLazy())
             return abort(AbortReason::Disable, "Direct eval in global code");
 
         if (info().funMaybeLazy()->isArrow())
             return abort(AbortReason::Disable, "Direct eval from arrow function");
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -1749,16 +1749,25 @@ JSObject*
 TemporaryTypeSet::maybeSingleton()
 {
     if (baseFlags() != 0 || baseObjectCount() != 1)
         return nullptr;
 
     return getSingleton(0);
 }
 
+TemporaryTypeSet::ObjectKey*
+TemporaryTypeSet::maybeSingleObject()
+{
+    if (baseFlags() != 0 || baseObjectCount() != 1)
+        return nullptr;
+
+    return getObject(0);
+}
+
 JSObject*
 HeapTypeSetKey::singleton(CompilerConstraintList* constraints)
 {
     HeapTypeSet* types = maybeTypes();
 
     if (!types || types->nonDataProperty() || types->baseFlags() != 0 || types->getObjectCount() != 1)
         return nullptr;
 
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -829,16 +829,17 @@ class TemporaryTypeSet : public TypeSet
     /* Whether clasp->isCallable() is true for one or more objects in this set. */
     bool maybeCallable(CompilerConstraintList* constraints);
 
     /* Whether clasp->emulatesUndefined() is true for one or more objects in this set. */
     bool maybeEmulatesUndefined(CompilerConstraintList* constraints);
 
     /* Get the single value which can appear in this type set, otherwise nullptr. */
     JSObject* maybeSingleton();
+    ObjectKey* maybeSingleObject();
 
     /* Whether any objects in the type set needs a barrier on id. */
     bool propertyNeedsBarrier(CompilerConstraintList* constraints, jsid id);
 
     /*
      * Whether this set contains all types in other, except (possibly) the
      * specified type.
      */
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_xray_named_element_access.js
@@ -0,0 +1,40 @@
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=1273251
+"use strict"
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+const XRAY_PREF = "dom.allow_named_properties_object_for_xrays";
+
+add_task(function*() {
+  let webnav = Services.appShell.createWindowlessBrowser(false);
+
+  let docShell = webnav.QueryInterface(Ci.nsIInterfaceRequestor)
+                       .getInterface(Ci.nsIDocShell);
+
+  docShell.createAboutBlankContentViewer(null);
+
+  let window = webnav.getInterface(Ci.nsIDOMWindow);
+  let unwrapped = Cu.waiveXrays(window);
+
+  window.document.body.innerHTML = '<div id="foo"></div>';
+
+  equal(Preferences.get(XRAY_PREF), 1, "Should have pref=1 by default");
+
+  Preferences.set(XRAY_PREF, 0);
+  equal(typeof window.foo, "object", "Should have named X-ray property access with pref=0");
+  equal(typeof unwrapped.foo, "object", "Should always have non-X-ray named property access");
+
+  Preferences.set(XRAY_PREF, 1);
+  equal(typeof window.foo, "object", "Should have named X-ray property access with pref=1");
+  equal(typeof unwrapped.foo, "object", "Should always have non-X-ray named property access");
+
+  Preferences.set(XRAY_PREF, 2);
+  equal(window.foo, undefined, "Should not have named X-ray property access with pref=2");
+  equal(typeof unwrapped.foo, "object", "Should always have non-X-ray named property access");
+
+  webnav.close();
+});
+
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -123,13 +123,14 @@ head = head_watchdog.js
 [test_watchdog_default.js]
 head = head_watchdog.js
 [test_watchdog_hibernate.js]
 head = head_watchdog.js
 [test_weak_keys.js]
 [test_writeToGlobalPrototype.js]
 [test_xpcwn_tamperproof.js]
 [test_xrayed_iterator.js]
+[test_xray_named_element_access.js]
 [test_xray_SavedFrame.js]
 [test_xray_SavedFrame-02.js]
 [test_xray_regexp.js]
 [test_resolve_dead_promise.js]
 [test_asyncLoadSubScriptError.js]
--- a/layout/generic/nsSimplePageSequenceFrame.cpp
+++ b/layout/generic/nsSimplePageSequenceFrame.cpp
@@ -17,17 +17,16 @@
 #include "nsPageFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsRegion.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsHTMLCanvasFrame.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
-#include "mozilla/gfx/DrawEventRecorder.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsServiceManagerUtils.h"
 #include <algorithm>
 
 #define OFFSET_NOT_SET -1
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -625,34 +624,30 @@ nsSimplePageSequenceFrame::PrePrintNextP
       nsDeviceContext *dc = PresContext()->DeviceContext();
       PR_PL(("\n"));
       PR_PL(("***************** BeginPage *****************\n"));
       rv = dc->BeginPage();
       NS_ENSURE_SUCCESS(rv, rv);
 
       mCalledBeginPage = true;
       
-      RefPtr<gfxContext> renderingContext = dc->CreateReferenceRenderingContext();
+      RefPtr<gfxContext> renderingContext = dc->CreateRenderingContext();
       NS_ENSURE_TRUE(renderingContext, NS_ERROR_OUT_OF_MEMORY);
 
       DrawTarget* drawTarget = renderingContext->GetDrawTarget();
       if (NS_WARN_IF(!drawTarget)) {
         return NS_ERROR_FAILURE;
       }
 
       for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) {
         HTMLCanvasElement* canvas = mCurrentCanvasList[i];
         nsIntSize size = canvas->GetSize();
 
-        RefPtr<mozilla::gfx::DrawEventRecorder> recorder =
-          new mozilla::gfx::DrawEventRecorderMemory();
         RefPtr<DrawTarget> canvasTarget =
           drawTarget->CreateSimilarDrawTarget(size, drawTarget->GetFormat());
-        canvasTarget =
-          mozilla::gfx::Factory::CreateRecordingDrawTarget(recorder, canvasTarget);
         if (!canvasTarget) {
           continue;
         }
 
         nsICanvasRenderingContextInternal* ctx = canvas->GetContextAtIndex(0);
         if (!ctx) {
           continue;
         }
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -562,35 +562,38 @@ libs:: FennecJNIWrappers.cpp
 	  echo '*****************************************************' && \
 	  exit 1)
 endif
 
 libs:: classes.dex
 	$(INSTALL) classes.dex $(FINAL_TARGET)
 
 # Generate Java binder interfaces from AIDL files.
-aidl_src_path := $(srcdir)/aidl
-aidl_target_path := generated
-media_pkg := org/mozilla/gecko/media
-
-$(aidl_target_path)/$(media_pkg)/%.java:$(aidl_geckoview_src_path)/$(media_pkg)/%.aidl
-	@echo "Processing AIDL: $< => $@"
-	$(AIDL) -p$(ANDROID_SDK)/framework.aidl -I$(aidl_geckoview_src_path) -o$(aidl_target_path) $<
-
 GECKOVIEW_AIDLS = \
   org/mozilla/gecko/IGeckoEditableChild.aidl \
   org/mozilla/gecko/IGeckoEditableParent.aidl \
-  org/mozilla/gecko/media/ICodec.java \
-  org/mozilla/gecko/media/ICodecCallbacks.java \
-  org/mozilla/gecko/media/IMediaDrmBridge.java \
-  org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.java \
-  org/mozilla/gecko/media/IMediaManager.java \
+  org/mozilla/gecko/media/ICodec.aidl \
+  org/mozilla/gecko/media/ICodecCallbacks.aidl \
+  org/mozilla/gecko/media/IMediaDrmBridge.aidl \
+  org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.aidl \
+  org/mozilla/gecko/media/IMediaManager.aidl \
   org/mozilla/gecko/process/IChildProcess.aidl \
   org/mozilla/gecko/process/IProcessManager.aidl \
   $(NULL)
 
 geckoview_aidl_src_path := $(topsrcdir)/mobile/android/geckoview/src/main/aidl
 geckoview_aidl_target_path := generated
-geckoview_aidl_targets := $(addprefix $(geckoview_aidl_target_path)/,$(GECKOVIEW_AIDLS:.aidl=.java))
+geckoview_aidl_targets := $(addprefix $(geckoview_aidl_target_path)/,$(patsubst %.aidl,%.java,$(GECKOVIEW_AIDLS:.java=)))
 
 $(geckoview_aidl_targets): $(geckoview_aidl_target_path)/%.java: $(geckoview_aidl_src_path)/%.aidl
 	@echo "Processing AIDL: $< => $@"
 	$(AIDL) -p$(ANDROID_SDK)/framework.aidl -I$(geckoview_aidl_src_path) -o$(geckoview_aidl_target_path) $<
+
+FENNEC_AIDLS = \
+  $(NULL)
+
+fennec_aidl_src_path := $(srcdir)/aidl
+fennec_aidl_target_path := generated
+fennec_aidl_targets := $(addprefix $(fennec_aidl_target_path)/,$(patsubst %.aidl,%.java,$(FENNEC_AIDLS:.java=)))
+
+$(fennec_aidl_targets): $(fennec_aidl_target_path)/%.java: $(fennec_aidl_src_path)/%.aidl
+	@echo "Processing AIDL: $< => $@"
+	$(AIDL) -p$(ANDROID_SDK)/framework.aidl -I$(fennec_aidl_src_path) -I$(geckoview_aidl_src_path) -o$(fennec_aidl_target_path) $<
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1,8 +1,9 @@
+
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* The prefs in this file are shipped with the GRE and should apply to all
  * embedding situations. Application-specific preferences belong somewhere else,
  * for example xpfe/bootstrap/browser-prefs.js
@@ -1232,16 +1233,23 @@ pref("dom.input.dirpicker", false);
 // Enables system messages and activities
 pref("dom.sysmsg.enabled", false);
 
 // Enable pre-installed applications.
 pref("dom.webapps.useCurrentProfile", false);
 
 pref("dom.cycle_collector.incremental", true);
 
+// Whether Xrays expose properties from the named properties object (aka global
+// scope polluter).  Values are:
+//   0 = properties exposed on Xrays
+//   1 = properties exposed on Xrays, except in web extension content scripts.
+//   2 = properties not exposed on xrays
+pref("dom.allow_named_properties_object_for_xrays", 1);
+
 // Parsing perf prefs. For now just mimic what the old code did.
 #ifndef XP_WIN
 pref("content.sink.pending_event_mode", 0);
 #endif
 
 // Disable popups from plugins by default
 //   0 = openAllowed
 //   1 = openControlled
new file mode 100644
--- /dev/null
+++ b/netwerk/base/SimpleChannel.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+#include "nsBaseChannel.h"
+#include "nsIInputStream.h"
+#include "nsIRequest.h"
+#include "SimpleChannel.h"
+
+namespace mozilla {
+namespace net {
+
+// Like MOZ_TRY, but returns the unwrapped error value rather than a
+// GenericErrorResult on failure.
+#define TRY_VAR(target, expr) \
+  do { \
+    auto result = (expr); \
+    if (result.isErr()) { \
+      return result.unwrapErr(); \
+    } \
+    (target) = result.unwrap(); \
+  } while (0)
+
+class SimpleChannel final : public nsBaseChannel
+{
+public:
+  explicit SimpleChannel(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);
+
+protected:
+  virtual ~SimpleChannel() {}
+
+  virtual nsresult OpenContentStream(bool async, nsIInputStream **streamOut,
+                                     nsIChannel** channel) override;
+
+  virtual nsresult BeginAsyncRead(nsIStreamListener* listener,
+                                  nsIRequest** request) override;
+
+private:
+  UniquePtr<SimpleChannelCallbacks> mCallbacks;
+};
+
+SimpleChannel::SimpleChannel(UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
+  : mCallbacks(Move(aCallbacks))
+{
+  EnableSynthesizedProgressEvents(true);
+}
+
+nsresult
+SimpleChannel::OpenContentStream(bool async, nsIInputStream **streamOut, nsIChannel** channel)
+{
+  NS_ENSURE_TRUE(mCallbacks, NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIInputStream> stream;
+  TRY_VAR(stream, mCallbacks->OpenContentStream(async, this));
+  MOZ_ASSERT(stream);
+
+  mCallbacks = nullptr;
+
+  *channel = nullptr;
+  stream.forget(streamOut);
+  return NS_OK;
+}
+
+nsresult
+SimpleChannel::BeginAsyncRead(nsIStreamListener* listener, nsIRequest** request)
+{
+  NS_ENSURE_TRUE(mCallbacks, NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIRequest> req;
+  TRY_VAR(req, mCallbacks->StartAsyncRead(listener, this));
+
+  mCallbacks = nullptr;
+
+  req.forget(request);
+  return NS_OK;
+}
+
+#undef TRY_VAR
+
+already_AddRefed<nsIChannel>
+NS_NewSimpleChannelInternal(nsIURI* aURI, nsILoadInfo* aLoadInfo, UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
+{
+  RefPtr<SimpleChannel> chan = new SimpleChannel(Move(aCallbacks));
+
+  chan->SetURI(aURI);
+
+  MOZ_ALWAYS_SUCCEEDS(chan->SetLoadInfo(aLoadInfo));
+
+  return chan.forget();
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/base/SimpleChannel.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+#ifndef SimpleChannel_h
+#define SimpleChannel_h
+
+#include "mozilla/Result.h"
+#include "mozilla/UniquePtr.h"
+#include "nsCOMPtr.h"
+
+class nsIChannel;
+class nsIInputStream;
+class nsILoadInfo;
+class nsIRequest;
+class nsIStreamListener;
+class nsIURI;
+
+//-----------------------------------------------------------------------------
+
+namespace mozilla {
+
+using InputStreamOrReason = Result<nsCOMPtr<nsIInputStream>, nsresult>;
+using RequestOrReason = Result<nsCOMPtr<nsIRequest>, nsresult>;
+
+namespace net {
+
+class SimpleChannelCallbacks
+{
+public:
+  virtual InputStreamOrReason OpenContentStream(bool async, nsIChannel* channel) = 0;
+
+  virtual RequestOrReason StartAsyncRead(nsIStreamListener* stream, nsIChannel* channel) = 0;
+
+  virtual ~SimpleChannelCallbacks() {}
+};
+
+template <typename F1, typename F2, typename T>
+class SimpleChannelCallbacksImpl final : public SimpleChannelCallbacks
+{
+public:
+  SimpleChannelCallbacksImpl(F1&& aStartAsyncRead, F2&& aOpenContentStream, T* context)
+    : mStartAsyncRead(aStartAsyncRead)
+    , mOpenContentStream(aOpenContentStream)
+    , mContext(context)
+  {}
+
+  virtual ~SimpleChannelCallbacksImpl() {}
+
+  virtual InputStreamOrReason OpenContentStream(bool async, nsIChannel* channel) override
+  {
+    return mOpenContentStream(async, channel, mContext);
+  }
+
+  virtual RequestOrReason StartAsyncRead(nsIStreamListener* listener, nsIChannel* channel) override
+  {
+    return mStartAsyncRead(listener, channel, mContext);
+  }
+
+private:
+  F1 mStartAsyncRead;
+  F2 mOpenContentStream;
+  RefPtr<T> mContext;
+};
+
+already_AddRefed<nsIChannel>
+NS_NewSimpleChannelInternal(nsIURI* aURI, nsILoadInfo* aLoadInfo, UniquePtr<SimpleChannelCallbacks>&& aCallbacks);
+
+} // namespace net
+} // namespace mozilla
+
+/**
+ * Creates a simple channel which wraps an input stream created by the given
+ * callbacks. The callbacks are not called until the underlying AsyncOpen2 or
+ * Open2 methods are called, and correspond to the nsBaseChannel::StartAsyncRead
+ * and nsBaseChannel::OpenContentStream methods of the same names.
+ *
+ * The last two arguments of each callback are the created channel instance,
+ * and the ref-counted context object passed to NS_NewSimpleChannel. A strong
+ * reference to that object is guaranteed to be kept alive until after a
+ * callback successfully completes.
+ */
+template <typename T, typename F1, typename F2>
+inline already_AddRefed<nsIChannel>
+NS_NewSimpleChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, T* context, F1&& aStartAsyncRead, F2&& aOpenContentStream)
+{
+  using namespace mozilla;
+
+  auto callbacks = MakeUnique<net::SimpleChannelCallbacksImpl<F1, F2, T>>(
+      Move(aStartAsyncRead), Move(aOpenContentStream), context);
+
+  return net::NS_NewSimpleChannelInternal(aURI, aLoadInfo, Move(callbacks));
+}
+
+template <typename T, typename F1>
+inline already_AddRefed<nsIChannel>
+NS_NewSimpleChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, T* context, F1&& aStartAsyncRead)
+{
+  using namespace mozilla;
+
+  auto openContentStream = [] (bool async, nsIChannel* channel, T* context) {
+    return Err(NS_ERROR_NOT_IMPLEMENTED);
+  };
+
+  return NS_NewSimpleChannel(
+      aURI, aLoadInfo, context, Move(aStartAsyncRead), Move(openContentStream));
+}
+
+#endif // SimpleChannel_h
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -155,16 +155,17 @@ EXPORTS += [
     'nsSerializationHelper.h',
     'nsSimpleNestedURI.h',
     'nsSimpleURI.h',
     'nsStreamListenerWrapper.h',
     'nsTemporaryFileInputStream.h',
     'nsURIHashKey.h',
     'nsURLHelper.h',
     'nsURLParsers.h',
+    'SimpleChannel.h',
 ]
 
 EXPORTS.mozilla += [
     'LoadContextInfo.h',
     'LoadInfo.h',
     'LoadTainting.h',
 ]
 
@@ -244,16 +245,17 @@ UNIFIED_SOURCES += [
     'nsURLHelper.cpp',
     'nsURLParsers.cpp',
     'PollableEvent.cpp',
     'Predictor.cpp',
     'ProxyAutoConfig.cpp',
     'RedirectChannelRegistrar.cpp',
     'RequestContextService.cpp',
     'SimpleBuffer.cpp',
+    'SimpleChannel.cpp',
     'StreamingProtocolService.cpp',
     'ThrottleQueue.cpp',
     'ThrottlingService.cpp',
     'Tickler.cpp',
     'TLSServerSocket.cpp',
 ]
 
 if CONFIG['MOZ_RUST'] and CONFIG['MOZ_RUST_URLPARSE']:
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -37,26 +37,27 @@ public:
   ~ScopedRequestSuspender() {
     if (mRequest)
       mRequest->Resume();
   }
 private:
   nsIRequest *mRequest;
 };
 
-// Used to suspend data events from mPump within a function scope.  This is
+// Used to suspend data events from mRequest within a function scope.  This is
 // usually needed when a function makes callbacks that could process events.
 #define SUSPEND_PUMP_FOR_SCOPE() \
-  ScopedRequestSuspender pump_suspender__(mPump)
+  ScopedRequestSuspender pump_suspender__(mRequest)
 
 //-----------------------------------------------------------------------------
 // nsBaseChannel
 
 nsBaseChannel::nsBaseChannel()
-  : mLoadFlags(LOAD_NORMAL)
+  : mPumpingData(false)
+  , mLoadFlags(LOAD_NORMAL)
   , mQueriedProgressSink(true)
   , mSynthProgressEvents(false)
   , mAllowThreadRetargeting(true)
   , mWaitingOnAsyncRedirect(false)
   , mOpenRedirectChannel(false)
   , mStatus(NS_OK)
   , mContentDispositionHint(UINT32_MAX)
   , mContentLength(-1)
@@ -226,20 +227,31 @@ nsBaseChannel::PushStreamConverter(const
     }
   }
   return rv;
 }
 
 nsresult
 nsBaseChannel::BeginPumpingData()
 {
+  nsresult rv;
+
+  rv = BeginAsyncRead(this, getter_AddRefs(mRequest));
+  if (NS_SUCCEEDED(rv)) {
+    mPumpingData = true;
+    return NS_OK;
+  }
+  if (rv != NS_ERROR_NOT_IMPLEMENTED) {
+    return rv;
+  }
+
   nsCOMPtr<nsIInputStream> stream;
   nsCOMPtr<nsIChannel> channel;
-  nsresult rv = OpenContentStream(true, getter_AddRefs(stream),
-                                  getter_AddRefs(channel));
+  rv = OpenContentStream(true, getter_AddRefs(stream),
+                         getter_AddRefs(channel));
   if (NS_FAILED(rv))
     return rv;
 
   NS_ASSERTION(!stream || !channel, "Got both a channel and a stream?");
 
   if (channel) {
       rv = NS_DispatchToCurrentThread(new RedirectRunnable(this, channel));
       if (NS_SUCCEEDED(rv))
@@ -250,26 +262,29 @@ nsBaseChannel::BeginPumpingData()
   // By assigning mPump, we flag this channel as pending (see Pending).  It's
   // important that the pending flag is set when we call into the stream (the
   // call to AsyncRead results in the stream's AsyncWait method being called)
   // and especially when we call into the loadgroup.  Our caller takes care to
   // release mPump if we return an error.
  
   rv = nsInputStreamPump::Create(getter_AddRefs(mPump), stream, -1, -1, 0, 0,
                                  true);
-  if (NS_SUCCEEDED(rv))
+  if (NS_SUCCEEDED(rv)) {
+    mPumpingData = true;
+    mRequest = mPump;
     rv = mPump->AsyncRead(this, nullptr);
+  }
 
   return rv;
 }
 
 void
 nsBaseChannel::HandleAsyncRedirect(nsIChannel* newChannel)
 {
-  NS_ASSERTION(!mPump, "Shouldn't have gotten here");
+  NS_ASSERTION(!mPumpingData, "Shouldn't have gotten here");
 
   nsresult rv = mStatus;
   if (NS_SUCCEEDED(mStatus)) {
     rv = Redirect(newChannel,
                   nsIChannelEventSink::REDIRECT_TEMPORARY,
                   true);
     if (NS_SUCCEEDED(rv)) {
       // OnRedirectVerifyCallback will be called asynchronously
@@ -356,51 +371,53 @@ nsBaseChannel::IsPending(bool *result)
 {
   *result = Pending();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::GetStatus(nsresult *status)
 {
-  if (mPump && NS_SUCCEEDED(mStatus)) {
-    mPump->GetStatus(status);
+  if (mRequest && NS_SUCCEEDED(mStatus)) {
+    mRequest->GetStatus(status);
   } else {
     *status = mStatus;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::Cancel(nsresult status)
 {
   // Ignore redundant cancelation
   if (NS_FAILED(mStatus))
     return NS_OK;
 
   mStatus = status;
 
-  if (mPump)
-    mPump->Cancel(status);
+  if (mRequest)
+    mRequest->Cancel(status);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::Suspend()
 {
-  NS_ENSURE_TRUE(mPump, NS_ERROR_NOT_INITIALIZED);
-  return mPump->Suspend();
+  NS_ENSURE_TRUE(mPumpingData, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_IMPLEMENTED);
+  return mRequest->Suspend();
 }
 
 NS_IMETHODIMP
 nsBaseChannel::Resume()
 {
-  NS_ENSURE_TRUE(mPump, NS_ERROR_NOT_INITIALIZED);
-  return mPump->Resume();
+  NS_ENSURE_TRUE(mPumpingData, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_IMPLEMENTED);
+  return mRequest->Resume();
 }
 
 NS_IMETHODIMP
 nsBaseChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
 {
   *aLoadFlags = mLoadFlags;
   return NS_OK;
 }
@@ -599,17 +616,17 @@ nsBaseChannel::SetContentLength(int64_t 
   mContentLength = aContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::Open(nsIInputStream **result)
 {
   NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED);
-  NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS);
+  NS_ENSURE_TRUE(!mPumpingData, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
 
   nsCOMPtr<nsIChannel> chan;
   nsresult rv = OpenContentStream(false, result, getter_AddRefs(chan));
   NS_ASSERTION(!chan || !*result, "Got both a channel and a stream?");
   if (NS_SUCCEEDED(rv) && chan) {
       rv = Redirect(chan, nsIChannelEventSink::REDIRECT_INTERNAL, false);
       if (NS_FAILED(rv))
@@ -641,17 +658,17 @@ nsBaseChannel::AsyncOpen(nsIStreamListen
   MOZ_ASSERT(!mLoadInfo ||
              mLoadInfo->GetSecurityMode() == 0 ||
              mLoadInfo->GetInitialSecurityCheckDone() ||
              (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
               nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
              "security flags in loadInfo but asyncOpen2() not called");
 
   NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED);
-  NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS);
+  NS_ENSURE_TRUE(!mPumpingData, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
   NS_ENSURE_ARG(listener);
 
   // Skip checking for chrome:// sub-resources.
   nsAutoCString scheme;
   mURI->GetScheme(scheme);
   if (!scheme.EqualsLiteral("file")) {
     NS_CompareLoadInfoAndLoadContext(this);
@@ -672,16 +689,18 @@ nsBaseChannel::AsyncOpen(nsIStreamListen
   mListener = listener;
   mListenerContext = ctxt;
 
   // This method assigns mPump as a side-effect.  We need to clear mPump if
   // this method fails.
   rv = BeginPumpingData();
   if (NS_FAILED(rv)) {
     mPump = nullptr;
+    mRequest = nullptr;
+    mPumpingData = false;
     ChannelDone();
     mCallbacks = nullptr;
     return rv;
   }
 
   // At this point, we are going to return success no matter what.
 
   mWasOpened = true;
@@ -712,17 +731,17 @@ nsBaseChannel::AsyncOpen2(nsIStreamListe
 // nsBaseChannel::nsITransportEventSink
 
 NS_IMETHODIMP
 nsBaseChannel::OnTransportStatus(nsITransport *transport, nsresult status,
                                  int64_t progress, int64_t progressMax)
 {
   // In some cases, we may wish to suppress transport-layer status events.
 
-  if (!mPump || NS_FAILED(mStatus)) {
+  if (!mPumpingData || NS_FAILED(mStatus)) {
     return NS_OK;
   }
 
   SUSPEND_PUMP_FOR_SCOPE();
 
   // Lazily fetch mProgressSink
   if (!mProgressSink) {
     if (mQueriedProgressSink) {
@@ -788,30 +807,32 @@ CallUnknownTypeSniffer(void *aClosure, c
   nsresult rv = sniffer->GetMIMETypeFromContent(chan, aData, aCount, detected);
   if (NS_SUCCEEDED(rv))
     chan->SetContentType(detected);
 }
 
 NS_IMETHODIMP
 nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
 {
-  MOZ_ASSERT(request == mPump);
+  MOZ_ASSERT_IF(mRequest, request == mRequest);
 
-  // If our content type is unknown, use the content type
-  // sniffer. If the sniffer is not available for some reason, then we just keep
-  // going as-is.
-  if (NS_SUCCEEDED(mStatus) &&
-      mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
-    mPump->PeekStream(CallUnknownTypeSniffer, static_cast<nsIChannel*>(this));
+  if (mPump) {
+    // If our content type is unknown, use the content type
+    // sniffer. If the sniffer is not available for some reason, then we just keep
+    // going as-is.
+    if (NS_SUCCEEDED(mStatus) &&
+        mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
+      mPump->PeekStream(CallUnknownTypeSniffer, static_cast<nsIChannel*>(this));
+    }
+
+    // Now, the general type sniffers. Skip this if we have none.
+    if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS)
+      mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
   }
 
-  // Now, the general type sniffers. Skip this if we have none.
-  if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS)
-    mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
-
   SUSPEND_PUMP_FOR_SCOPE();
 
   if (mListener) // null in case of redirect
       return mListener->OnStartRequest(this, mListenerContext);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -820,16 +841,18 @@ nsBaseChannel::OnStopRequest(nsIRequest 
 {
   // If both mStatus and status are failure codes, we keep mStatus as-is since
   // that is consistent with our GetStatus and Cancel methods.
   if (NS_SUCCEEDED(mStatus))
     mStatus = status;
 
   // Cause Pending to return false.
   mPump = nullptr;
+  mRequest = nullptr;
+  mPumpingData = false;
 
   if (mListener) // null in case of redirect
       mListener->OnStopRequest(this, mListenerContext, mStatus);
   ChannelDone();
 
   // No need to suspend pump in this scope since we will not be receiving
   // any more events from it.
 
@@ -908,23 +931,26 @@ nsBaseChannel::OnRedirectVerifyCallback(
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::RetargetDeliveryTo(nsIEventTarget* aEventTarget)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  NS_ENSURE_TRUE(mPump, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_INITIALIZED);
 
-  if (!mAllowThreadRetargeting) {
-    return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIThreadRetargetableRequest> req;
+  if (mAllowThreadRetargeting) {
+    req = do_QueryInterface(mRequest);
   }
 
-  return mPump->RetargetDeliveryTo(aEventTarget);
+  NS_ENSURE_TRUE(req, NS_ERROR_NOT_IMPLEMENTED);
+
+  return req->RetargetDeliveryTo(aEventTarget);
 }
 
 NS_IMETHODIMP
 nsBaseChannel::CheckListenerChain()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mAllowThreadRetargeting) {
--- a/netwerk/base/nsBaseChannel.h
+++ b/netwerk/base/nsBaseChannel.h
@@ -87,16 +87,29 @@ private:
   // terms of AsyncOpen (see NS_ImplementChannelOpen).
   // A callee is allowed to return an nsIChannel instead of an nsIInputStream.
   // That case will be treated as a redirect to the new channel.  By default
   // *channel will be set to null by the caller, so callees who don't want to
   // return one an just not touch it.
   virtual nsresult OpenContentStream(bool async, nsIInputStream **stream,
                                      nsIChannel** channel) = 0;
 
+  // Implemented by subclass to begin pumping data for an async channel, in
+  // lieu of returning a stream. If implemented, OpenContentStream will never
+  // be called for async channels. If not implemented, AsyncOpen2 will fall
+  // back to OpenContentStream.
+  //
+  // On success, the callee must begin pumping data to the stream listener,
+  // and at some point call OnStartRequest followed by OnStopRequest.
+  // Additionally, it may provide a request object which may be used to
+  // suspend, resume, and cancel the underlying request.
+  virtual nsresult BeginAsyncRead(nsIStreamListener* listener, nsIRequest** request) {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
   // The basechannel calls this method from its OnTransportStatus method to
   // determine whether to call nsIProgressEventSink::OnStatus in addition to
   // nsIProgressEventSink::OnProgress.  This method may be overriden by the
   // subclass to enable nsIProgressEventSink::OnStatus events.  If this method
   // returns true, then the statusArg out param specifies the "statusArg" value
   // to pass to the OnStatus method.  By default, OnStatus messages are
   // suppressed.  The status parameter passed to this method is the status value
   // from the OnTransportStatus method.
@@ -159,17 +172,17 @@ public:
 
   // Test the load flags
   bool HasLoadFlag(uint32_t flag) {
     return (mLoadFlags & flag) != 0;
   }
 
   // This is a short-cut to calling nsIRequest::IsPending()
   virtual bool Pending() const {
-    return mPump || mWaitingOnAsyncRedirect;
+    return mPumpingData || mWaitingOnAsyncRedirect;
  }
 
   // Helper function for querying the channel's notification callbacks.
   template <class T> void GetCallback(nsCOMPtr<T> &result) {
     GetInterface(NS_GET_TEMPLATE_IID(T), getter_AddRefs(result));
   }
 
   // Helper function for calling QueryInterface on this.
@@ -261,16 +274,18 @@ private:
 
   private:
     RefPtr<nsBaseChannel> mChannel;
     nsCOMPtr<nsIChannel> mNewChannel;
   };
   friend class RedirectRunnable;
 
   RefPtr<nsInputStreamPump>         mPump;
+  RefPtr<nsIRequest>                  mRequest;
+  bool                                mPumpingData;
   nsCOMPtr<nsIProgressEventSink>      mProgressSink;
   nsCOMPtr<nsIURI>                    mOriginalURI;
   nsCOMPtr<nsISupports>               mOwner;
   nsCOMPtr<nsISupports>               mSecurityInfo;
   nsCOMPtr<nsIChannel>                mRedirectChannel;
   nsCString                           mContentType;
   nsCString                           mContentCharset;
   uint32_t                            mLoadFlags;
--- a/netwerk/base/nsInputStreamPump.cpp
+++ b/netwerk/base/nsInputStreamPump.cpp
@@ -235,17 +235,20 @@ NS_IMETHODIMP
 nsInputStreamPump::Resume()
 {
     ReentrantMonitorAutoEnter mon(mMonitor);
 
     LOG(("nsInputStreamPump::Resume [this=%p]\n", this));
     NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
     NS_ENSURE_TRUE(mState != STATE_IDLE, NS_ERROR_UNEXPECTED);
 
-    if (--mSuspendCount == 0)
+    // There is a brief in-between state when we null out mAsyncStream in
+    // OnStateStop() before calling OnStopRequest, and only afterwards set
+    // STATE_IDLE, which we need to handle gracefully.
+    if (--mSuspendCount == 0 && mAsyncStream)
         EnsureWaiting();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsInputStreamPump::GetLoadFlags(nsLoadFlags *aLoadFlags)
 {
     ReentrantMonitorAutoEnter mon(mMonitor);
--- a/netwerk/base/nsSyncStreamListener.cpp
+++ b/netwerk/base/nsSyncStreamListener.cpp
@@ -3,16 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIOService.h"
 #include "nsSyncStreamListener.h"
 #include "nsIPipe.h"
 #include "nsThreadUtils.h"
 #include <algorithm>
 
+using namespace mozilla::net;
+
 nsresult
 nsSyncStreamListener::Init()
 {
     return NS_NewPipe(getter_AddRefs(mPipeIn),
                       getter_AddRefs(mPipeOut),
                       nsIOService::gDefaultSegmentSize,
                       UINT32_MAX, // no size limit
                       false,
--- a/netwerk/protocol/res/ExtensionProtocolHandler.cpp
+++ b/netwerk/protocol/res/ExtensionProtocolHandler.cpp
@@ -6,24 +6,22 @@
 
 #include "ExtensionProtocolHandler.h"
 
 #include "nsIAddonPolicyService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIURL.h"
 #include "nsIChannel.h"
 #include "nsIStreamListener.h"
-#include "nsIRequestObserver.h"
-#include "nsIInputStreamChannel.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsIStreamConverterService.h"
-#include "nsIPipe.h"
 #include "nsNetUtil.h"
 #include "LoadInfo.h"
+#include "SimpleChannel.h"
 
 namespace mozilla {
 namespace net {
 
 NS_IMPL_QUERY_INTERFACE(ExtensionProtocolHandler, nsISubstitutingProtocolHandler,
                         nsIProtocolHandler, nsIProtocolHandlerWithDynamicFlags,
                         nsISupportsWeakReference)
 NS_IMPL_ADDREF_INHERITED(ExtensionProtocolHandler, SubstitutingProtocolHandler)
@@ -40,49 +38,16 @@ ExtensionProtocolHandler::GetFlagsForURI
     nsresult rv = aps->ExtensionURILoadableByAnyone(aURI, &loadableByAnyone);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   *aFlags = URI_STD | URI_IS_LOCAL_RESOURCE | (loadableByAnyone ? (URI_LOADABLE_BY_ANYONE | URI_FETCHABLE_BY_ANYONE) : URI_DANGEROUS_TO_LOAD);
   return NS_OK;
 }
 
-class PipeCloser : public nsIRequestObserver
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  explicit PipeCloser(nsIOutputStream* aOutputStream) :
-    mOutputStream(aOutputStream)
-  {
-  }
-
-  NS_IMETHOD OnStartRequest(nsIRequest*, nsISupports*) override
-  {
-    return NS_OK;
-  }
-
-  NS_IMETHOD OnStopRequest(nsIRequest*, nsISupports*, nsresult aStatusCode) override
-  {
-    NS_ENSURE_TRUE(mOutputStream, NS_ERROR_UNEXPECTED);
-
-    nsresult rv = mOutputStream->Close();
-    mOutputStream = nullptr;
-    return rv;
-  }
-
-protected:
-  virtual ~PipeCloser() {}
-
-private:
-  nsCOMPtr<nsIOutputStream> mOutputStream;
-};
-
-NS_IMPL_ISUPPORTS(PipeCloser, nsIRequestObserver)
-
 bool
 ExtensionProtocolHandler::ResolveSpecialCases(const nsACString& aHost,
                                               const nsACString& aPath,
                                               const nsACString& aPathname,
                                               nsACString& aResult)
 {
   // Create special moz-extension:-pages such as moz-extension://foo/_blank.html
   // for all registered extensions. We can't just do this as a substitution
@@ -106,16 +71,27 @@ ExtensionProtocolHandler::ResolveSpecial
       MOZ_RELEASE_ASSERT(Substring(aResult, 0, 5).Equals("data:"));
       return true;
     }
   }
 
   return false;
 }
 
+static inline Result<Ok, nsresult>
+WrapNSResult(nsresult aRv)
+{
+  if (NS_FAILED(aRv)) {
+    return Err(aRv);
+  }
+  return Ok();
+}
+
+#define NS_TRY(expr) MOZ_TRY(WrapNSResult(expr))
+
 nsresult
 ExtensionProtocolHandler::SubstituteChannel(nsIURI* aURI,
                                             nsILoadInfo* aLoadInfo,
                                             nsIChannel** result)
 {
   nsresult rv;
   nsCOMPtr<nsIURL> url = do_QueryInterface(aURI, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -125,55 +101,51 @@ ExtensionProtocolHandler::SubstituteChan
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!ext.LowerCaseEqualsLiteral("css")) {
     return NS_OK;
   }
 
   // Filter CSS files to replace locale message tokens with localized strings.
 
-  nsCOMPtr<nsIStreamConverterService> convService =
-    do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  bool haveLoadInfo = aLoadInfo;
+  nsCOMPtr<nsIChannel> channel = NS_NewSimpleChannel(
+    aURI, aLoadInfo, *result,
+    [haveLoadInfo] (nsIStreamListener* listener, nsIChannel* channel, nsIChannel* origChannel) -> RequestOrReason {
+      nsresult rv;
+      nsCOMPtr<nsIStreamConverterService> convService =
+        do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
+      NS_TRY(rv);
 
-  const char* kFromType = "application/vnd.mozilla.webext.unlocalized";
-  const char* kToType = "text/css";
+      nsCOMPtr<nsIURI> uri;
+      NS_TRY(channel->GetURI(getter_AddRefs(uri)));
 
-  nsCOMPtr<nsIInputStream> inputStream;
-  nsCOMPtr<nsIOutputStream> outputStream;
-  rv = NS_NewPipe(getter_AddRefs(inputStream), getter_AddRefs(outputStream),
-                  0, UINT32_MAX, true, false);
-  NS_ENSURE_SUCCESS(rv, rv);
+      const char* kFromType = "application/vnd.mozilla.webext.unlocalized";
+      const char* kToType = "text/css";
 
-  nsCOMPtr<nsIStreamListener> listener;
-  nsCOMPtr<nsIRequestObserver> observer = new PipeCloser(outputStream);
-  rv = NS_NewSimpleStreamListener(getter_AddRefs(listener), outputStream, observer);
-  NS_ENSURE_SUCCESS(rv, rv);
+      nsCOMPtr<nsIStreamListener> converter;
+      NS_TRY(convService->AsyncConvertData(kFromType, kToType, listener,
+                                        uri, getter_AddRefs(converter)));
+      if (haveLoadInfo) {
+        NS_TRY(origChannel->AsyncOpen2(converter));
+      } else {
+        NS_TRY(origChannel->AsyncOpen(converter, nullptr));
+      }
 
-  nsCOMPtr<nsIStreamListener> converter;
-  rv = convService->AsyncConvertData(kFromType, kToType, listener,
-                                     aURI, getter_AddRefs(converter));
-  NS_ENSURE_SUCCESS(rv, rv);
+      return RequestOrReason(origChannel);
+    });
+  NS_ENSURE_TRUE(channel, NS_ERROR_OUT_OF_MEMORY);
 
   if (aLoadInfo) {
     nsCOMPtr<nsILoadInfo> loadInfo =
         static_cast<LoadInfo*>(aLoadInfo)->CloneForNewRequest();
-      (*result)->SetLoadInfo(loadInfo);
-
-    rv = (*result)->AsyncOpen2(converter);
-  } else {
-    rv = (*result)->AsyncOpen(converter, nullptr);
+    (*result)->SetLoadInfo(loadInfo);
   }
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIChannel> channel;
-  rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI, inputStream,
-                                        NS_LITERAL_CSTRING("text/css"),
-                                        NS_LITERAL_CSTRING("utf-8"),
-                                        aLoadInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
 
   channel.swap(*result);
+
   return NS_OK;
 }
 
+#undef NS_TRY
+
 } // namespace net
 } // namespace mozilla
--- a/toolkit/components/aboutcache/moz.build
+++ b/toolkit/components/aboutcache/moz.build
@@ -1,7 +1,10 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files("**"):
+    BUG_COMPONENT = ('Core', 'Networking: Cache')
+
 JAR_MANIFESTS += ['jar.mn']
--- a/toolkit/components/aboutperformance/moz.build
+++ b/toolkit/components/aboutperformance/moz.build
@@ -1,9 +1,12 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Performance Monitoring')
+
 JAR_MANIFESTS += ['jar.mn']
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
--- a/toolkit/components/addoncompat/moz.build
+++ b/toolkit/components/addoncompat/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'Extension Compatibility')
+
 TEST_DIRS += ['tests']
 
 EXTRA_COMPONENTS += [
     'addoncompat.manifest',
     'defaultShims.js',
     'multiprocessShims.js',
 ]
 
--- a/toolkit/components/apppicker/moz.build
+++ b/toolkit/components/apppicker/moz.build
@@ -1,7 +1,10 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Preferences')
+
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
--- a/toolkit/components/browser/moz.build
+++ b/toolkit/components/browser/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 DIRS += ['build']
 
 XPIDL_SOURCES += [
     'nsCWebBrowser.idl',
     'nsICommandHandler.idl',
     'nsIEmbeddingSiteWindow.idl',
     'nsIWebBrowser.idl',
     'nsIWebBrowserChrome.idl',
--- a/toolkit/components/build/moz.build
+++ b/toolkit/components/build/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Build Config')
+
 EXPORTS += [
     'nsToolkitCompsCID.h',
 ]
 
 SOURCES += [
     'nsToolkitCompsModule.cpp',
 ]
 
--- a/toolkit/components/captivedetect/moz.build
+++ b/toolkit/components/captivedetect/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'DOM: Device Interfaces')
+
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 XPIDL_SOURCES += [
     'nsICaptivePortalDetector.idl',
 ]
 
 XPIDL_MODULE = 'captivedetect'
 
--- a/toolkit/components/contextualidentity/moz.build
+++ b/toolkit/components/contextualidentity/moz.build
@@ -1,11 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'DOM: Security')
+
 EXTRA_JS_MODULES += [
     'ContextualIdentityService.jsm',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
--- a/toolkit/components/crashmonitor/moz.build
+++ b/toolkit/components/crashmonitor/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 EXTRA_JS_MODULES += [
     'CrashMonitor.jsm',
 ]
 
 EXTRA_COMPONENTS += [
     'crashmonitor.manifest',
--- a/toolkit/components/diskspacewatcher/moz.build
+++ b/toolkit/components/diskspacewatcher/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 XPIDL_SOURCES += [
     'nsIDiskSpaceWatcher.idl',
 ]
 
 EXPORTS += [
     'DiskSpaceWatcher.h'
 ]
 
--- a/toolkit/components/extensions/moz.build
+++ b/toolkit/components/extensions/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'WebExtensions: General')
+
 EXTRA_JS_MODULES += [
     'Extension.jsm',
     'ExtensionAPI.jsm',
     'ExtensionChild.jsm',
     'ExtensionCommon.jsm',
     'ExtensionContent.jsm',
     'ExtensionManagement.jsm',
     'ExtensionParent.jsm',
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/data/file_sample.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+
+<div id="test">Sample text</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_xrays.js
@@ -0,0 +1,72 @@
+"use strict";
+
+Cu.import("resource://gre/modules/Preferences.jsm");
+
+const server = createHttpServer();
+server.registerDirectory("/data/", do_get_file("data"));
+
+const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
+const XRAY_PREF = "dom.allow_named_properties_object_for_xrays";
+
+add_task(async function test_contentscript_xrays() {
+  async function contentScript() {
+    let deferred;
+    browser.test.onMessage.addListener(msg => {
+      if (msg === "pref-set") {
+        deferred.resolve();
+      }
+    });
+    function setPref(val) {
+      browser.test.sendMessage("set-pref", val);
+      return new Promise(resolve => { deferred = {resolve}; });
+    }
+
+    let unwrapped = window.wrappedJSObject;
+
+    await setPref(0);
+    browser.test.assertEq("object", typeof test, "Should have named X-ray property access with pref=0");
+    browser.test.assertEq("object", typeof window.test, "Should have named X-ray property access with pref=0");
+    browser.test.assertEq("object", typeof unwrapped.test, "Should always have non-X-ray named property access");
+
+    await setPref(1);
+    browser.test.assertEq("undefined", typeof test, "Should not have named X-ray property access with pref=1");
+    browser.test.assertEq(undefined, window.test, "Should not have named X-ray property access with pref=1");
+    browser.test.assertEq("object", typeof unwrapped.test, "Should always have non-X-ray named property access");
+
+    await setPref(2);
+    browser.test.assertEq("undefined", typeof test, "Should not have named X-ray property access with pref=2");
+    browser.test.assertEq(undefined, window.test, "Should not have named X-ray property access with pref=2");
+    browser.test.assertEq("object", typeof unwrapped.test, "Should always have non-X-ray named property access");
+
+    browser.test.notifyPass("contentScriptXrays");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      content_scripts: [{
+        "matches": ["http://*/*/file_sample.html"],
+        "js": ["content_script.js"],
+      }],
+    },
+
+    files: {
+      "content_script.js": contentScript,
+    },
+  });
+
+  extension.onMessage("set-pref", value => {
+    Preferences.set(XRAY_PREF, value);
+    extension.sendMessage("pref-set");
+  });
+
+  equal(Preferences.get(XRAY_PREF), 1, "Should have pref=1 by default");
+
+  await extension.startup();
+  let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
+
+  await extension.awaitFinish("contentScriptXrays");
+
+  await contentPage.close();
+  await extension.unload();
+});
+
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-content.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-content.ini
@@ -1,3 +1,4 @@
 [test_ext_i18n.js]
 [test_ext_i18n_css.js]
 [test_ext_contentscript.js]
+[test_ext_contentscript_xrays.js]
--- a/toolkit/components/exthelper/moz.build
+++ b/toolkit/components/exthelper/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 XPIDL_SOURCES += [
     'extIApplication.idl',
 ]
 
 XPIDL_MODULE = 'exthelper'
 
--- a/toolkit/components/feeds/moz.build
+++ b/toolkit/components/feeds/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
+
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 XPIDL_SOURCES += [
     'nsIFeed.idl',
     'nsIFeedContainer.idl',
     'nsIFeedElementBase.idl',
     'nsIFeedEntry.idl',
     'nsIFeedGenerator.idl',
--- a/toolkit/components/filepicker/moz.build
+++ b/toolkit/components/filepicker/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Widget: Gtk')
+
 XPIDL_MODULE = 'filepicker'
 XPIDL_SOURCES += [
     'nsIFileView.idl',
 ]
 SOURCES += [
     'nsFileView.cpp',
 ]
 EXTRA_COMPONENTS += [
--- a/toolkit/components/filewatcher/moz.build
+++ b/toolkit/components/filewatcher/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'OS.File')
+
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += ['NativeFileWatcherWin.h']
     UNIFIED_SOURCES += [
         'NativeFileWatcherWin.cpp',
     ]
 else:
--- a/toolkit/components/finalizationwitness/moz.build
+++ b/toolkit/components/finalizationwitness/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
 SOURCES += [
   'FinalizationWitnessService.cpp',
 ]
 
 XPIDL_SOURCES += [
   'nsIFinalizationWitnessService.idl',
 ]
 
--- a/toolkit/components/find/moz.build
+++ b/toolkit/components/find/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
 XPIDL_SOURCES += [
     'nsIFind.idl',
     'nsIFindService.idl',
     'nsIWebBrowserFind.idl',
 ]
 
 XPIDL_MODULE = 'mozfind'
 
--- a/toolkit/components/gfx/moz.build
+++ b/toolkit/components/gfx/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Graphics')
+
 EXTRA_COMPONENTS += [
     'GfxSanityTest.manifest',
     'SanityTest.js',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
--- a/toolkit/components/lz4/moz.build
+++ b/toolkit/components/lz4/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'OS.File')
+
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
 EXTRA_JS_MODULES += [
     'lz4.js',
     'lz4_internal.js',
 ]
 
 SOURCES += [
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 # These component dirs are built for all apps (including suite)
 if CONFIG['MOZ_ENABLE_XREMOTE']:
     DIRS += ['remote']
 
 DIRS += [
     'aboutcache',
     'aboutcheckerboard',
     'aboutmemory',
--- a/toolkit/components/mozintl/moz.build
+++ b/toolkit/components/mozintl/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Internationalization')
+
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
 
 XPIDL_SOURCES += [
     'mozIMozIntl.idl',
     'mozIMozIntlHelper.idl',
 ]
 
 XPIDL_MODULE = 'mozintl'
--- a/toolkit/components/mozprotocol/moz.build
+++ b/toolkit/components/mozprotocol/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 EXTRA_COMPONENTS += [
     'mozProtocolHandler.js',
     'mozProtocolHandler.manifest',
 ]
 
 BROWSER_CHROME_MANIFESTS += [
     'tests/browser.ini'
 ]
--- a/toolkit/components/narrate/moz.build
+++ b/toolkit/components/narrate/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Reader Mode')
+
 EXTRA_JS_MODULES.narrate = [
   'NarrateControls.jsm',
   'Narrator.jsm',
   'VoiceSelect.jsm'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/toolkit/components/parentalcontrols/moz.build
+++ b/toolkit/components/parentalcontrols/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 XPIDL_SOURCES += [
     'nsIParentalControlsService.idl',
 ]
 
 XPIDL_MODULE = 'parentalcontrols'
 
 if not CONFIG['MOZ_DISABLE_PARENTAL_CONTROLS']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
--- a/toolkit/components/perf/moz.build
+++ b/toolkit/components/perf/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'JavaScript Engine')
+
 SOURCES += [
     'PerfMeasurement.cpp',
 ]
 
 EXTRA_JS_MODULES += [
     'PerfMeasurement.jsm',
 ]
 
--- a/toolkit/components/perfmonitoring/moz.build
+++ b/toolkit/components/perfmonitoring/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Performance Monitoring')
+
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 
 XPIDL_MODULE = 'toolkit_perfmonitoring'
 
 EXTRA_JS_MODULES += [
     'PerformanceStats-content.js',
     'PerformanceStats.jsm',
     'PerformanceWatcher-content.js',
--- a/toolkit/components/places/nsAnnoProtocolHandler.cpp
+++ b/toolkit/components/places/nsAnnoProtocolHandler.cpp
@@ -15,25 +15,28 @@
 
 #include "nsAnnoProtocolHandler.h"
 #include "nsFaviconService.h"
 #include "nsIChannel.h"
 #include "nsIInputStreamChannel.h"
 #include "nsILoadGroup.h"
 #include "nsIStandardURL.h"
 #include "nsIStringStream.h"
+#include "nsIInputStream.h"
 #include "nsISupportsUtils.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIOutputStream.h"
+#include "nsInputStreamPump.h"
 #include "nsContentUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStringStream.h"
+#include "SimpleChannel.h"
+#include "mozilla/ScopeExit.h"
 #include "mozilla/storage.h"
-#include "nsIPipe.h"
 #include "Helpers.h"
 
 using namespace mozilla;
 using namespace mozilla::places;
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Global Functions
 
@@ -63,30 +66,26 @@ namespace {
  * will close the original channel for the favicon request.
  *
  * However, if an error occurs at any point, we do not set mReturnDefaultIcon to
  * false, so we will open up another channel to get the default favicon, and
  * pass that along to our output stream in HandleCompletion.  If anything
  * happens at that point, the world must be against us, so we return nothing.
  */
 class faviconAsyncLoader : public AsyncStatementCallback
-                         , public nsIRequestObserver
 {
 public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  faviconAsyncLoader(nsIChannel *aChannel, nsIOutputStream *aOutputStream) :
+  faviconAsyncLoader(nsIChannel *aChannel, nsIStreamListener *aListener) :
       mChannel(aChannel)
-    , mOutputStream(aOutputStream)
-    , mReturnDefaultIcon(true)
+    , mListener(aListener)
   {
     NS_ASSERTION(aChannel,
                  "Not providing a channel will result in crashes!");
-    NS_ASSERTION(aOutputStream,
-                 "Not providing an output stream will result in crashes!");
+    NS_ASSERTION(aListener,
+                 "Not providing a stream listener will result in crashes!");
   }
 
   //////////////////////////////////////////////////////////////////////////////
   //// mozIStorageStatementCallback
 
   NS_IMETHOD HandleResult(mozIStorageResultSet *aResultSet) override
   {
     // We will only get one row back in total, so we do not need to loop.
@@ -105,107 +104,77 @@ public:
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Obtain the binary blob that contains our favicon data.
     uint8_t *favicon;
     uint32_t size = 0;
     rv = row->GetBlob(0, &size, &favicon);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    uint32_t totalWritten = 0;
-    do {
-      uint32_t bytesWritten;
-      rv = mOutputStream->Write(
-        &(reinterpret_cast<const char *>(favicon)[totalWritten]),
-        size - totalWritten,
-        &bytesWritten
-      );
-      if (NS_FAILED(rv) || !bytesWritten)
-        break;
-      totalWritten += bytesWritten;
-    } while (size != totalWritten);
-    NS_ASSERTION(NS_FAILED(rv) || size == totalWritten,
-                 "Failed to write all of our data out to the stream!");
+    nsCOMPtr<nsIInputStream> stream;
+    rv = NS_NewByteInputStream(getter_AddRefs(stream),
+                               reinterpret_cast<char*>(favicon),
+                               size, NS_ASSIGNMENT_ADOPT);
+    if (NS_FAILED(rv)) {
+      free(favicon);
+      return rv;
+    }
 
-    // Free our favicon array.
-    free(favicon);
-
-    // Handle an error to write if it occurred, but only after we've freed our
-    // favicon.
+    RefPtr<nsInputStreamPump> pump;
+    rv = nsInputStreamPump::Create(getter_AddRefs(pump), stream, -1, -1, 0, 0,
+                                   true);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    // At this point, we should have written out all of our data to our stream.
-    // HandleCompletion will close the output stream, so we are done here.
-    mReturnDefaultIcon = false;
+    MOZ_DIAGNOSTIC_ASSERT(mListener);
+    NS_ENSURE_TRUE(mListener, NS_ERROR_UNEXPECTED);
+
+    rv = pump->AsyncRead(mListener, nullptr);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    mListener = nullptr;
     return NS_OK;
   }
 
   NS_IMETHOD HandleCompletion(uint16_t aReason) override
   {
-    if (!mReturnDefaultIcon)
-      return mOutputStream->Close();
+    // If we've already written our icon data to the channel, there's nothing
+    // more to do. If we didn't, then return the default icon instead.
+    if (!mListener)
+      return NS_OK;
 
-    // We need to return our default icon, so we'll open up a new channel to get
-    // that data, and push it to our output stream.  If at any point we get an
-    // error, we can't do anything, so we'll just close our output stream.
-    nsCOMPtr<nsIStreamListener> listener;
-    nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(listener),
-                                             mOutputStream, this);
-    NS_ENSURE_SUCCESS(rv, mOutputStream->Close());
+    auto cleanup = MakeScopeExit([&] () {
+      mListener = nullptr;
+    });
 
     // we should pass the loadInfo of the original channel along
     // to the new channel. Note that mChannel can not be null,
     // constructor checks that.
     nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
     nsCOMPtr<nsIChannel> newChannel;
-    rv = GetDefaultIcon(loadInfo, getter_AddRefs(newChannel));
-    NS_ENSURE_SUCCESS(rv, mOutputStream->Close());
-
-    rv = newChannel->AsyncOpen2(listener);
-    NS_ENSURE_SUCCESS(rv, mOutputStream->Close());
-
-    return NS_OK;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //// nsIRequestObserver
+    nsresult rv = GetDefaultIcon(loadInfo, getter_AddRefs(newChannel));
 
-  NS_IMETHOD OnStartRequest(nsIRequest *, nsISupports *) override
-  {
-    return NS_OK;
-  }
+    if (NS_FAILED(rv)) {
+      mListener->OnStartRequest(mChannel, nullptr);
+      mListener->OnStopRequest(mChannel, nullptr, rv);
+      return rv;
+    }
 
-  NS_IMETHOD OnStopRequest(nsIRequest *, nsISupports *, nsresult aStatusCode) override
-  {
-    // We always need to close our output stream, regardless of the status code.
-    (void)mOutputStream->Close();
+    mChannel->SetContentType(NS_LITERAL_CSTRING("image/png"));
 
-    // But, we'll warn about it not being successful if it wasn't.
-    NS_WARNING_ASSERTION(
-      NS_SUCCEEDED(aStatusCode),
-      "Got an error when trying to load our default favicon!");
-
-    return NS_OK;
+    return newChannel->AsyncOpen2(mListener);
   }
 
 protected:
   virtual ~faviconAsyncLoader() {}
 
 private:
   nsCOMPtr<nsIChannel> mChannel;
-  nsCOMPtr<nsIOutputStream> mOutputStream;
-  bool mReturnDefaultIcon;
+  nsCOMPtr<nsIStreamListener> mListener;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED(
-  faviconAsyncLoader,
-  AsyncStatementCallback,
-  nsIRequestObserver
-)
-
 } // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsAnnoProtocolHandler
 
 NS_IMPL_ISUPPORTS(nsAnnoProtocolHandler, nsIProtocolHandler)
 
 // nsAnnoProtocolHandler::GetScheme
@@ -326,42 +295,45 @@ nsAnnoProtocolHandler::ParseAnnoURI(nsIU
   aName = Substring(path, 0, firstColon);
   return NS_OK;
 }
 
 nsresult
 nsAnnoProtocolHandler::NewFaviconChannel(nsIURI *aURI, nsIURI *aAnnotationURI,
                                          nsILoadInfo* aLoadInfo, nsIChannel **_channel)
 {
-  // Create our pipe.  This will give us our input stream and output stream
-  // that will be written to when we get data from the database.
-  nsCOMPtr<nsIInputStream> inputStream;
-  nsCOMPtr<nsIOutputStream> outputStream;
-  nsresult rv = NS_NewPipe(getter_AddRefs(inputStream),
-                           getter_AddRefs(outputStream),
-                           0, nsIFaviconService::MAX_FAVICON_BUFFER_SIZE,
-                           true, true);
-  NS_ENSURE_SUCCESS(rv, GetDefaultIcon(aLoadInfo, _channel));
-
   // Create our channel.  We'll call SetContentType with the right type when
   // we know what it actually is.
-  nsCOMPtr<nsIChannel> channel;
-  rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
-                                        aURI,
-                                        inputStream,
-                                        EmptyCString(), // aContentType
-                                        EmptyCString(), // aContentCharset
-                                        aLoadInfo);
-  NS_ENSURE_SUCCESS(rv, GetDefaultIcon(aLoadInfo, _channel));
+  nsCOMPtr<nsIChannel> channel = NS_NewSimpleChannel(
+    aURI, aLoadInfo, aAnnotationURI,
+    [] (nsIStreamListener* listener, nsIChannel* channel, nsIURI* annotationURI) {
+      auto fallback = [&] () -> RequestOrReason {
+        nsCOMPtr<nsIChannel> chan;
+        nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
+        nsresult rv = GetDefaultIcon(loadInfo, getter_AddRefs(chan));
+        NS_ENSURE_SUCCESS(rv, Err(rv));
+
+        rv = chan->AsyncOpen2(listener);
+        NS_ENSURE_SUCCESS(rv, Err(rv));
+
+        return RequestOrReason(chan.forget());
+      };
 
-  // Now we go ahead and get our data asynchronously for the favicon.
-  nsCOMPtr<mozIStorageStatementCallback> callback =
-    new faviconAsyncLoader(channel, outputStream);
-  NS_ENSURE_TRUE(callback, GetDefaultIcon(aLoadInfo, _channel));
-  nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
-  NS_ENSURE_TRUE(faviconService, GetDefaultIcon(aLoadInfo, _channel));
+      // Now we go ahead and get our data asynchronously for the favicon.
+      nsCOMPtr<mozIStorageStatementCallback> callback =
+        new faviconAsyncLoader(channel, listener);
 
-  rv = faviconService->GetFaviconDataAsync(aAnnotationURI, callback);
-  NS_ENSURE_SUCCESS(rv, GetDefaultIcon(aLoadInfo, _channel));
+      nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
+      // Any failures fallback to the default icon channel.
+      if (!callback || !faviconService)
+        return fallback();
+
+      nsresult rv = faviconService->GetFaviconDataAsync(annotationURI, callback);
+      if (NS_FAILED(rv))
+        return fallback();
+
+      return RequestOrReason(nullptr);
+    });
+  NS_ENSURE_TRUE(channel, NS_ERROR_OUT_OF_MEMORY);
 
   channel.forget(_channel);
   return NS_OK;
 }
--- a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js
+++ b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js
@@ -34,16 +34,17 @@ streamListener.prototype =
     this._checked = true;
   },
   onStopRequest() {
     do_check_true(this._checked);
     do_test_finished();
   },
   onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) {
     aRequest.cancel(Cr.NS_ERROR_ABORT);
+    throw Cr.NS_ERROR_ABORT;
   }
 };
 
 // Test Runner
 
 function run_test() {
   let fs = Cc["@mozilla.org/browser/favicon-service;1"].
            getService(Ci.nsIFaviconService);
--- a/toolkit/components/printingui/moz.build
+++ b/toolkit/components/printingui/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Printing')
+
 toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
 
 DIRS += ['ipc']
 
 if CONFIG['NS_PRINTING']:
     if toolkit == 'windows':
         DIRS += ['win']
     elif toolkit == 'cocoa':
--- a/toolkit/components/privatebrowsing/moz.build
+++ b/toolkit/components/privatebrowsing/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'DOM: Security')
+
 XPIDL_SOURCES += [
     'nsIPrivateBrowsingTrackingProtectionWhitelist.idl',
 ]
 
 XPIDL_MODULE = 'privatebrowsing'
 
 EXTRA_COMPONENTS += [
     'PrivateBrowsing.manifest',
--- a/toolkit/components/processsingleton/moz.build
+++ b/toolkit/components/processsingleton/moz.build
@@ -1,11 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 EXTRA_COMPONENTS += [
     'ContentProcessSingleton.js',
     'MainProcessSingleton.js',
     'ProcessSingleton.manifest',
 ]
--- a/toolkit/components/prompts/moz.build
+++ b/toolkit/components/prompts/moz.build
@@ -1,11 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+# possibly Notifications and Alerts
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 DIRS += ['src']
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 JAR_MANIFESTS += ['jar.mn']
--- a/toolkit/components/protobuf/moz.build
+++ b/toolkit/components/protobuf/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'General')
+
 EXPORTS.google.protobuf += [
     'src/google/protobuf/descriptor.h',
     'src/google/protobuf/descriptor.pb.h',
     'src/google/protobuf/descriptor_database.h',
     'src/google/protobuf/dynamic_message.h',
     'src/google/protobuf/extension_set.h',
     'src/google/protobuf/generated_enum_reflection.h',
     'src/google/protobuf/generated_message_reflection.h',
--- a/toolkit/components/reflect/moz.build
+++ b/toolkit/components/reflect/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'JavaScript Engine')
+
 SOURCES += [
     'reflect.cpp',
 ]
 
 EXTRA_JS_MODULES += [
     'reflect.jsm',
 ]
 
--- a/toolkit/components/remote/moz.build
+++ b/toolkit/components/remote/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Startup and Profile System')
+
 XPIDL_SOURCES += [
     'nsIRemoteService.idl',
 ]
 
 XPIDL_MODULE = 'toolkitremote'
 
 SOURCES += [
     'nsXRemoteService.cpp',
--- a/toolkit/components/remotebrowserutils/moz.build
+++ b/toolkit/components/remotebrowserutils/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Document Navigation')
+
 EXTRA_COMPONENTS += [
     'remotebrowserutils.manifest',
     'RemoteWebNavigation.js',
 ]
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
--- a/toolkit/components/satchel/moz.build
+++ b/toolkit/components/satchel/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Form Manager')
+
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 
 XPIDL_SOURCES += [
     'nsIFormAutoComplete.idl',
     'nsIFormFillController.idl',
     'nsIInputListAutoComplete.idl',
--- a/toolkit/components/securityreporter/moz.build
+++ b/toolkit/components/securityreporter/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'General')
+
 XPIDL_MODULE = 'toolkit_securityreporter'
 
 XPIDL_SOURCES += [
     'nsISecurityReporter.idl',
 ]
 
 EXTRA_COMPONENTS += [
     'SecurityReporter.js',
deleted file mode 100644
--- a/toolkit/components/social/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/toolkit/components/statusfilter/moz.build
+++ b/toolkit/components/statusfilter/moz.build
@@ -1,11 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Document Navigation')
+
 SOURCES += [
     'nsBrowserStatusFilter.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/components/terminator/moz.build
+++ b/toolkit/components/terminator/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
 SOURCES += [
     'nsTerminator.cpp',
 ]
 
 EXPORTS += [
     'nsTerminator.h',
--- a/toolkit/components/thumbnails/moz.build
+++ b/toolkit/components/thumbnails/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'New Tab Page')
+
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
 
 EXTRA_COMPONENTS += [
     'BrowserPageThumbs.manifest',
     'PageThumbsProtocol.js',
 ]
 
--- a/toolkit/components/url-classifier/moz.build
+++ b/toolkit/components/url-classifier/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Safe Browsing')
+
 TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsIUrlClassifierDBService.idl',
     'nsIUrlClassifierHashCompleter.idl',
     'nsIUrlClassifierPrefixSet.idl',
     'nsIUrlClassifierStreamUpdater.idl',
     'nsIUrlClassifierUtils.idl',
--- a/toolkit/components/urlformatter/moz.build
+++ b/toolkit/components/urlformatter/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 XPIDL_SOURCES += [
     'nsIURLFormatter.idl',
 ]
 
 XPIDL_MODULE = 'urlformatter'
 
--- a/toolkit/components/utils/moz.build
+++ b/toolkit/components/utils/moz.build
@@ -1,10 +1,13 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 EXTRA_COMPONENTS += [
     'simpleServices.js',
     'utils.manifest',
 ]
--- a/toolkit/components/viewconfig/moz.build
+++ b/toolkit/components/viewconfig/moz.build
@@ -1,7 +1,10 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Preferences')
+
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
--- a/toolkit/components/windowcreator/moz.build
+++ b/toolkit/components/windowcreator/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Window Management')
+
 TEST_DIRS += ['test']
 
 if CONFIG['ENABLE_TESTS']:
     XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 XPIDL_SOURCES += [
     'nsIWindowCreator.idl',
     'nsIWindowCreator2.idl',
--- a/toolkit/components/windowwatcher/moz.build
+++ b/toolkit/components/windowwatcher/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Window Management')
+
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsIDialogParamBlock.idl',
     'nsIPromptFactory.idl',
     'nsIPromptService.idl',
     'nsIPromptService2.idl',
     'nsIWindowWatcher.idl',
--- a/toolkit/components/xulstore/moz.build
+++ b/toolkit/components/xulstore/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Startup and Profile System')
+
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
 XPIDL_SOURCES += [
     'nsIXULStore.idl',
 ]
 
 XPIDL_MODULE = 'toolkit_xulstore'
--- a/toolkit/content/moz.build
+++ b/toolkit/content/moz.build
@@ -17,18 +17,271 @@ if CONFIG['OS_TARGET'] == 'Android':
 if CONFIG['MOZ_ANDROID_CXX_STL'] == 'libc++':
     DEFINES['MOZ_USE_LIBCXX'] = True
 
 if CONFIG['MOZ_BUILD_APP'] == 'mobile/android':
     DEFINES['MOZ_FENNEC'] = True
 
 JAR_MANIFESTS += ['jar.mn']
 
+DEFINES['TOPOBJDIR'] = TOPOBJDIR
+
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
 with Files('aboutTelemetry.*'):
     BUG_COMPONENT = ('Toolkit', 'Telemetry')
 
 with Files('customizeToolbar.*'):
     BUG_COMPONENT = ('Toolkit', 'Toolbars and Toolbar Customization')
 
+with Files('aboutwebrtc/*'):
+    BUG_COMPONENT = ('Core', 'WebRTC')
+
+with Files('gmp-sources/*'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('tests/browser/browser_audio*'):
+    BUG_COMPONENT = ('Core', 'Audio/Video: Playback')
+
+with Files('tests/browser/*block*'):
+    BUG_COMPONENT = ('Core', 'Audio/Video: Playback')
+
+with Files('tests/browser/*silent*'):
+    BUG_COMPONENT = ('Core', 'Audio/Video: Playback')
+
+with Files('tests/browser/*1170531*'):
+    BUG_COMPONENT = ('Firefox', 'Menus')
+
+with Files('tests/browser/*1198465*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/browser/*451286*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/browser/*594509*'):
+    BUG_COMPONENT = ('Toolkit Graveyard', 'XULRunner')
+
+with Files('tests/browser/*982298*'):
+    BUG_COMPONENT = ('Core', 'Layout')
+
+with Files('tests/browser/browser_content_url_annotation.js'):
+    BUG_COMPONENT = ('Toolkit', 'Breakpad Integration')
+
+with Files('tests/browser/browser_default_image_filename.js'):
+    BUG_COMPONENT = ('Firefox', 'File Handling')
+
+with Files('tests/browser/*caret*'):
+    BUG_COMPONENT = ('Firefox', 'Keyboard Navigation')
+
+with Files('tests/browser/*find*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/browser/browser_isSynthetic.js'):
+    BUG_COMPONENT = ('Firefox', 'Tabbed Browsing')
+
+with Files('tests/browser/*mediaPlayback*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('tests/browser/*mute*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('tests/browser/*save*'):
+    BUG_COMPONENT = ('Firefox', 'File Handling')
+
+with Files('tests/browser/*scroll*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('tests/chrome/**'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('tests/chrome/*networking*'):
+    BUG_COMPONENT = ('Core', 'Networking')
+
+with Files('tests/chrome/*autocomplete*'):
+    BUG_COMPONENT = ('Toolkit', 'Autocomplete')
+
+with Files('tests/chrome/*drop*'):
+    BUG_COMPONENT = ('Core', 'Drag and Drop')
+
+with Files('tests/chrome/*1048178*'):
+    BUG_COMPONENT = ('Core', 'XUL')
+
+with Files('tests/chrome/*253481*'):
+    BUG_COMPONENT = ('Core', 'Editor')
+
+with Files('tests/chrome/*263683*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*304188*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*331215*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*360220*'):
+    BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
+
+with Files('tests/chrome/*360437*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*409624*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*418874*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*429723*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*437844*'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+with Files('tests/chrome/rtlchrome/**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('tests/chrome/*451540*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/*554279*'):
+    BUG_COMPONENT = ('Toolkit', 'Toolbars and Toolbar Customization')
+with Files('tests/chrome/*585946*'):
+    BUG_COMPONENT = ('Toolkit', 'Toolbars and Toolbar Customization')
+
+with Files('tests/chrome/*557987*'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: Menus')
+with Files('tests/chrome/*562554*'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: Menus')
+
+with Files('tests/chrome/*570192*'):
+    BUG_COMPONENT = ('Firefox', 'Session Restore')
+
+with Files('tests/chrome/*findbar*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/chrome/test_preferences*'):
+    BUG_COMPONENT = ('Toolkit', 'Preferences')
+
+with Files('tests/mochitest/*autocomplete*'):
+    BUG_COMPONENT = ('Toolkit', 'Autocomplete')
+
+with Files('tests/mochitest/*mousecapture*'):
+    BUG_COMPONENT = ('Core', 'Event Handling')
+
+with Files('tests/reftests/*progress*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('tests/reftests/*multiline*'):
+    BUG_COMPONENT = ('Core', 'XBL')
+
+with Files('tests/reftests/*videocontrols*'):
+    BUG_COMPONENT = ('Toolkit', 'Video/Audio Controls')
+
+with Files('tests/unit/**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+
+with Files('tests/widgets/*audiocontrols*'):
+    BUG_COMPONENT = ('Toolkit', 'Video/Audio Controls')
+with Files('tests/widgets/*1319301*'):
+    BUG_COMPONENT = ('Toolkit', 'Video/Audio Controls')
+with Files('tests/widgets/*898940*'):
+    BUG_COMPONENT = ('Toolkit', 'Video/Audio Controls')
+
+with Files('tests/widgets/*contextmenu*'):
+    BUG_COMPONENT = ('Firefox', 'Menus')
+
+with Files('tests/widgets/*editor*'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: XUL')
+
+with Files('tests/widgets/*menubar*'):
+    BUG_COMPONENT = ('Core', 'XUL')
+
+with Files('tests/widgets/*capture*'):
+    BUG_COMPONENT = ('Core', 'Event Handling')
+
+with Files('tests/widgets/*popup*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+with Files('tests/widgets/*tree*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('tests/widgets/*videocontrols*'):
+    BUG_COMPONENT = ('Toolkit', 'Video/Audio Controls')
+
 with Files('widgets/*'):
     BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
 
-DEFINES['TOPOBJDIR'] = TOPOBJDIR
+with Files('TopLevelVideoDocument.js'):
+    BUG_COMPONENT = ('Toolkit', 'Video/Audio Controls')
+
+with Files('about*'):
+    BUG_COMPONENT = ('Firefox', 'General')
+
+with Files('aboutNetworking*'):
+    BUG_COMPONENT = ('Core', 'Networking')
+
+with Files('aboutProfile*'):
+    BUG_COMPONENT = ('Toolkit', 'Startup and Profile System')
+
+with Files('aboutRights*'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('aboutService*'):
+    BUG_COMPONENT = ('Core', 'DOM: Workers')
+
+with Files('aboutSupport*'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('aboutTelemetry*'):
+    BUG_COMPONENT = ('Toolkit', 'Telemetry')
+
+with Files('autocomplete.css'):
+    BUG_COMPONENT = ('Firefox', 'Search')
+
+with Files('browser-*.js'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('buildconfig.html'):
+    BUG_COMPONENT = ('Toolkit', 'Build Config')
+
+with Files('contentAreaUtils.js'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('customizeToolbar.*'):
+    BUG_COMPONENT = ('Toolkit', 'Toolbars and Toolbar Customization')
+
+with Files('*picker*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('direction*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('edit*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('*find*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('globalOverlay.*'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('menulist.css'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('minimal-xul.css'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('plugins*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('resetProfile*'):
+    BUG_COMPONENT = ('Firefox', 'Migration')
+
+with Files('textbox*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('timepicker*'):
+    BUG_COMPONENT = ('Toolkit', 'XUL Widgets')
+
+with Files('treeUtils.js'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('viewZoomOverlay.js'):
+    BUG_COMPONENT = ('Toolkit', 'General')
--- a/toolkit/locales/moz.build
+++ b/toolkit/locales/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Build Config')
+
 if CONFIG['MOZ_BUILD_APP'] == 'mobile/android':
   DEFINES['MOZ_FENNEC'] = True
 
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
   DEFINES['MOZ_GTK'] = True
 
 JAR_MANIFESTS += ['jar.mn']
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -1,14 +1,168 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('addons/**'):
+    BUG_COMPONENT = ('Toolkit', 'WebExtensions: General')
+
+with Files('docs/**'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('subprocess/**'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('tests/browser/*AsyncPrefs*'):
+    BUG_COMPONENT = ('Core', 'Security: Process Sandboxing')
+
+with Files('tests/browser/*Finder*'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/xpcshell/test_Color.js'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/xpcshell/test_DeferredTask.js'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('tests/xpcshell/test_FinderIterator.js'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('tests/xpcshell/test_Integration.js'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('tests/xpcshell/test_JSONFile.js'):
+    BUG_COMPONENT = ('Toolkit', 'Form Manager')
+
+with Files('tests/xpcshell/test_Match*.js'):
+    BUG_COMPONENT = ('Toolkit', 'WebExtentions: General')
+
+with Files('tests/xpcshell/test_NewTabUtils.js'):
+    BUG_COMPONENT = ('Firefox', 'New Tab Page')
+
+with Files('tests/xpcshell/test_UpdateUtils*.js'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+with Files('tests/xpcshell/test_client_id.js'):
+    BUG_COMPONENT = ('Toolkit', 'Telemetry')
+
+with Files('tests/xpcshell/test_session_recorder.js'):
+    BUG_COMPONENT = ('Toolkit', 'Telemetry')
+
+with Files('AsyncPrefs.jsm'):
+    BUG_COMPONENT = ('Core', 'Security: Process Sandboxing')
+
+with Files('CharsetMenu.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Toolbars and Customization')
+
+with Files('ClientID.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Telemetry')
+
+with Files('Color.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('Console.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Developer Tools: Console')
+
+with Files('DateTimePickerHelper.jsm'):
+    BUG_COMPONENT = ('Core', 'Layout: Form Controls ')
+
+with Files('DeferredTask.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('Finder*.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('FormLikeFactory.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Password Manager')
+
+with Files('IndexedDB.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Web Extensions: General')
+
+with Files('InlineSpellChecker*.jsm'):
+    BUG_COMPONENT = ('Core', 'Spell Checker')
+
+with Files('Integration.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('JSONFile.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Form Manager')
+
+with Files('LightweightThemeConsumer.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Toolbars and Customization')
+
+with Files('LoadContextInfo.jsm'):
+    BUG_COMPONENT = ('Core', 'Networking: Cache')
+
+with Files('Locale.jsm'):
+    BUG_COMPONENT = ('Core', 'Internationalization')
+
+with Files('Memory.jsm'):
+    BUG_COMPONENT = ('Core', 'DOM: Content Processes')
+
+with Files('NLP.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('NewTabUtils.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Tabbed Browser')
+
+with Files('ObjectUtils.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Telemetry')
+
+with Files('PageMenu.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Menus')
+
+with Files('PermissionsUtils.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Add-ons Manager')
+
+with Files('PopupNotifications.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Password Manager')
+
+with Files('PrivateBrowsingUtils.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Private Browsing')
+
+with Files('Promise*.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Async Tooling')
+
+with Files('RemoteController.jsm'):
+    BUG_COMPONENT = ('Core', 'Widget')
+
+with Files('RemoteFinder.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Find Toolbar')
+
+with Files('RemoteSecurityUI.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Tabbed Browser')
+
+with Files('RemoteWebProgress.jsm'):
+    BUG_COMPONENT = ('Core', 'Document Navigation')
+
+with Files('ResponsivenessMonitor.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Migration')
+
+with Files('SessionRecorder.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Telemetry')
+
+with Files('ShortcutUtils.jsm'):
+    BUG_COMPONENT = ('Firefox', 'Toolbars and Customization')
+
+with Files('Sqlite.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Storage')
+
+with Files('UpdateUtils.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'Add-ons Manager')
+
+with Files('WindowsRegistry.jsm'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
 
 TESTING_JS_MODULES += [
     'tests/modules/MockDocument.jsm',
     'tests/modules/PromiseTestUtils.jsm',
     'tests/xpcshell/TestIntegration.jsm',
--- a/toolkit/mozapps/downloads/moz.build
+++ b/toolkit/mozapps/downloads/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Downloads API')
+
 TEST_DIRS += ['tests']
 
 EXTRA_COMPONENTS += [
     'nsHelperAppDlg.manifest',
 ]
 
 EXTRA_PP_COMPONENTS += [
     'nsHelperAppDlg.js',
--- a/toolkit/mozapps/handling/moz.build
+++ b/toolkit/mozapps/handling/moz.build
@@ -1,12 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'File Handling')
+
 EXTRA_COMPONENTS += [
     'nsContentDispatchChooser.js',
     'nsContentDispatchChooser.manifest',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/installer/moz.build
@@ -0,0 +1,11 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'Installer')
+
+with Files('windows/**'):
+    BUG_COMPONENT = ('Toolkit', 'NSIS Installer')
--- a/toolkit/mozapps/preferences/moz.build
+++ b/toolkit/mozapps/preferences/moz.build
@@ -1,7 +1,10 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Preferences')
+
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
--- a/toolkit/system/androidproxy/moz.build
+++ b/toolkit/system/androidproxy/moz.build
@@ -1,11 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox for Android', 'General')
+
 SOURCES += [
     'nsAndroidSystemProxySettings.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/system/gnome/moz.build
+++ b/toolkit/system/gnome/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'Shell Integration')
+
 SOURCES += [
     'nsAlertsIconListener.cpp',
     'nsGnomeModule.cpp',
     'nsSystemAlertsService.cpp',
 ]
 
 if CONFIG['MOZ_ENABLE_GCONF']:
     SOURCES += [
--- a/toolkit/system/osxproxy/moz.build
+++ b/toolkit/system/osxproxy/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Networking')
+
 TEST_DIRS += ['tests/gtest']
 
 SOURCES += [
     'nsOSXSystemProxySettings.mm',
     'ProxyUtils.mm',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/system/unixproxy/moz.build
+++ b/toolkit/system/unixproxy/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Networking')
+
 if CONFIG['MOZ_ENABLE_LIBPROXY']:
     CXXFLAGS += CONFIG['MOZ_LIBPROXY_CFLAGS']
     SOURCES += [
         'nsLibProxySettings.cpp',
     ]
 else:
     SOURCES += [
         'nsUnixSystemProxySettings.cpp',
--- a/toolkit/system/windowsproxy/moz.build
+++ b/toolkit/system/windowsproxy/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Networking')
+
 TEST_DIRS += ['tests/gtest']
 
 SOURCES += [
     'nsWindowsSystemProxySettings.cpp',
     'ProxyUtils.cpp'
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'Startup and Profile System')
+
 if CONFIG['OS_ARCH'] == 'WINNT':
     TEST_DIRS += ['test/win']
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 XPIDL_SOURCES += [
     'nsINativeAppSupport.idl',