Bug 1326339 - Store top level outer content window id in http transaction and connMgr. r=mayhemer
authorKershaw Chang <kechang@mozilla.com>
Thu, 09 Mar 2017 02:55:00 -0500
changeset 346836 379ac27cbef7fddf32b40ddfd0b11a78fb1aef9d
parent 346835 50a0ca4800c14484161587adb16a19499f3c2e11
child 346837 4c2eaf534ed7ef20b6bf331807c0a15be591dd85
push id31479
push userkwierso@gmail.com
push dateFri, 10 Mar 2017 00:33:39 +0000
treeherdermozilla-central@35398cae65c1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1326339
milestone55.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 1326339 - Store top level outer content window id in http transaction and connMgr. r=mayhemer
netwerk/ipc/NeckoChannelParams.ipdlh
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpConnectionMgr.h
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -126,16 +126,17 @@ struct HttpChannelOpenArgs
   uint32_t                    initialRwin;
   bool                        blockAuthPrompt;
   bool                        suspendAfterSynthesizeResponse;
   bool                        allowStaleCacheContent;
   nsCString                   contentTypeHint;
   nsCString                   channelId;
   uint64_t                    contentWindowId;
   nsCString                   preferredAlternativeType;
+  uint64_t                    topLevelOuterContentWindowId;
 };
 
 struct HttpChannelConnectArgs
 {
   uint32_t registrarId;
   bool shouldIntercept;
 };
 
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -195,16 +195,17 @@ HttpBaseChannel::HttpBaseChannel()
   , mFetchCacheMode(nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT)
   , mOnStartRequestCalled(false)
   , mOnStopRequestCalled(false)
   , mAfterOnStartRequestBegun(false)
   , mTransferSize(0)
   , mDecodedBodySize(0)
   , mEncodedBodySize(0)
   , mContentWindowId(0)
+  , mTopLevelOuterContentWindowId(0)
   , mRequireCORSPreflight(false)
   , mReportCollector(new ConsoleReportCollector())
   , mForceMainDocumentChannel(false)
   , mIsTrackingResource(false)
 {
   LOG(("Creating HttpBaseChannel @%p\n", this));
 
   // Subfields of unions cannot be targeted in an initializer list.
@@ -3826,16 +3827,39 @@ HttpBaseChannel::EnsureRequestContextID(
     }
 
     // Set the load group connection scope on the transaction
     rootLoadGroup->GetRequestContextID(&mRequestContextID);
     return true;
 }
 
 void
+HttpBaseChannel::EnsureTopLevelOuterContentWindowId()
+{
+  if (mTopLevelOuterContentWindowId) {
+    return;
+  }
+
+  nsCOMPtr<nsILoadContext> loadContext;
+  GetCallback(loadContext);
+  if (!loadContext) {
+    return;
+  }
+
+  nsCOMPtr<mozIDOMWindowProxy> topWindow;
+  loadContext->GetTopWindow(getter_AddRefs(topWindow));
+  if (!topWindow) {
+    return;
+  }
+
+  mTopLevelOuterContentWindowId =
+    nsPIDOMWindowOuter::From(topWindow)->WindowID();
+}
+
+void
 HttpBaseChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders)
 {
   MOZ_RELEASE_ASSERT(!mRequestObserversCalled);
 
   mRequireCORSPreflight = true;
   mUnsafeHeaders = aUnsafeHeaders;
 }
 
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -353,16 +353,21 @@ public: /* Necko internal use only... */
     // the new mUploadStream.
     void EnsureUploadStreamIsCloneableComplete(nsresult aStatus);
 
     void SetIsTrackingResource()
     {
       mIsTrackingResource = true;
     }
 
+    void SetTopLevelOuterContentWindowId(uint64_t aTopLevelOuterContentWindowId)
+    {
+      mTopLevelOuterContentWindowId = aTopLevelOuterContentWindowId;
+    }
+
 protected:
   // Handle notifying listener, removing from loadgroup if request failed.
   void     DoNotifyListener();
   virtual void DoNotifyListenerCleanup() = 0;
 
   // drop reference to listener, its callbacks, and the progress sink
   void ReleaseListeners();
 
@@ -582,16 +587,19 @@ protected:
 
   nsID mRequestContextID;
   bool EnsureRequestContextID();
 
   // ID of the top-level document's inner window this channel is being
   // originated from.
   uint64_t mContentWindowId;
 
