Bug 1583251 - P1 - Propagate the targetAgentClusterId to PostMessageEvent::Run(); r=nika
authorTom Tung <ttung@mozilla.com>
Wed, 23 Oct 2019 07:19:48 +0000
changeset 498674 b2c99cc8f60b314cfad5760fd56e45ae195ab5d6
parent 498673 f786d0a35cee212c7b95dbda21e1635af332ce8c
child 498675 51bb06ee4062fe6356268096ff3f9ec3efe47618
push id98599
push userttung@mozilla.com
push dateWed, 23 Oct 2019 07:22:53 +0000
treeherderautoland@058946a415aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1583251
milestone72.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 1583251 - P1 - Propagate the targetAgentClusterId to PostMessageEvent::Run(); r=nika Differential Revision: https://phabricator.services.mozilla.com/D48347
docshell/base/BrowsingContext.cpp
dom/base/PostMessageEvent.cpp
dom/base/PostMessageEvent.h
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsGlobalWindowOuter.h
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -1006,22 +1006,26 @@ void BrowsingContext::PostMessageMoz(JSC
     return;
   }
 
   RefPtr<BrowsingContext> sourceBc;
   PostMessageData data;
   data.targetOrigin() = aTargetOrigin;
   data.subjectPrincipal() = &aSubjectPrincipal;
   RefPtr<nsGlobalWindowInner> callerInnerWindow;
+  // We don't need to get the caller's agentClusterId since that is used for
+  // checking whehter it's okay to sharing memory (and it's not allowed to share
+  // memory cross processes)
   if (!nsGlobalWindowOuter::GatherPostMessageData(
           aCx, aTargetOrigin, getter_AddRefs(sourceBc), data.origin(),
           getter_AddRefs(data.targetOriginURI()),
           getter_AddRefs(data.callerPrincipal()),
           getter_AddRefs(callerInnerWindow),
-          getter_AddRefs(data.callerDocumentURI()), aError)) {
+          getter_AddRefs(data.callerDocumentURI()),
+          /* aCallerAgentClusterId */ nullptr, aError)) {
     return;
   }
   data.source() = sourceBc;
   data.isFromPrivateWindow() =
       callerInnerWindow &&
       nsScriptErrorBase::ComputeIsFromPrivateWindow(callerInnerWindow);
 
   JS::Rooted<JS::Value> transferArray(aCx);
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -3,16 +3,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 "PostMessageEvent.h"
 
 #include "MessageEvent.h"
 #include "mozilla/dom/BlobBinding.h"
+#include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileList.h"
 #include "mozilla/dom/FileListBinding.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/PMessagePort.h"
