Bug 1598520 - Don't require nsIChildChannel for process switching, as we don't need this for DocumentChannel either. r=mayhemer,kmag
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 06 Jan 2020 21:58:48 +0000
changeset 509000 3f05a0cebcea103ecd60bbfa0814f97256a86d93
parent 508999 a99bcdc5c85992a6ab33eadd3bafc1d0324019bf
child 509001 4c86fb804a50f22335c90a1d3231e998afaa2449
push id104371
push usermwoodrow@mozilla.com
push dateMon, 06 Jan 2020 22:09:25 +0000
treeherderautoland@35c4ea0dd402 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, kmag
bugs1598520
milestone73.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1598520 - Don't require nsIChildChannel for process switching, as we don't need this for DocumentChannel either. r=mayhemer,kmag Differential Revision: https://phabricator.services.mozilla.com/D57586
docshell/base/ChildProcessChannelListener.cpp
docshell/base/ChildProcessChannelListener.h
docshell/base/nsDocShell.cpp
docshell/base/nsDocShellLoadState.cpp
docshell/base/nsDocShellLoadState.h
dom/ipc/ContentChild.cpp
uriloader/base/nsURILoader.cpp
--- a/docshell/base/ChildProcessChannelListener.cpp
+++ b/docshell/base/ChildProcessChannelListener.cpp
@@ -17,17 +17,17 @@ void ChildProcessChannelListener::Regist
     aCallback(args->mChannel, std::move(args->mRedirects),
               args->mLoadStateLoadFlags, args->mTiming);
   } else {
     mCallbacks.Put(aIdentifier, std::move(aCallback));
   }
 }
 
 void ChildProcessChannelListener::OnChannelReady(
-    nsIChildChannel* aChannel, uint64_t aIdentifier,
+    nsIChannel* aChannel, uint64_t aIdentifier,
     nsTArray<net::DocumentChannelRedirect>&& aRedirects,
     uint32_t aLoadStateLoadFlags, nsDOMNavigationTiming* aTiming) {
   if (auto callback = mCallbacks.GetAndRemove(aIdentifier)) {
     (*callback)(aChannel, std::move(aRedirects), aLoadStateLoadFlags, aTiming);
   } else {
     mChannelArgs.Put(aIdentifier, {aChannel, std::move(aRedirects),
                                    aLoadStateLoadFlags, aTiming});
   }
--- a/docshell/base/ChildProcessChannelListener.h
+++ b/docshell/base/ChildProcessChannelListener.h
@@ -7,42 +7,42 @@
 #ifndef mozilla_dom_ChildProcessChannelListener_h
 #define mozilla_dom_ChildProcessChannelListener_h
 
 #include <functional>
 
 #include "mozilla/net/NeckoChannelParams.h"
 #include "nsDOMNavigationTiming.h"
 #include "nsDataHashtable.h"
-#include "nsIChildChannel.h"
+#include "nsIChannel.h"
 
 namespace mozilla {
 namespace dom {
 
 class ChildProcessChannelListener final {
   NS_INLINE_DECL_REFCOUNTING(ChildProcessChannelListener)
 
-  using Callback = std::function<void(nsIChildChannel*,
+  using Callback = std::function<void(nsIChannel*,
                                       nsTArray<net::DocumentChannelRedirect>&&,
                                       uint32_t, nsDOMNavigationTiming*)>;
 
   void RegisterCallback(uint64_t aIdentifier, Callback&& aCallback);
 
-  void OnChannelReady(nsIChildChannel* aChannel, uint64_t aIdentifier,
+  void OnChannelReady(nsIChannel* aChannel, uint64_t aIdentifier,
                       nsTArray<net::DocumentChannelRedirect>&& aRedirects,
                       uint32_t aLoadStateLoadFlags,
                       nsDOMNavigationTiming* aTiming);
 
   static already_AddRefed<ChildProcessChannelListener> GetSingleton();
 
  private:
   ChildProcessChannelListener() = default;
   ~ChildProcessChannelListener() = default;
   struct CallbackArgs {
-    nsCOMPtr<nsIChildChannel> mChannel;
+    nsCOMPtr<nsIChannel> mChannel;
     nsTArray<net::DocumentChannelRedirect> mRedirects;
     uint32_t mLoadStateLoadFlags;
     RefPtr<nsDOMNavigationTiming> mTiming;
   };
 
   // TODO Backtrack.
   nsDataHashtable<nsUint64HashKey, Callback> mCallbacks;
   nsDataHashtable<nsUint64HashKey, CallbackArgs> mChannelArgs;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -9727,30 +9727,25 @@ nsresult nsDocShell::DoURILoad(nsDocShel
       nestedURI = do_QueryInterface(tempURI);
     }
   } else {
     MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
                "DoURILoad thinks this is a document and InternalLoad does not");
   }
 
   // open a channel for the url
-  nsCOMPtr<nsIChannel> channel;
 
   // If we have a pending channel, use the channel we've already created here.
   // We don't need to set up load flags for our channel, as it has already been
   // created.
-  nsCOMPtr<nsIChildChannel> pendingChannel =
-      aLoadState->GetPendingRedirectedChannel();
-  if (pendingChannel) {
+  nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
+  if (channel) {
     MOZ_ASSERT(!aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC),
                "pending channel for srcdoc load?");
 
-    channel = do_QueryInterface(pendingChannel);
-    MOZ_ASSERT(channel, "nsIChildChannel isn't a nsIChannel?");
-
     // If we have a request outparameter, shove our channel into it.
     if (aRequest) {
       nsCOMPtr<nsIRequest> outRequest = channel;
       outRequest.forget(aRequest);
     }
 
     rv = OpenInitializedChannel(channel, uriLoader,
                                 nsIURILoader::REDIRECTED_CHANNEL);
@@ -12742,44 +12737,38 @@ NS_IMETHODIMP
 nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
   RefPtr<nsDocShell> self = this;
   RefPtr<ChildProcessChannelListener> cpcl =
       ChildProcessChannelListener::GetSingleton();
 
   // Call into InternalLoad with the pending channel when it is received.
   cpcl->RegisterCallback(
       aIdentifier,
-      [self, aHistoryIndex](nsIChildChannel* aChannel,
+      [self, aHistoryIndex](nsIChannel* aChannel,
                             nsTArray<net::DocumentChannelRedirect>&& aRedirects,
                             uint32_t aLoadStateLoadFlags,
                             nsDOMNavigationTiming* aTiming) {
         if (NS_WARN_IF(self->mIsBeingDestroyed)) {
-          nsCOMPtr<nsIRequest> request = do_QueryInterface(aChannel);
-          if (request) {
-            request->Cancel(NS_BINDING_ABORTED);
-          }
+          aChannel->Cancel(NS_BINDING_ABORTED);
           return;
         }
 
         RefPtr<nsDocShellLoadState> loadState;
         nsresult rv = nsDocShellLoadState::CreateFromPendingChannel(
             aChannel, getter_AddRefs(loadState));
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return;
         }
         loadState->SetLoadFlags(aLoadStateLoadFlags);
 
-        if (nsCOMPtr<nsIChannel> channel = do_QueryInterface(aChannel)) {
-          nsCOMPtr<nsIURI> previousURI;
-          uint32_t previousFlags = 0;
-          ExtractLastVisit(channel, getter_AddRefs(previousURI),
-                           &previousFlags);
-          self->SavePreviousRedirectsAndLastVisit(channel, previousURI,
-                                                  previousFlags, aRedirects);
-        }
+        nsCOMPtr<nsIURI> previousURI;
+        uint32_t previousFlags = 0;
+        ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
+        self->SavePreviousRedirectsAndLastVisit(aChannel, previousURI,
+                                                previousFlags, aRedirects);
 
         MOZ_ASSERT(
             (self->mCurrentURI && NS_IsAboutBlank(self->mCurrentURI)) ||
                 !self->mTiming,
             "timing object can't already exists in non-about:blank loads");
         self->mTiming = new nsDOMNavigationTiming(self, aTiming);
 
         // If we're performing a history load, locate the correct history entry,
--- a/docshell/base/nsDocShellLoadState.cpp
+++ b/docshell/base/nsDocShellLoadState.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsDocShellLoadState.h"
 #include "nsIDocShell.h"
 #include "SHEntryParent.h"
 #include "SHEntryChild.h"
 #include "nsISHEntry.h"
 #include "nsIWebNavigation.h"
-#include "nsIChildChannel.h"
+#include "nsIChannel.h"
 #include "ReferrerInfo.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/LoadURIOptionsBinding.h"
 #include "mozilla/StaticPrefs_fission.h"
 
 #include "mozilla/OriginAttributes.h"
 #include "mozilla/NullPrincipal.h"
@@ -85,43 +85,38 @@ nsDocShellLoadState::nsDocShellLoadState
   } else {
     mSHEntry = static_cast<SHEntryChild*>(aLoadState.SHEntry());
   }
 }
 
 nsDocShellLoadState::~nsDocShellLoadState() {}
 
 nsresult nsDocShellLoadState::CreateFromPendingChannel(
-    nsIChildChannel* aPendingChannel, nsDocShellLoadState** aResult) {
-  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aPendingChannel);
-  if (NS_WARN_IF(!channel)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
+    nsIChannel* aPendingChannel, nsDocShellLoadState** aResult) {
   // Create the nsDocShellLoadState object with default state pulled from the
   // passed-in channel.
   nsCOMPtr<nsIURI> uri;
-  nsresult rv = channel->GetURI(getter_AddRefs(uri));
+  nsresult rv = aPendingChannel->GetURI(getter_AddRefs(uri));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(uri);
   loadState->mPendingRedirectedChannel = aPendingChannel;
 
   // Pull relevant state from the channel, and store it on the
   // nsDocShellLoadState.
   nsCOMPtr<nsIURI> originalUri;
-  rv = channel->GetOriginalURI(getter_AddRefs(originalUri));
+  rv = aPendingChannel->GetOriginalURI(getter_AddRefs(originalUri));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   loadState->SetOriginalURI(originalUri);
 
-  nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
+  nsCOMPtr<nsILoadInfo> loadInfo = aPendingChannel->LoadInfo();
   loadState->SetTriggeringPrincipal(loadInfo->TriggeringPrincipal());
 
   // Return the newly created loadState.
   loadState.forget(aResult);
   return NS_OK;
 }
 
 nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
--- a/docshell/base/nsDocShellLoadState.h
+++ b/docshell/base/nsDocShellLoadState.h
@@ -14,17 +14,17 @@
 #include "nsString.h"
 #include "nsDocShellLoadTypes.h"
 
 class nsIContentSecurityPolicy;
 class nsIInputStream;
 class nsISHEntry;
 class nsIURI;
 class nsIDocShell;
-class nsIChildChannel;
+class nsIChannel;
 class nsIReferrerInfo;
 class OriginAttibutes;
 namespace mozilla {
 namespace dom {
 class DocShellLoadStateInit;
 }  // namespace dom
 }  // namespace mozilla
 
@@ -35,17 +35,17 @@ class DocShellLoadStateInit;
 class nsDocShellLoadState final {
  public:
   NS_INLINE_DECL_REFCOUNTING(nsDocShellLoadState);
 
   explicit nsDocShellLoadState(nsIURI* aURI);
   explicit nsDocShellLoadState(
       const mozilla::dom::DocShellLoadStateInit& aLoadState);
 
-  static nsresult CreateFromPendingChannel(nsIChildChannel* aPendingChannel,
+  static nsresult CreateFromPendingChannel(nsIChannel* aPendingChannel,
                                            nsDocShellLoadState** aResult);
 
   static nsresult CreateFromLoadURIOptions(
       nsISupports* aConsumer, nsIURIFixup* aURIFixup, const nsAString& aURI,
       const mozilla::dom::LoadURIOptions& aLoadURIOptions,
       nsDocShellLoadState** aResult);
 
   // Getters and Setters
@@ -195,17 +195,17 @@ class nsDocShellLoadState final {
 
   void SetIsFromProcessingFrameAttributes() {
     mIsFromProcessingFrameAttributes = true;
   }
   bool GetIsFromProcessingFrameAttributes() const {
     return mIsFromProcessingFrameAttributes;
   }
 
-  nsIChildChannel* GetPendingRedirectedChannel() {
+  nsIChannel* GetPendingRedirectedChannel() {
     return mPendingRedirectedChannel;
   }
 
   void SetOriginalURIString(const nsCString& aOriginalURI) {
     mOriginalURIString.emplace(aOriginalURI);
   }
   const mozilla::Maybe<nsCString>& GetOriginalURIString() const {
     return mOriginalURIString;
@@ -360,17 +360,17 @@ class nsDocShellLoadState final {
   nsString mFileName;
 
   // This will be true if this load is triggered by attribute changes.
   // See nsILoadInfo.isFromProcessingFrameAttributes
   bool mIsFromProcessingFrameAttributes;
 
   // If set, a pending cross-process redirected channel should be used to
   // perform the load. The channel will be stored in this value.
-  nsCOMPtr<nsIChildChannel> mPendingRedirectedChannel;
+  nsCOMPtr<nsIChannel> mPendingRedirectedChannel;
 
   // An optional string representation of mURI, before any
   // fixups were applied, so that we can send it to a search
   // engine service if needed.
   mozilla::Maybe<nsCString> mOriginalURIString;
 
   // An optional value to pass to nsIDocShell::setCancelJSEpoch
   // when initiating the load.
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -3723,22 +3723,16 @@ mozilla::ipc::IPCResult ContentChild::Re
     aResolve(
         Tuple<const nsresult&, const Maybe<LoadInfoArgs>&>(rv, loadInfoArgs));
   });
 
   if (NS_FAILED(rv)) {
     return IPC_OK();
   }
 
-  RefPtr<nsIChildChannel> childChannel = do_QueryObject(newChannel);
-  if (!childChannel) {
-    rv = NS_ERROR_UNEXPECTED;
-    return IPC_OK();
-  }
-
   if (httpChild) {
     rv = httpChild->SetChannelId(aArgs.channelId());
     if (NS_FAILED(rv)) {
       return IPC_OK();
     }
 
     rv = httpChild->SetOriginalURI(aArgs.originalURI());
     if (NS_FAILED(rv)) {
@@ -3753,34 +3747,38 @@ mozilla::ipc::IPCResult ContentChild::Re
 
   if (aArgs.init()) {
     HttpBaseChannel::ReplacementChannelConfig config(std::move(*aArgs.init()));
     HttpBaseChannel::ConfigureReplacementChannel(
         newChannel, config,
         HttpBaseChannel::ReplacementReason::DocumentChannel);
   }
 
-  // connect parent.
-  rv = childChannel->ConnectParent(
-      aArgs.registrarId());  // creates parent channel
-  if (NS_FAILED(rv)) {
-    return IPC_OK();
+  if (nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(newChannel)) {
+    // Connect to the parent if this is a remote channel. If it's entirely
+    // handled locally, then we'll call AsyncOpen from the docshell when
+    // we complete the setup
+    rv = childChannel->ConnectParent(
+        aArgs.registrarId());  // creates parent channel
+    if (NS_FAILED(rv)) {
+      return IPC_OK();
+    }
   }
 
   // We need to copy the property bag before signaling that the channel
   // is ready so that the nsDocShell can retrieve the history data when called.
   if (nsCOMPtr<nsIWritablePropertyBag> bag = do_QueryInterface(newChannel)) {
     nsHashPropertyBag::CopyFrom(bag, aArgs.properties());
   }
 
   RefPtr<ChildProcessChannelListener> processListener =
       ChildProcessChannelListener::GetSingleton();
-  // The listener will call completeRedirectSetup on the channel.
+  // The listener will call completeRedirectSetup or asyncOpen on the channel.
   processListener->OnChannelReady(
-      childChannel, aArgs.redirectIdentifier(), std::move(aArgs.redirects()),
+      newChannel, aArgs.redirectIdentifier(), std::move(aArgs.redirects()),
       aArgs.loadStateLoadFlags(), aArgs.timing().refOr(nullptr));
 
   // scopeExit will call CrossProcessRedirectFinished(rv) here
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvStartDelayedAutoplayMediaComponents(
     BrowsingContext* aContext) {
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -710,47 +710,48 @@ NS_IMETHODIMP nsURILoader::OpenURI(nsICh
     nsAutoCString spec;
     uri->GetAsciiSpec(spec);
     LOG(("nsURILoader::OpenURI for %s", spec.get()));
   }
 
   nsCOMPtr<nsIStreamListener> loader;
   nsresult rv = OpenChannel(channel, aFlags, aWindowContext, false,
                             getter_AddRefs(loader));
+  if (NS_FAILED(rv)) {
+    if (rv == NS_ERROR_WONT_HANDLE_CONTENT) {
+      // Not really an error, from this method's point of view
+      return NS_OK;
+    }
+  }
 
-  if (NS_SUCCEEDED(rv)) {
-    if (aFlags & nsIURILoader::REDIRECTED_CHANNEL) {
-      // Our channel was redirected from another process, so doesn't need to
-      // be opened again. However, it does need its listener hooked up
-      // correctly.
-      nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(channel);
-      MOZ_ASSERT(childChannel);
-      if (!childChannel) {
-        return NS_ERROR_UNEXPECTED;
-      }
-
+  if (aFlags & nsIURILoader::REDIRECTED_CHANNEL) {
+    // Our channel was redirected from another process, so doesn't need to
+    // be opened again. However, it does need its listener hooked up
+    // correctly.
+    if (nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(channel)) {
       return childChannel->CompleteRedirectSetup(loader, nullptr);
     }
 
-    // this method is not complete!!! Eventually, we should first go
-    // to the content listener and ask them for a protocol handler...
-    // if they don't give us one, we need to go to the registry and get
-    // the preferred protocol handler.
-
-    // But for now, I'm going to let necko do the work for us....
-    rv = channel->AsyncOpen(loader);
+    // It's possible for the redirected channel to not implement
+    // nsIChildChannel and be entirely local (like srcdoc). In that case we
+    // can just open the local instance and it will work.
+  }
 
-    // no content from this load - that's OK.
-    if (rv == NS_ERROR_NO_CONTENT) {
-      LOG(("  rv is NS_ERROR_NO_CONTENT -- doing nothing"));
-      rv = NS_OK;
-    }
-  } else if (rv == NS_ERROR_WONT_HANDLE_CONTENT) {
-    // Not really an error, from this method's point of view
-    rv = NS_OK;
+  // This method is not complete. Eventually, we should first go
+  // to the content listener and ask them for a protocol handler...
+  // if they don't give us one, we need to go to the registry and get
+  // the preferred protocol handler.
+
+  // But for now, I'm going to let necko do the work for us....
+  rv = channel->AsyncOpen(loader);
+
+  // no content from this load - that's OK.
+  if (rv == NS_ERROR_NO_CONTENT) {
+    LOG(("  rv is NS_ERROR_NO_CONTENT -- doing nothing"));
+    return NS_OK;
   }
   return rv;
 }
 
 nsresult nsURILoader::OpenChannel(nsIChannel* channel, uint32_t aFlags,
                                   nsIInterfaceRequestor* aWindowContext,
                                   bool aChannelIsOpen,
                                   nsIStreamListener** aListener) {