Bug 1579218 - Fix JSWindowActorProtocol::Matches() doesn't properly handle webIsolated remote types; r=nika
authorJohn Dai <jdai@mozilla.com>
Fri, 13 Sep 2019 09:51:34 +0000
changeset 493023 59ec879901195eaef3b004fa3f9ce327dbb39e6a
parent 493022 0883e018c595b5fc15b00bc30a5df79882448159
child 493024 4fe410147ca0dfd93c3335ac8ee39c0496b3d27c
push id36571
push userbtara@mozilla.com
push dateFri, 13 Sep 2019 15:46:31 +0000
treeherdermozilla-central@6a36994d2e14 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1579218
milestone71.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 1579218 - Fix JSWindowActorProtocol::Matches() doesn't properly handle webIsolated remote types; r=nika Differential Revision: https://phabricator.services.mozilla.com/D45535
dom/chrome-webidl/JSWindowActor.webidl
dom/ipc/JSWindowActorService.cpp
dom/ipc/JSWindowActorService.h
dom/ipc/tests/JSWindowActor/browser_getActor_filter.js
--- a/dom/chrome-webidl/JSWindowActor.webidl
+++ b/dom/chrome-webidl/JSWindowActor.webidl
@@ -125,19 +125,22 @@ dictionary WindowActorOptions {
    * class in MatchPattern.webidl) which restrict which pages the actor
    * may be instantiated for. If this is defined, only documents URL which match
    * are allowed to have the given actor created for them. Other
    * documents will fail to have their actor constructed, returning nullptr.
    */
   sequence<DOMString> matches;
 
   /**
-   * Optional list of regular expressions for remoteTypes which are
-   * allowed to instantiate this actor. If not passed, all content
-   * processes are allowed to instantiate the actor.
+   * An array of remote type which restricts the actor is allowed to instantiate
+   * in specific process type. If this is defined, the prefix of process type
+   * matches the remote type by prefix match is allowed to instantiate, ex: if
+   * Fission is enabled, the prefix of process type will be `webIsolated`, it
+   * can prefix match remote type either `web` or `webIsolated`. If not passed,
+   * all content processes are allowed to instantiate the actor.
    */
   sequence<DOMString> remoteTypes;
 
   /** This fields are used for configuring individual sides of the actor. */
   WindowActorSidedOptions parent = {};
   WindowActorChildOptions child = {};
 };
 
--- a/dom/ipc/JSWindowActorService.cpp
+++ b/dom/ipc/JSWindowActorService.cpp
@@ -301,34 +301,45 @@ extensions::MatchPatternSet* JSWindowAct
   MatchPatternOptions matchPatternOptions;
   // Make MatchPattern's mSchemes create properly.
   matchPatternOptions.mRestrictSchemes = false;
   mURIMatcher = extensions::MatchPatternSet::Constructor(
       global, patterns, matchPatternOptions, IgnoreErrors());
   return mURIMatcher;
 }
 
+bool JSWindowActorProtocol::RemoteTypePrefixMatches(
+    const nsDependentSubstring& aRemoteType) {
+  for (auto& remoteType : mRemoteTypes) {
+    if (StringBeginsWith(aRemoteType, remoteType)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 bool JSWindowActorProtocol::Matches(BrowsingContext* aBrowsingContext,
                                     nsIURI* aURI,
                                     const nsAString& aRemoteType) {
   MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
   MOZ_ASSERT(aURI, "Must have URI!");
 
-  if (!mRemoteTypes.IsEmpty() && !mRemoteTypes.Contains(aRemoteType)) {
-    return false;
-  }
-
   if (!mAllFrames && aBrowsingContext->GetParent()) {
     return false;
   }
 
   if (!mIncludeChrome && !aBrowsingContext->IsContent()) {
     return false;
   }
 
+  if (!mRemoteTypes.IsEmpty() &&
+      !RemoteTypePrefixMatches(RemoteTypePrefix(aRemoteType))) {
+    return false;
+  }
+
   if (extensions::MatchPatternSet* uriMatcher = GetURIMatcher()) {
     if (!uriMatcher->Matches(aURI)) {
       return false;
     }
   }
 
   return true;
 }
--- a/dom/ipc/JSWindowActorService.h
+++ b/dom/ipc/JSWindowActorService.h
@@ -75,16 +75,17 @@ class JSWindowActorProtocol final : publ
   void AddObservers();
   void RemoveObservers();
   bool Matches(BrowsingContext* aBrowsingContext, nsIURI* aURI,
                const nsAString& aRemoteType);
 
  private:
   explicit JSWindowActorProtocol(const nsAString& aName) : mName(aName) {}
   extensions::MatchPatternSet* GetURIMatcher();
+  bool RemoteTypePrefixMatches(const nsDependentSubstring& aRemoteType);
   ~JSWindowActorProtocol() = default;
 
   nsString mName;
   bool mAllFrames = false;
   bool mIncludeChrome = false;
   nsTArray<nsString> mMatches;
   nsTArray<nsString> mRemoteTypes;
 
--- a/dom/ipc/tests/JSWindowActor/browser_getActor_filter.js
+++ b/dom/ipc/tests/JSWindowActor/browser_getActor_filter.js
@@ -1,12 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
+requestLongerTimeout(2);
+
 declTest("getActor with mismatch", {
   matches: ["*://*/*"],
 
   async test(browser) {
     let parent = browser.browsingContext.currentWindowGlobal;
     ok(parent, "WindowGlobalParent should have value.");
     Assert.throws(
       () => parent.getActor("Test"),
@@ -102,16 +104,44 @@ declTest("getActor with remoteType match
     await ContentTask.spawn(browser, {}, async function() {
       let child = content.getWindowGlobalChild();
       ok(child, "WindowGlobalChild should have value.");
       ok(child.getActor("Test"), "JSWindowActorChild should have value.");
     });
   },
 });
 
+declTest("getActor with iframe remoteType match", {
+  allFrames: true,
+  remoteTypes: ["web"],
+
+  async test(browser) {
+    await ContentTask.spawn(browser, TEST_URL, async function(url) {
+      let child = content.getWindowGlobalChild();
+      ok(child, "WindowGlobalChild should have value.");
+      ok(child.getActor("Test"), "JSWindowActorChild should have value.");
+
+      // Create and append an iframe into the window's document.
+      let frame = content.document.createElement("iframe");
+      frame.src = url;
+      content.document.body.appendChild(frame);
+      await ContentTaskUtils.waitForEvent(frame, "load");
+
+      is(content.frames.length, 1, "There should be an iframe.");
+      await content.SpecialPowers.spawn(frame, [], () => {
+        child = content.getWindowGlobalChild();
+        Assert.ok(
+          child.getActor("Test"),
+          "JSWindowActorChild should have value."
+        );
+      });
+    });
+  },
+});
+
 declTest("getActor with remoteType mismatch", {
   remoteTypes: ["privilegedabout"],
   url: TEST_URL,
 
   async test(browser) {
     let parent = browser.browsingContext.currentWindowGlobal;
     Assert.throws(
       () => parent.getActor("Test"),