+  uint64_t mTopLevelOuterContentWindowId;
+  void EnsureTopLevelOuterContentWindowId();
+
   bool                              mRequireCORSPreflight;
   nsTArray<nsCString>               mUnsafeHeaders;
 
   nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
 
   // Holds the name of the preferred alt-data type.
   nsCString mPreferredCachedAltDataType;
   // Holds the name of the alternative data type the channel returned.
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -2142,16 +2142,17 @@ HttpChannelChild::ContinueAsyncOpen()
   // This id identifies the inner window's top-level document,
   // which changes on every new load or navigation.
   uint64_t contentWindowId = 0;
   if (tabChild) {
     MOZ_ASSERT(tabChild->WebNavigation());
     nsCOMPtr<nsIDocument> document = tabChild->GetDocument();
     if (document) {
       contentWindowId = document->InnerWindowID();
+      mTopLevelOuterContentWindowId = document->OuterWindowID();
     }
   }
   SetTopLevelContentWindowId(contentWindowId);
 
   HttpChannelOpenArgs openArgs;
   // No access to HttpChannelOpenArgs members, but they each have a
   // function with the struct name that returns a ref.
   SerializeURI(mURI, openArgs.uri());
@@ -2240,16 +2241,17 @@ HttpChannelChild::ContinueAsyncOpen()
   mRequestContextID.ToProvidedString(rcid);
   openArgs.requestContextID().AssignASCII(rcid);
 
   char chid[NSID_LENGTH];
   mChannelId.ToProvidedString(chid);
   openArgs.channelId().AssignASCII(chid);
 
   openArgs.contentWindowId() = contentWindowId;
+  openArgs.topLevelOuterContentWindowId() = mTopLevelOuterContentWindowId;
 
   if (tabChild && !tabChild->IPCOpen()) {
     return NS_ERROR_FAILURE;
   }
 
   ContentChild* cc = static_cast<ContentChild*>(gNeckoChild->Manager());
   if (cc->IsShuttingDown()) {
     return NS_ERROR_FAILURE;
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -125,17 +125,18 @@ HttpChannelParent::Init(const HttpChanne
                        a.entityID(), a.chooseApplicationCache(),
                        a.appCacheClientID(), a.allowSpdy(), a.allowAltSvc(), a.beConservative(),
                        a.loadInfo(), a.synthesizedResponseHead(),
                        a.synthesizedSecurityInfoSerialization(),
                        a.cacheKey(), a.requestContextID(), a.preflightArgs(),
                        a.initialRwin(), a.blockAuthPrompt(),
                        a.suspendAfterSynthesizeResponse(),
                        a.allowStaleCacheContent(), a.contentTypeHint(),
-                       a.channelId(), a.contentWindowId(), a.preferredAlternativeType());
+                       a.channelId(), a.contentWindowId(), a.preferredAlternativeType(),
+                       a.topLevelOuterContentWindowId());
   }
   case HttpChannelCreationArgs::THttpChannelConnectArgs:
   {
     const HttpChannelConnectArgs& cArgs = aArgs.get_HttpChannelConnectArgs();
     return ConnectChannel(cArgs.registrarId(), cArgs.shouldIntercept());
   }
   default:
     NS_NOTREACHED("unknown open type");
@@ -323,17 +324,18 @@ HttpChannelParent::DoAsyncOpen(  const U
                                  const OptionalCorsPreflightArgs& aCorsPreflightArgs,
                                  const uint32_t&            aInitialRwin,
                                  const bool&                aBlockAuthPrompt,
                                  const bool&                aSuspendAfterSynthesizeResponse,
                                  const bool&                aAllowStaleCacheContent,
                                  const nsCString&           aContentTypeHint,
                                  const nsCString&           aChannelId,
                                  const uint64_t&            aContentWindowId,
-                                 const nsCString&           aPreferredAlternativeType)
+                                 const nsCString&           aPreferredAlternativeType,
+                                 const uint64_t&            aTopLevelOuterContentWindowId)
 {
   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
   if (!uri) {
     // URIParams does MOZ_ASSERT if null, but we need to protect opt builds from
     // null deref here.
     return false;
   }
   nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI);
