Bug 1220007 P2 Make InterceptedChannel's collect logs locally and only flush to nsIChannel on main thread r=bz a=ritu
authorBen Kelly <ben@wanderview.com>
Wed, 18 Nov 2015 13:07:42 -0800
changeset 303767 3f63e0a21969587cb4fb7116573763f8c55e2cb4
parent 303766 f0b7aa7305fffc9d0bd76d716892bcacf173fb0b
child 303768 20b9fbb31b4e9fda097dcf731f31ddc2156e630e
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, ritu
bugs1220007
milestone44.0a2
Bug 1220007 P2 Make InterceptedChannel's collect logs locally and only flush to nsIChannel on main thread r=bz a=ritu
CLOBBER
dom/workers/ServiceWorkerEvents.cpp
modules/libjar/InterceptedJARChannel.cpp
modules/libjar/InterceptedJARChannel.h
netwerk/base/nsINetworkInterceptController.idl
netwerk/protocol/http/InterceptedChannel.cpp
netwerk/protocol/http/InterceptedChannel.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Merge day clobber
\ No newline at end of file
+Bug 1220007 Clobber since .idl changes not getting picked up on emulator-L in b2g-inbound
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -108,20 +108,17 @@ namespace {
 
 void
 AsyncLog(nsIInterceptedChannel *aInterceptedChannel,
          const nsACString& aRespondWithScriptSpec,
          uint32_t aRespondWithLineNumber, uint32_t aRespondWithColumnNumber,
          const nsACString& aMessageName, const nsTArray<nsString>& aParams)
 {
   MOZ_ASSERT(aInterceptedChannel);
-  // Since the intercepted channel is kept alive and paused while handling
-  // the FetchEvent, we are guaranteed the reporter is stable on the worker
-  // thread.
-  nsIConsoleReportCollector* reporter =
+  nsCOMPtr<nsIConsoleReportCollector> reporter =
     aInterceptedChannel->GetConsoleReportCollector();
   if (reporter) {
     reporter->AddConsoleReport(nsIScriptError::errorFlag,
                                NS_LITERAL_CSTRING("Service Worker Interception"),
                                nsContentUtils::eDOM_PROPERTIES,
                                aRespondWithScriptSpec,
                                aRespondWithLineNumber,
                                aRespondWithColumnNumber,
--- a/modules/libjar/InterceptedJARChannel.cpp
+++ b/modules/libjar/InterceptedJARChannel.cpp
@@ -118,16 +118,22 @@ InterceptedJARChannel::SetChannelInfo(mo
 {
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
   return aChannelInfo->ResurrectInfoOnChannel(mChannel);
 }
 
+NS_IMETHODIMP
+InterceptedJARChannel::GetConsoleReportCollector(nsIConsoleReportCollector**)
+{
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
 void
 InterceptedJARChannel::NotifyController()
 {
   nsresult rv = NS_NewPipe(getter_AddRefs(mSynthesizedInput),
                            getter_AddRefs(mResponseBody),
                            0, UINT32_MAX, true, true);
   NS_ENSURE_SUCCESS_VOID(rv);
 
@@ -141,14 +147,8 @@ InterceptedJARChannel::NotifyController(
   rv = dispatcher->Dispatch();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     rv = ResetInterception();
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
         "Failed to resume intercepted network request");
   }
   mController = nullptr;
 }
-
-nsIConsoleReportCollector*
-InterceptedJARChannel::GetConsoleReportCollector() const
-{
-  return nullptr;
-}
--- a/modules/libjar/InterceptedJARChannel.h
+++ b/modules/libjar/InterceptedJARChannel.h
@@ -48,17 +48,14 @@ class InterceptedJARChannel : public nsI
 public:
   InterceptedJARChannel(nsJARChannel* aChannel,
                         nsINetworkInterceptController* aController);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIINTERCEPTEDCHANNEL
 
   void NotifyController();
-
-  virtual nsIConsoleReportCollector*
-  GetConsoleReportCollector() const override;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // InterceptedJARChannel_h
--- a/netwerk/base/nsINetworkInterceptController.idl
+++ b/netwerk/base/nsINetworkInterceptController.idl
@@ -2,16 +2,17 @@
 /* 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 "nsISupports.idl"
 #include "nsIContentPolicyBase.idl"
 
 interface nsIChannel;
+interface nsIConsoleReportCollector;
 interface nsIOutputStream;
 interface nsIURI;
 
 %{C++
 #include "nsIConsoleReportCollector.h"
 namespace mozilla {
 namespace dom {
 class ChannelInfo;
@@ -23,17 +24,17 @@ class ChannelInfo;
 
 /**
  * Interface to allow implementors of nsINetworkInterceptController to control the behaviour
  * of intercepted channels without tying implementation details of the interception to
  * the actual channel. nsIInterceptedChannel is expected to be implemented by objects
  * which do not implement nsIChannel.
  */
 
-[scriptable, uuid(ea78e439-cc42-4b2d-a42b-85ab55a149d1)]
+[scriptable, uuid(231bb567-90e1-4973-9728-7dab93ab29a8)]
 interface nsIInterceptedChannel : nsISupports
 {
     /**
      * Instruct a channel that has been intercepted to continue with the original
      * network request.
      */
     void resetInterception();
 
@@ -82,26 +83,27 @@ interface nsIInterceptedChannel : nsISup
     void setChannelInfo(in ChannelInfo channelInfo);
 
     /**
      * Get the internal load type from the underlying channel.
      */
     [noscript]
     readonly attribute nsContentPolicyType internalContentPolicyType;
 
+    [noscript]
+    readonly attribute nsIConsoleReportCollector consoleReportCollector;
+
 %{C++
-    // Allow access to the inner channel as a ConsoleReportCollector off
-    // the main thread.  Pure C++ method here to avoid requiring an
-    // AddRef() during QI.  Callers should not save the returned pointer.
-    // May return nullptr.
-    //
-    // Note: Only safe to use OMT prior to resetInterception(),
-    //       finishSynthesizedResponse(), and cancel().
-    virtual nsIConsoleReportCollector*
-    GetConsoleReportCollector() const = 0;
+    already_AddRefed<nsIConsoleReportCollector>
+    GetConsoleReportCollector()
+    {
+      nsCOMPtr<nsIConsoleReportCollector> reporter;
+      GetConsoleReportCollector(getter_AddRefs(reporter));
+      return reporter.forget();
+    }
 %}
 };
 
 /**
  * Interface to allow consumers to dispatch the fetch event asynchronously.
  * Consumers get access to this interface by calling channelIntercepted(),
  * and they can choose to either dispatch() immediately or do that at some
  * later time.
--- a/netwerk/protocol/http/InterceptedChannel.cpp
+++ b/netwerk/protocol/http/InterceptedChannel.cpp
@@ -8,16 +8,17 @@
 
 #include "InterceptedChannel.h"
 #include "nsInputStreamPump.h"
 #include "nsIPipe.h"
 #include "nsIStreamListener.h"
 #include "nsHttpChannel.h"
 #include "HttpChannelChild.h"
 #include "nsHttpResponseHead.h"
+#include "mozilla/ConsoleReportCollector.h"
 #include "mozilla/dom/ChannelInfo.h"
 
 namespace mozilla {
 namespace net {
 
 extern bool
 WillRedirect(const nsHttpResponseHead * response);
 
@@ -32,16 +33,17 @@ DoAddCacheEntryHeaders(nsHttpChannel *se
                        nsHttpRequestHead *requestHead,
                        nsHttpResponseHead *responseHead,
                        nsISupports *securityInfo);
 
 NS_IMPL_ISUPPORTS(InterceptedChannelBase, nsIInterceptedChannel)
 
 InterceptedChannelBase::InterceptedChannelBase(nsINetworkInterceptController* aController)
 : mController(aController)
+, mReportCollector(new ConsoleReportCollector())
 {
 }
 
 InterceptedChannelBase::~InterceptedChannelBase()
 {
 }
 
 NS_IMETHODIMP
@@ -102,16 +104,25 @@ InterceptedChannelBase::DoSynthesizeHead
 
     nsAutoCString header = aName + NS_LITERAL_CSTRING(": ") + aValue;
     // Overwrite any existing header.
     nsresult rv = (*mSynthesizedResponseHead)->ParseHeaderLine(header.get());
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
 }
 
+NS_IMETHODIMP
+InterceptedChannelBase::GetConsoleReportCollector(nsIConsoleReportCollector** aCollectorOut)
+{
+  MOZ_ASSERT(aCollectorOut);
+  nsCOMPtr<nsIConsoleReportCollector> ref = mReportCollector;
+  ref.forget(aCollectorOut);
+  return NS_OK;
+}
+
 InterceptedChannelChrome::InterceptedChannelChrome(nsHttpChannel* aChannel,
                                                    nsINetworkInterceptController* aController,
                                                    nsICacheEntry* aEntry)
 : InterceptedChannelBase(aController)
 , mChannel(aChannel)
 , mSynthesizedCacheEntry(aEntry)
 {
   nsresult rv = mChannel->GetApplyConversion(&mOldApplyConversion);
@@ -129,40 +140,32 @@ InterceptedChannelChrome::NotifyControll
   mChannel->SetApplyConversion(false);
 
   nsresult rv = mSynthesizedCacheEntry->OpenOutputStream(0, getter_AddRefs(mResponseBody));
   NS_ENSURE_SUCCESS_VOID(rv);
 
   DoNotifyController();
 }
 
-nsIConsoleReportCollector*
-InterceptedChannelChrome::GetConsoleReportCollector() const
-{
-  // The ConsoleReportCollector should only be used when the inner channel is
-  // stable.  Nothing should try to use it once we return to the main thread
-  // and clear the inner channel.
-  MOZ_ASSERT(mChannel);
-  return mChannel;
-}
-
 NS_IMETHODIMP
 InterceptedChannelChrome::GetChannel(nsIChannel** aChannel)
 {
   NS_IF_ADDREF(*aChannel = mChannel);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptedChannelChrome::ResetInterception()
 {
   if (!mChannel) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  mReportCollector->FlushConsoleReports(mChannel);
+
   mSynthesizedCacheEntry->AsyncDoom(nullptr);
   mSynthesizedCacheEntry = nullptr;
 
   mChannel->SetApplyConversion(mOldApplyConversion);
 
   nsCOMPtr<nsIURI> uri;
   mChannel->GetURI(getter_AddRefs(uri));
 
@@ -195,16 +198,18 @@ InterceptedChannelChrome::SynthesizeHead
 
 NS_IMETHODIMP
 InterceptedChannelChrome::FinishSynthesizedResponse(const nsACString& aFinalURLSpec)
 {
   if (!mChannel) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  mReportCollector->FlushConsoleReports(mChannel);
+
   EnsureSynthesizedResponse();
 
   // If the synthesized response is a redirect, then we want to respect
   // the encoding of whatever is loaded as a result.
   if (WillRedirect(mSynthesizedResponseHead.ref())) {
     nsresult rv = mChannel->SetApplyConversion(mOldApplyConversion);
     NS_ENSURE_SUCCESS(rv, rv);
   }
@@ -268,16 +273,18 @@ NS_IMETHODIMP
 InterceptedChannelChrome::Cancel(nsresult aStatus)
 {
   MOZ_ASSERT(NS_FAILED(aStatus));
 
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
+  mReportCollector->FlushConsoleReports(mChannel);
+
   // we need to use AsyncAbort instead of Cancel since there's no active pump
   // to cancel which will provide OnStart/OnStopRequest to the channel.
   nsresult rv = mChannel->AsyncAbort(aStatus);
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -317,40 +324,32 @@ InterceptedChannelContent::NotifyControl
   nsresult rv = NS_NewPipe(getter_AddRefs(mSynthesizedInput),
                            getter_AddRefs(mResponseBody),
                            0, UINT32_MAX, true, true);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   DoNotifyController();
 }
 
-nsIConsoleReportCollector*
-InterceptedChannelContent::GetConsoleReportCollector() const
-{
-  // The ConsoleReportCollector should only be used when the inner channel is
-  // stable.  Nothing should try to use it once we return to the main thread
-  // and clear the inner channel.
-  MOZ_ASSERT(mChannel);
-  return mChannel;
-}
-
 NS_IMETHODIMP
 InterceptedChannelContent::GetChannel(nsIChannel** aChannel)
 {
   NS_IF_ADDREF(*aChannel = mChannel);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptedChannelContent::ResetInterception()
 {
   if (!mChannel) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  mReportCollector->FlushConsoleReports(mChannel);
+
   mResponseBody = nullptr;
   mSynthesizedInput = nullptr;
 
   mChannel->ResetInterception();
   mChannel = nullptr;
   return NS_OK;
 }
 
@@ -376,16 +375,18 @@ InterceptedChannelContent::SynthesizeHea
 
 NS_IMETHODIMP
 InterceptedChannelContent::FinishSynthesizedResponse(const nsACString& aFinalURLSpec)
 {
   if (NS_WARN_IF(!mChannel)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  mReportCollector->FlushConsoleReports(mChannel);
+
   EnsureSynthesizedResponse();
 
   nsCOMPtr<nsIURI> originalURI;
   mChannel->GetURI(getter_AddRefs(originalURI));
 
   nsCOMPtr<nsIURI> responseURI;
   if (!aFinalURLSpec.IsEmpty()) {
     nsresult rv = NS_NewURI(getter_AddRefs(responseURI), aFinalURLSpec);
@@ -415,16 +416,18 @@ NS_IMETHODIMP
 InterceptedChannelContent::Cancel(nsresult aStatus)
 {
   MOZ_ASSERT(NS_FAILED(aStatus));
 
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
+  mReportCollector->FlushConsoleReports(mChannel);
+
   // we need to use AsyncAbort instead of Cancel since there's no active pump
   // to cancel which will provide OnStart/OnStopRequest to the channel.
   nsresult rv = mChannel->AsyncAbort(aStatus);
   NS_ENSURE_SUCCESS(rv, rv);
   mChannel = nullptr;
   mStreamListener = nullptr;
   return NS_OK;
 }
--- a/netwerk/protocol/http/InterceptedChannel.h
+++ b/netwerk/protocol/http/InterceptedChannel.h
@@ -31,32 +31,35 @@ protected:
   nsCOMPtr<nsINetworkInterceptController> mController;
 
   // The stream to write the body of the synthesized response
   nsCOMPtr<nsIOutputStream> mResponseBody;
 
   // Response head for use when synthesizing
   Maybe<nsAutoPtr<nsHttpResponseHead>> mSynthesizedResponseHead;
 
+  nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
+
   void EnsureSynthesizedResponse();
   void DoNotifyController();
   nsresult DoSynthesizeStatus(uint16_t aStatus, const nsACString& aReason);
   nsresult DoSynthesizeHeader(const nsACString& aName, const nsACString& aValue);
 
   virtual ~InterceptedChannelBase();
 public:
   explicit InterceptedChannelBase(nsINetworkInterceptController* aController);
 
   // Notify the interception controller that the channel has been intercepted
   // and prepare the response body output stream.
   virtual void NotifyController() = 0;
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD GetResponseBody(nsIOutputStream** aOutput) override;
+  NS_IMETHOD GetConsoleReportCollector(nsIConsoleReportCollector** aCollectorOut) override;
 };
 
 class InterceptedChannelChrome : public InterceptedChannelBase
 {
   // The actual channel being intercepted.
   RefPtr<nsHttpChannel> mChannel;
 
   // Writeable cache entry for use when synthesizing a response in a parent process
@@ -77,19 +80,16 @@ public:
   NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
   NS_IMETHOD SynthesizeStatus(uint16_t aStatus, const nsACString& aReason) override;
   NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
   NS_IMETHOD Cancel(nsresult aStatus) override;
   NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
   NS_IMETHOD GetInternalContentPolicyType(nsContentPolicyType *aInternalContentPolicyType) override;
 
   virtual void NotifyController() override;
-
-  virtual nsIConsoleReportCollector*
-  GetConsoleReportCollector() const override;
 };
 
 class InterceptedChannelContent : public InterceptedChannelBase
 {
   // The actual channel being intercepted.
   RefPtr<HttpChannelChild> mChannel;
 
   // Reader-side of the response body when synthesizing in a child proces
@@ -108,17 +108,14 @@ public:
   NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
   NS_IMETHOD SynthesizeStatus(uint16_t aStatus, const nsACString& aReason) override;
   NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
   NS_IMETHOD Cancel(nsresult aStatus) override;
   NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
   NS_IMETHOD GetInternalContentPolicyType(nsContentPolicyType *aInternalContentPolicyType) override;
 
   virtual void NotifyController() override;
-
-  virtual nsIConsoleReportCollector*
-  GetConsoleReportCollector() const override;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // InterceptedChannel_h