Bug 1318727 - BroadcastChannel should support data URL, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 30 Nov 2016 15:13:27 +0100
changeset 324813 124b6d7669264412a06cd9885aa34f25768ea880
parent 324812 c72d9641ee848ed3859e4d85eb04b40348df2a39
child 324814 0bdc2dfc9dcc02f29656518b5dc4812d184fbad3
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewerssmaug
bugs1318727
milestone53.0a1
Bug 1318727 - BroadcastChannel should support data URL, r=smaug
caps/nsNullPrincipal.cpp
caps/nsNullPrincipal.h
dom/broadcastchannel/BroadcastChannel.cpp
dom/broadcastchannel/tests/mochitest.ini
dom/broadcastchannel/tests/test_dataURL.html
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundUtils.cpp
ipc/glue/PBackgroundSharedTypes.ipdlh
--- a/caps/nsNullPrincipal.cpp
+++ b/caps/nsNullPrincipal.cpp
@@ -53,32 +53,45 @@ nsNullPrincipal::CreateWithInheritedAttr
 
   RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
   nsresult rv = nullPrin->Init(attrs);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   return nullPrin.forget();
 }
 
 /* static */ already_AddRefed<nsNullPrincipal>
-nsNullPrincipal::Create(const PrincipalOriginAttributes& aOriginAttributes)
+nsNullPrincipal::Create(const PrincipalOriginAttributes& aOriginAttributes,
+                        nsIURI* aURI)
 {
   RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
-  nsresult rv = nullPrin->Init(aOriginAttributes);
+  nsresult rv = nullPrin->Init(aOriginAttributes, aURI);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
 
   return nullPrin.forget();
 }
 
 nsresult
-nsNullPrincipal::Init(const PrincipalOriginAttributes& aOriginAttributes)
+nsNullPrincipal::Init(const PrincipalOriginAttributes& aOriginAttributes,
+                      nsIURI* aURI)
 {
   mOriginAttributes = aOriginAttributes;
 
-  mURI = nsNullPrincipalURI::Create();
-  NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_AVAILABLE);
+  if (aURI) {
+    nsAutoCString scheme;
+    nsresult rv = aURI->GetScheme(scheme);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    NS_ENSURE_TRUE(scheme.EqualsLiteral(NS_NULLPRINCIPAL_SCHEME),
+                   NS_ERROR_NOT_AVAILABLE);
+
+    mURI = aURI;
+  } else {
+    mURI = nsNullPrincipalURI::Create();
+    NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_AVAILABLE);
+  }
 
   return NS_OK;
 }
 
 nsresult
 nsNullPrincipal::GetScriptLocation(nsACString &aStr)
 {
   return mURI->GetSpec(aStr);
--- a/caps/nsNullPrincipal.h
+++ b/caps/nsNullPrincipal.h
@@ -48,19 +48,21 @@ public:
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom);
 
   static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIDocShell* aDocShell);
 
   static already_AddRefed<nsNullPrincipal>
-  Create(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
+  Create(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes(),
+         nsIURI* aURI = nullptr);
 
-  nsresult Init(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
+  nsresult Init(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes(),
+                nsIURI* aURI = nullptr);
 
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
   PrincipalKind Kind() override { return eNullPrincipal; }
 
  protected:
   virtual ~nsNullPrincipal() {}
 
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -88,21 +88,16 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
 
     nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate);
     if (!principal) {
       mRv.Throw(NS_ERROR_FAILURE);
       return true;
     }
 
-    if (NS_WARN_IF(principal->GetIsNullPrincipal())) {
-      mRv.Throw(NS_ERROR_FAILURE);
-      return true;
-    }
-
     mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo);
     if (NS_WARN_IF(mRv.Failed())) {
       return true;
     }
 
     mRv = principal->GetOrigin(mOrigin);
     if (NS_WARN_IF(mRv.Failed())) {
       return true;
@@ -318,21 +313,16 @@ BroadcastChannel::Constructor(const Glob
     }
 
     nsIPrincipal* principal = incumbent->PrincipalOrNull();
     if (!principal) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
 
-    if (NS_WARN_IF(principal->GetIsNullPrincipal())) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return nullptr;
-    }
-
     aRv = principal->GetOrigin(origin);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
--- a/dom/broadcastchannel/tests/mochitest.ini
+++ b/dom/broadcastchannel/tests/mochitest.ini
@@ -17,8 +17,9 @@ support-files =
 [test_broadcastchannel_self.html]
 [test_broadcastchannel_sharedWorker.html]
 [test_broadcastchannel_worker.html]
 [test_broadcastchannel_worker_alive.html]
 [test_bfcache.html]
 [test_invalidState.html]
 [test_ordering.html]
 [test_dataCloning.html]