@@ -26,29 +27,28 @@
 #include "nsIScriptError.h"
 #include "nsNetUtil.h"
 #include "nsPresContext.h"
 #include "nsQueryObject.h"
 
 namespace mozilla {
 namespace dom {
 
-PostMessageEvent::PostMessageEvent(BrowsingContext* aSource,
-                                   const nsAString& aCallerOrigin,
-                                   nsGlobalWindowOuter* aTargetWindow,
-                                   nsIPrincipal* aProvidedPrincipal,
-                                   const Maybe<uint64_t>& aCallerWindowID,
-                                   nsIURI* aCallerDocumentURI,
-                                   bool aIsFromPrivateWindow)
+PostMessageEvent::PostMessageEvent(
+    BrowsingContext* aSource, const nsAString& aCallerOrigin,
+    nsGlobalWindowOuter* aTargetWindow, nsIPrincipal* aProvidedPrincipal,
+    const Maybe<uint64_t>& aCallerWindowID, nsIURI* aCallerDocumentURI,
+    bool aIsFromPrivateWindow, const Maybe<nsID>& aCallerAgentClusterId)
     : Runnable("dom::PostMessageEvent"),
       mSource(aSource),
       mCallerOrigin(aCallerOrigin),
       mTargetWindow(aTargetWindow),
       mProvidedPrincipal(aProvidedPrincipal),
       mCallerWindowID(aCallerWindowID),
+      mCallerAgentClusterId(aCallerAgentClusterId),
       mCallerDocumentURI(aCallerDocumentURI),
       mIsFromPrivateWindow(aIsFromPrivateWindow) {}
 
 PostMessageEvent::~PostMessageEvent() {}
 
 NS_IMETHODIMP
 PostMessageEvent::Run() {
   // Note: We don't init this AutoJSAPI with targetWindow, because we do not
@@ -157,16 +157,24 @@ PostMessageEvent::Run() {
     }
   }
 
   IgnoredErrorResult rv;
   JS::Rooted<JS::Value> messageData(cx);
   nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
       do_QueryObject(targetWindow);
 
+  // XXX cloneDataPolicy will be used in P3
+  JS::CloneDataPolicy cloneDataPolicy;
+  MOZ_DIAGNOSTIC_ASSERT(targetWindow);
+  if (mCallerAgentClusterId.isSome() &&
+      targetWindow->CanShareMemory(mCallerAgentClusterId.ref())) {
+    cloneDataPolicy.allowSharedMemory();
+  }
+
   StructuredCloneHolder* holder;
   if (mHolder.constructed<StructuredCloneHolder>()) {
     mHolder.ref<StructuredCloneHolder>().Read(targetWindow->AsGlobal(), cx,
                                               &messageData, rv);
     holder = &mHolder.ref<StructuredCloneHolder>();
   } else {
     MOZ_ASSERT(mHolder.constructed<ipc::StructuredCloneData>());
     mHolder.ref<ipc::StructuredCloneData>().Read(cx, &messageData, rv);
--- a/dom/base/PostMessageEvent.h
+++ b/dom/base/PostMessageEvent.h
@@ -33,30 +33,31 @@ class BrowsingContext;
 class PostMessageEvent final : public Runnable {
  public:
   NS_DECL_NSIRUNNABLE
 
   // aCallerWindowID should not be 0.
   PostMessageEvent(BrowsingContext* aSource, const nsAString& aCallerOrigin,
                    nsGlobalWindowOuter* aTargetWindow,
                    nsIPrincipal* aProvidedPrincipal, uint64_t aCallerWindowID,
-                   nsIURI* aCallerDocumentURI)
+                   nsIURI* aCallerDocumentURI,
+                   const Maybe<nsID>& aCallerAgentClusterId)
       : PostMessageEvent(aSource, aCallerOrigin, aTargetWindow,
                          aProvidedPrincipal, Some(aCallerWindowID),
-                         aCallerDocumentURI, false) {}
+                         aCallerDocumentURI, false, aCallerAgentClusterId) {}
 
   // To be used if there is no WindowID for the PostMessage caller's window (for
   // example because it lives in a different process).
   PostMessageEvent(BrowsingContext* aSource, const nsAString& aCallerOrigin,
                    nsGlobalWindowOuter* aTargetWindow,
                    nsIPrincipal* aProvidedPrincipal, nsIURI* aCallerDocumentURI,
                    bool aIsFromPrivateWindow)
       : PostMessageEvent(aSource, aCallerOrigin, aTargetWindow,
                          aProvidedPrincipal, Nothing(), aCallerDocumentURI,
-                         aIsFromPrivateWindow) {}
+                         aIsFromPrivateWindow, Nothing()) {}
 
   void Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
              JS::Handle<JS::Value> aTransfer, JS::CloneDataPolicy aClonePolicy,
              ErrorResult& aError) {
     mHolder.construct<StructuredCloneHolder>(
         StructuredCloneHolder::CloningSupported,
         StructuredCloneHolder::TransferringSupported,
         JS::StructuredCloneScope::SameProcessSameThread);
@@ -71,33 +72,35 @@ class PostMessageEvent final : public Ru
         aMessageData);
   }
 
  private:
   PostMessageEvent(BrowsingContext* aSource, const nsAString& aCallerOrigin,
                    nsGlobalWindowOuter* aTargetWindow,
                    nsIPrincipal* aProvidedPrincipal,
                    const Maybe<uint64_t>& aCallerWindowID,
-                   nsIURI* aCallerDocumentURI, bool aIsFromPrivateWindow);
+                   nsIURI* aCallerDocumentURI, bool aIsFromPrivateWindow,
+                   const Maybe<nsID>& aCallerAgentClusterId);
   ~PostMessageEvent();
 
   void Dispatch(nsGlobalWindowInner* aTargetWindow, Event* aEvent);
 
   void DispatchError(JSContext* aCx, nsGlobalWindowInner* aTargetWindow,
                      mozilla::dom::EventTarget* aEventTarget);
 
   RefPtr<BrowsingContext> mSource;
   nsString mCallerOrigin;
   RefPtr<nsGlobalWindowOuter> mTargetWindow;
   nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
   // If the postMessage call was made on a WindowProxy whose Window lives in a
   // separate process then mHolder will contain a StructuredCloneData, else
   // it'll contain a StructuredCloneHolder.
   MaybeOneOf<StructuredCloneHolder, ipc::StructuredCloneData> mHolder;
   Maybe<uint64_t> mCallerWindowID;