@@ -374,16 +376,17 @@ HttpChannelParent::DoAsyncOpen(  const U
   mChannel = do_QueryObject(channel, &rv);
   if (NS_FAILED(rv)) {
     return SendFailedAsyncOpen(rv);
   }
 
   // Set the channelId allocated in child to the parent instance
   mChannel->SetChannelId(aChannelId);
   mChannel->SetTopLevelContentWindowId(aContentWindowId);
+  mChannel->SetTopLevelOuterContentWindowId(aTopLevelOuterContentWindowId);
 
   mChannel->SetWarningReporter(this);
   mChannel->SetTimingEnabled(true);
   if (mPBOverride != kPBOverride_Unset) {
     mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
   }
 
   if (doResumeAt)
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -143,17 +143,18 @@ protected:
               const OptionalCorsPreflightArgs& aCorsPreflightArgs,
               const uint32_t&            aInitialRwin,
               const bool&                aBlockAuthPrompt,
               const bool&                aSuspendAfterSynthesizeResponse,
               const bool&                aAllowStaleCacheContent,
               const nsCString&           aContentTypeHint,
               const nsCString&           aChannelId,
               const uint64_t&            aContentWindowId,
-              const nsCString&           aPreferredAlternativeType);
+              const nsCString&           aPreferredAlternativeType,
+              const uint64_t&            aTopLevelOuterContentWindowId);
 
   virtual mozilla::ipc::IPCResult RecvSetPriority(const int16_t& priority) override;
   virtual mozilla::ipc::IPCResult RecvSetClassOfService(const uint32_t& cos) override;
   virtual mozilla::ipc::IPCResult RecvSetCacheTokenCachedCharset(const nsCString& charset) override;
   virtual mozilla::ipc::IPCResult RecvSuspend() override;
   virtual mozilla::ipc::IPCResult RecvResume() override;
   virtual mozilla::ipc::IPCResult RecvCancel(const nsresult& status) override;
   virtual mozilla::ipc::IPCResult RecvRedirect2Verify(const nsresult& result,
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -987,20 +987,23 @@ nsHttpChannel::SetupTransaction()
     NS_QueryNotificationCallbacks(mCallbacks,
                                   mLoadGroup,
                                   NS_GET_IID(nsIHttpPushListener),
                                   getter_AddRefs(pushListener));
     if (pushListener) {
         mCaps |= NS_HTTP_ONPUSH_LISTENER;
     }
 
+    EnsureTopLevelOuterContentWindowId();
+
     nsCOMPtr<nsIAsyncInputStream> responseStream;
     rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead,
                             mUploadStream, mUploadStreamHasHeaders,
                             NS_GetCurrentThread(), callbacks, this,
+                            mTopLevelOuterContentWindowId,
                             getter_AddRefs(responseStream));
     if (NS_FAILED(rv)) {
         mTransaction = nullptr;
         return rv;
     }
 
     mTransaction->SetClassOfService(mClassOfService);
     SetupTransactionRequestContext();
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -82,16 +82,17 @@ nsHttpConnectionMgr::nsHttpConnectionMgr
     , mNumActiveConns(0)
     , mNumIdleConns(0)
     , mNumSpdyActiveConns(0)
     , mNumHalfOpenConns(0)
     , mTimeOfNextWakeUp(UINT64_MAX)
     , mPruningNoTraffic(false)
     , mTimeoutTickArmed(false)
     , mTimeoutTickNext(1)
+    , mCurrentTopLevelOuterContentWindowId(0)
 {
     LOG(("Creating nsHttpConnectionMgr @%p\n", this));
 }
 
 nsHttpConnectionMgr::~nsHttpConnectionMgr()
 {
     LOG(("Destroying nsHttpConnectionMgr @%p\n", this));
     if (mTimeoutTick)
@@ -2423,16 +2424,54 @@ nsHttpConnectionMgr::ActivateTimeoutTick
         mTimeoutTick->SetTarget(mSocketThreadTarget);
     }
 
     MOZ_ASSERT(!mTimeoutTickArmed, "timer tick armed");
     mTimeoutTickArmed = true;
     mTimeoutTick->Init(this, 1000, nsITimer::TYPE_REPEATING_SLACK);
 }
 