+[test_dataURL.html]
new file mode 100644
--- /dev/null
+++ b/dom/broadcastchannel/tests/test_dataURL.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for BroadcastChannel in data: URL</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="dataURL">
+var a = new BroadcastChannel('a');
+var b = new BroadcastChannel('a');
+a.onmessage = function(e) { parent.postMessage(e.data, "*"); };
+b.postMessage(42);
+</div>
+
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+onmessage= function(e) {
+  ok(e.data, "42", "BroadcastChannel works with data URLs");
+  SimpleTest.finish();
+}
+
+var url = "data:text/html,<script>" + document.getElementById("dataURL").textContent + "</" + "script>";
+
+var ifr = document.createElement('iframe');
+document.body.appendChild(ifr);
+
+ifr.setAttribute('sandbox', 'allow-scripts');
+ifr.src = url;
+</script>
+</body>
+</html>
+
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -516,21 +516,16 @@ public:
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     NullifyContentParentRAII raii(mContentParent);
 
     nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(mPrincipalInfo);
 
-    if (principal->GetIsNullPrincipal()) {
-      mContentParent->KillHard("BroadcastChannel killed: no null principal.");
-      return NS_OK;
-    }
-
     nsAutoCString origin;
     nsresult rv = principal->GetOrigin(origin);
     if (NS_FAILED(rv)) {
       mContentParent->KillHard("BroadcastChannel killed: principal::GetOrigin failed.");
       return NS_OK;
     }
 
     if (NS_WARN_IF(!mOrigin.Equals(origin))) {
@@ -633,17 +628,16 @@ BackgroundParentImpl::RecvPBroadcastChan
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
   RefPtr<ContentParent> parent = BackgroundParent::GetContentParent(this);
 
   // If the ContentParent is null we are dealing with a same-process actor.
   if (!parent) {
-    MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::TNullPrincipalInfo);
     return IPC_OK();
   }
 
   RefPtr<CheckPrincipalRunnable> runnable =
     new CheckPrincipalRunnable(parent.forget(), aPrincipalInfo, aOrigin);
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
 
   return IPC_OK();
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -57,18 +57,24 @@ PrincipalInfoToPrincipal(const Principal
       }
 
       return principal.forget();
     }
 
     case PrincipalInfo::TNullPrincipalInfo: {
       const NullPrincipalInfo& info =
         aPrincipalInfo.get_NullPrincipalInfo();
-      principal = nsNullPrincipal::Create(info.attrs());
 
+      nsCOMPtr<nsIURI> uri;
+      rv = NS_NewURI(getter_AddRefs(uri), info.spec());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return nullptr;
+      }
+
+      principal = nsNullPrincipal::Create(info.attrs(), uri);
       return principal.forget();
     }
 
     case PrincipalInfo::TContentPrincipalInfo: {
       const ContentPrincipalInfo& info =
         aPrincipalInfo.get_ContentPrincipalInfo();
 
       nsCOMPtr<nsIURI> uri;
@@ -126,17 +132,35 @@ nsresult
 PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
                          PrincipalInfo* aPrincipalInfo)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(aPrincipalInfo);
 
   if (aPrincipal->GetIsNullPrincipal()) {
-    *aPrincipalInfo = NullPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef());
+    nsCOMPtr<nsIURI> uri;
+    nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (NS_WARN_IF(!uri)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    nsAutoCString spec;
+    rv = uri->GetSpec(spec);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    *aPrincipalInfo =
+      NullPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(),
+                        spec);
     return NS_OK;
   }
 
   nsresult rv;
   nsCOMPtr<nsIScriptSecurityManager> secMan =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -186,17 +210,17 @@ PrincipalToPrincipalInfo(nsIPrincipal* a
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (NS_WARN_IF(!uri)) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCString spec;
+  nsAutoCString spec;
   rv = uri->GetSpec(spec);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   *aPrincipalInfo = ContentPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(),
                                          spec);
   return NS_OK;
--- a/ipc/glue/PBackgroundSharedTypes.ipdlh
+++ b/ipc/glue/PBackgroundSharedTypes.ipdlh
@@ -15,16 +15,17 @@ struct ContentPrincipalInfo
 };
 
 struct SystemPrincipalInfo
 { };
 
 struct NullPrincipalInfo
 {
   PrincipalOriginAttributes attrs;
+  nsCString spec;
 };
 
 struct ExpandedPrincipalInfo
 {
   PrincipalOriginAttributes attrs;
   PrincipalInfo[] whitelist;
 };