+  const Maybe<nsID> mCallerAgentClusterId;
   nsCOMPtr<nsIURI> mCallerDocumentURI;
   // This is only set to a relevant value if mCallerWindowID doesn't contain a
   // value.
   bool mIsFromPrivateWindow;
 };
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -5847,17 +5847,18 @@ WindowProxyHolder nsGlobalWindowOuter::G
   return WindowProxyHolder(mBrowsingContext);
 }
 
 /* static */
 bool nsGlobalWindowOuter::GatherPostMessageData(
     JSContext* aCx, const nsAString& aTargetOrigin, BrowsingContext** aSource,
     nsAString& aOrigin, nsIURI** aTargetOriginURI,
     nsIPrincipal** aCallerPrincipal, nsGlobalWindowInner** aCallerInnerWindow,
-    nsIURI** aCallerDocumentURI, ErrorResult& aError) {
+    nsIURI** aCallerDocumentURI, Maybe<nsID>* aCallerAgentClusterId,
+    ErrorResult& aError) {
   //
   // Window.postMessage is an intentional subversion of the same-origin policy.
   // As such, this code must be particularly careful in the information it
   // exposes to calling code.
   //
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
   //
 
@@ -5933,16 +5934,22 @@ bool nsGlobalWindowOuter::GatherPostMess
   if (!nsContentUtils::IsCallerChrome() && callerInnerWin &&
       callerInnerWin->GetOuterWindowInternal()) {
     NS_ADDREF(*aSource = callerInnerWin->GetOuterWindowInternal()
                              ->GetBrowsingContext());
   } else {
     *aSource = nullptr;
   }
 
+  if (aCallerAgentClusterId && callerInnerWin &&
+      callerInnerWin->GetDocGroup()) {
+    *aCallerAgentClusterId =
+        Some(callerInnerWin->GetDocGroup()->AgentClusterId());
+  }
+
   callerInnerWin.forget(aCallerInnerWindow);
 
   return true;
 }
 
 bool nsGlobalWindowOuter::GetPrincipalForPostMessage(
     const nsAString& aTargetOrigin, nsIURI* aTargetOriginURI,
     nsIPrincipal* aCallerPrincipal, nsIPrincipal& aSubjectPrincipal,
@@ -6040,36 +6047,38 @@ void nsGlobalWindowOuter::PostMessageMoz
                                               nsIPrincipal& aSubjectPrincipal,
                                               ErrorResult& aError) {
   RefPtr<BrowsingContext> sourceBc;
   nsAutoString origin;
   nsCOMPtr<nsIURI> targetOriginURI;
   nsCOMPtr<nsIPrincipal> callerPrincipal;
   RefPtr<nsGlobalWindowInner> callerInnerWindow;
   nsCOMPtr<nsIURI> callerDocumentURI;
-  if (!GatherPostMessageData(aCx, aTargetOrigin, getter_AddRefs(sourceBc),
-                             origin, getter_AddRefs(targetOriginURI),
-                             getter_AddRefs(callerPrincipal),
-                             getter_AddRefs(callerInnerWindow),
-                             getter_AddRefs(callerDocumentURI), aError)) {
+  Maybe<nsID> callerAgentClusterId = Nothing();
+  if (!GatherPostMessageData(
+          aCx, aTargetOrigin, getter_AddRefs(sourceBc), origin,
+          getter_AddRefs(targetOriginURI), getter_AddRefs(callerPrincipal),
+          getter_AddRefs(callerInnerWindow), getter_AddRefs(callerDocumentURI),
+          &callerAgentClusterId, aError)) {
     return;
   }
 
   nsCOMPtr<nsIPrincipal> providedPrincipal;
   if (!GetPrincipalForPostMessage(aTargetOrigin, targetOriginURI,
                                   callerPrincipal, aSubjectPrincipal,
                                   getter_AddRefs(providedPrincipal))) {
     return;
   }
 
   // Create and asynchronously dispatch a runnable which will handle actual DOM
   // event creation and dispatch.
   RefPtr<PostMessageEvent> event = new PostMessageEvent(
       sourceBc, origin, this, providedPrincipal,
-      callerInnerWindow ? callerInnerWindow->WindowID() : 0, callerDocumentURI);
+      callerInnerWindow ? callerInnerWindow->WindowID() : 0, callerDocumentURI,
+      callerAgentClusterId);
 
   JS::CloneDataPolicy clonePolicy;
   if (GetDocGroup() && callerInnerWindow &&
       callerInnerWindow->CanShareMemory(GetDocGroup()->AgentClusterId())) {
     clonePolicy.allowSharedMemory();
   }
   event->Write(aCx, aMessage, aTransfer, clonePolicy, aError);
   if (NS_WARN_IF(aError.Failed())) {
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -998,26 +998,29 @@ class nsGlobalWindowOuter final : public
    *                               postMessage call.
    *
    * @param aCallerInnerWindow [out] Inner window of the caller of
    * postMessage, or null if the incumbent global is not a Window.
    *
    * @param aCallerDocumentURI [out] The URI of the document of the incumbent
    * global if it's a Window, null otherwise.
    *
+   * @param aCallerAgentCluterId [out] If a non-nullptr is passed, it would
+   * return the caller's agent cluster id.
+   *
    * @param aError [out] The error, if any.
    *
    * @return Whether the postMessage call should continue or return now.
    */
   static bool GatherPostMessageData(
       JSContext* aCx, const nsAString& aTargetOrigin,
       mozilla::dom::BrowsingContext** aSource, nsAString& aOrigin,
       nsIURI** aTargetOriginURI, nsIPrincipal** aCallerPrincipal,
       nsGlobalWindowInner** aCallerInnerWindow, nsIURI** aCallerDocumentURI,
-      mozilla::ErrorResult& aError);
+      Maybe<nsID>* aCallerAgentClusterId, mozilla::ErrorResult& aError);
 
   // Ask the user if further dialogs should be blocked, if dialogs are currently
   // being abused. This is used in the cases where we have no modifiable UI to
   // show, in that case we show a separate dialog to ask this question.
   bool ConfirmDialogIfNeeded();
 
   // Helper called after moving/resizing, to update docShell's presContext
   // if we have caused a resolution change by moving across monitors.