+class UINT64Wrapper : public ARefBase
+{
+public:
+    explicit UINT64Wrapper(uint64_t aUint64) : mUint64(aUint64) {}
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UINT64Wrapper)
+
+    uint64_t GetValue()
+    {
+        return mUint64;
+    }
+private:
+    uint64_t mUint64;
+    virtual ~UINT64Wrapper() = default;
+};
+
+nsresult
+nsHttpConnectionMgr::UpdateCurrentTopLevelOuterContentWindowId(
+    uint64_t aWindowId)
+{
+    RefPtr<UINT64Wrapper> windowIdWrapper = new UINT64Wrapper(aWindowId);
+    return PostEvent(
+        &nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId,
+        0,
+        windowIdWrapper);
+}
+
+void
+nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId(
+    int32_t, ARefBase *param)
+{
+    MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+    mCurrentTopLevelOuterContentWindowId =
+        static_cast<UINT64Wrapper*>(param)->GetValue();
+    LOG(("nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId"
+         " id=%" PRIu64 "\n",
+         mCurrentTopLevelOuterContentWindowId));
+}
+
 void
 nsHttpConnectionMgr::TimeoutTick()
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
     MOZ_ASSERT(mTimeoutTick, "no readtimeout tick");
 
     LOG(("nsHttpConnectionMgr::TimeoutTick active=%d\n", mNumActiveConns));
     // The next tick will be between 1 second and 1 hr
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -187,16 +187,18 @@ public:
 
     void ResetIPFamilyPreference(nsHttpConnectionInfo *);
 
     uint16_t MaxRequestDelay() { return mMaxRequestDelay; }
 
     // public, so that the SPDY/http2 seesions can activate
     void ActivateTimeoutTick();
 
+    nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId);
+
 private:
     virtual ~nsHttpConnectionMgr();
 
     class nsHalfOpenSocket;
 
     // nsConnectionEntry
     //
     // mCT maps connection info hash key to nsConnectionEntry object, which
@@ -439,16 +441,17 @@ private:
     void OnMsgCompleteUpgrade      (int32_t, ARefBase *);
     void OnMsgUpdateParam          (int32_t, ARefBase *);
     void OnMsgDoShiftReloadConnectionCleanup (int32_t, ARefBase *);
     void OnMsgProcessFeedback      (int32_t, ARefBase *);
     void OnMsgProcessAllSpdyPendingQ (int32_t, ARefBase *);
     void OnMsgUpdateRequestTokenBucket (int32_t, ARefBase *);
     void OnMsgVerifyTraffic (int32_t, ARefBase *);
     void OnMsgPruneNoTraffic (int32_t, ARefBase *);
+    void OnMsgUpdateCurrentTopLevelOuterContentWindowId (int32_t, ARefBase *);
 
     // Total number of active connections in all of the ConnectionEntry objects
     // that are accessed from mCT connection table.
     uint16_t mNumActiveConns;
     // Total number of idle connections in all of the ConnectionEntry objects
     // that are accessed from mCT connection table.
     uint16_t mNumIdleConns;
     // Total number of spdy connections which are a subset of the active conns
@@ -483,14 +486,15 @@ private:
 
     // Read Timeout Tick handlers
     void TimeoutTick();
 
     // For diagnostics
     void OnMsgPrintDiagnostics(int32_t, ARefBase *);
 
     nsCString mLogData;
+    uint64_t mCurrentTopLevelOuterContentWindowId;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // !nsHttpConnectionMgr_h__
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -130,16 +130,17 @@ nsHttpTransaction::nsHttpTransaction()
     , mContentDecoding(false)
     , mContentDecodingCheck(false)
     , mDeferredSendProgress(false)
     , mWaitingOnPipeOut(false)
     , mReportedStart(false)
     , mReportedResponseHeader(false)
     , mForTakeResponseHead(nullptr)
     , mResponseHeadTaken(false)
+    , mTopLevelOuterContentWindowId(0)
     , mSubmittedRatePacing(false)
     , mPassedRatePacing(false)
     , mSynchronousRatePaceRequest(false)
     , mClassOfService(0)
     , m0RTTInProgress(false)
     , mTransportStatus(NS_OK)
 {
     LOG(("Creating nsHttpTransaction @%p\n", this));
@@ -182,27 +183,30 @@ nsresult
 nsHttpTransaction::Init(uint32_t caps,
                         nsHttpConnectionInfo *cinfo,
                         nsHttpRequestHead *requestHead,
                         nsIInputStream *requestBody,
                         bool requestBodyHasHeaders,
                         nsIEventTarget *target,
                         nsIInterfaceRequestor *callbacks,
                         nsITransportEventSink *eventsink,
+                        uint64_t topLevelOuterContentWindowId,
                         nsIAsyncInputStream **responseBody)
 {
     nsresult rv;
 
     LOG(("nsHttpTransaction::Init [this=%p caps=%x]\n", this, caps));
 
     MOZ_ASSERT(cinfo);
     MOZ_ASSERT(requestHead);
     MOZ_ASSERT(target);
     MOZ_ASSERT(NS_IsMainThread());
 
+    mTopLevelOuterContentWindowId = topLevelOuterContentWindowId;
+
     mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv);
     if (NS_FAILED(rv)) return rv;
 
     bool activityDistributorActive;
     rv = mActivityDistributor->GetIsActive(&activityDistributorActive);
     if (NS_SUCCEEDED(rv) && activityDistributorActive) {
         // there are some observers registered at activity distributor, gather
         // nsISupports for the channel that called Init()
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -69,29 +69,33 @@ public:
     // @param reqBody
     //        the request body (POST or PUT data stream)
     // @param reqBodyIncludesHeaders
     //        fun stuff to support NPAPI plugins.
     // @param target
     //        the dispatch target were notifications should be sent.
     // @param callbacks
     //        the notification callbacks to be given to PSM.
+    // @param topLevelOuterContentWindowId
+    //        indicate the top level outer content window in which
+    //        this transaction is being loaded.
     // @param responseBody
     //        the input stream that will contain the response data.  async
     //        wait on this input stream for data.  on first notification,
     //        headers should be available (check transaction status).
     //
     MOZ_MUST_USE nsresult Init(uint32_t               caps,
                                nsHttpConnectionInfo  *connInfo,
                                nsHttpRequestHead     *reqHeaders,
                                nsIInputStream        *reqBody,
                                bool                   reqBodyIncludesHeaders,
                                nsIEventTarget        *consumerTarget,
                                nsIInterfaceRequestor *callbacks,
                                nsITransportEventSink *eventsink,
+                               uint64_t               topLevelOuterContentWindowId,
                                nsIAsyncInputStream  **responseBody);
 
     // attributes
     nsHttpResponseHead    *ResponseHead()   { return mHaveAllHeaders ? mResponseHead : nullptr; }
     nsISupports           *SecurityInfo()   { return mSecurityInfo; }
 
     nsIEventTarget        *ConsumerTarget() { return mConsumerTarget; }
     nsISupports           *HttpChannel()    { return mChannel; }
@@ -161,16 +165,21 @@ public:
     mozilla::TimeStamp GetRequestStart();
     mozilla::TimeStamp GetResponseStart();
     mozilla::TimeStamp GetResponseEnd();
 
     int64_t GetTransferSize() { return mTransferSize; }
 
     MOZ_MUST_USE bool Do0RTT() override;
     MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged /* ignored */) override;
+
+    uint64_t TopLevelOuterContentWindowId()
+    {
+        return mTopLevelOuterContentWindowId;
+    }
 private:
     friend class DeleteHttpTransaction;
     virtual ~nsHttpTransaction();
 
     MOZ_MUST_USE nsresult Restart();
     char    *LocateHttpStart(char *buf, uint32_t len,
                              bool aAllowPartialMatch);
     MOZ_MUST_USE nsresult ParseLine(nsACString &line);
@@ -328,16 +337,18 @@ private:
 
     // protected by nsHttp::GetLock()
     nsHttpResponseHead             *mForTakeResponseHead;
     bool                            mResponseHeadTaken;
 
     // The time when the transaction was submitted to the Connection Manager
     TimeStamp                       mPendingTime;
 
+    uint64_t                        mTopLevelOuterContentWindowId;
+
 // For Rate Pacing via an EventTokenBucket
 public:
     // called by the connection manager to run this transaction through the
     // token bucket. If the token bucket admits the transaction immediately it
     // returns true. The function is called repeatedly until it returns true.
     bool TryToRunPacedRequest();
 
     // ATokenBucketEvent pure virtual implementation. Called by the token bucket