From 58bd113b8cd525cdcc11b58f0103a10e1f5e1493 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 14 Jan 2015 11:50:35 +0000 Subject: [PATCH] Bug 966439 - BroadcastChannel API - patch 7 - Blob supported, r=bent --- dom/broadcastchannel/BroadcastChannel.cpp | 25 ++++++++----- dom/broadcastchannel/BroadcastChannel.h | 2 +- .../BroadcastChannelChild.cpp | 16 +++++++- dom/broadcastchannel/BroadcastChannelChild.h | 3 +- .../BroadcastChannelParent.cpp | 37 +++++++++++++++---- dom/broadcastchannel/BroadcastChannelParent.h | 4 +- .../BroadcastChannelService.cpp | 6 +-- .../BroadcastChannelService.h | 4 +- dom/broadcastchannel/PBroadcastChannel.ipdl | 11 ++---- .../tests/test_broadcastchannel_any.html | 1 + dom/ipc/StructuredCloneUtils.cpp | 9 +++-- 11 files changed, 80 insertions(+), 38 deletions(-) diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp index a37e342e451..d4802b39074 100644 --- a/dom/broadcastchannel/BroadcastChannel.cpp +++ b/dom/broadcastchannel/BroadcastChannel.cpp @@ -190,18 +190,28 @@ public: return NS_OK; } - BroadcastChannelMessageData message; + ClonedMessageData message; SerializedStructuredCloneBuffer& buffer = message.data(); buffer.data = mData->mBuffer.data(); buffer.dataLength = mData->mBuffer.nbytes(); -#ifdef DEBUG - { - const nsTArray>& blobs = mData->mClosure.mBlobs; - MOZ_ASSERT(blobs.IsEmpty()); + PBackgroundChild* backgroundManager = mActor->Manager(); + MOZ_ASSERT(backgroundManager); + + const nsTArray>& blobs = mData->mClosure.mBlobs; + + if (!blobs.IsEmpty()) { + message.blobsChild().SetCapacity(blobs.Length()); + + for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) { + PBlobChild* blobChild = + BackgroundChild::GetOrCreateActorForBlob(backgroundManager, blobs[i]); + MOZ_ASSERT(blobChild); + + message.blobsChild().AppendElement(blobChild); + } } -#endif mActor->SendPostMessage(message); return NS_OK; @@ -270,9 +280,6 @@ public: virtual bool Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE { if (aStatus >= Canceling) { - WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); - MOZ_ASSERT(workerPrivate); - mChannel->Shutdown(); } diff --git a/dom/broadcastchannel/BroadcastChannel.h b/dom/broadcastchannel/BroadcastChannel.h index f268882e512..dfbae2d1e7e 100644 --- a/dom/broadcastchannel/BroadcastChannel.h +++ b/dom/broadcastchannel/BroadcastChannel.h @@ -24,7 +24,7 @@ class WorkerFeature; } class BroadcastChannelChild; -struct BroadcastChannelMessage; +class BroadcastChannelMessage; class BroadcastChannel MOZ_FINAL : public DOMEventTargetHelper diff --git a/dom/broadcastchannel/BroadcastChannelChild.cpp b/dom/broadcastchannel/BroadcastChannelChild.cpp index 462e1fb82df..647b6107f3e 100644 --- a/dom/broadcastchannel/BroadcastChannelChild.cpp +++ b/dom/broadcastchannel/BroadcastChannelChild.cpp @@ -6,6 +6,8 @@ #include "BroadcastChannelChild.h" #include "BroadcastChannel.h" #include "jsapi.h" +#include "mozilla/dom/ipc/BlobChild.h" +#include "mozilla/dom/File.h" #include "mozilla/dom/MessageEvent.h" #include "mozilla/dom/MessageEventBinding.h" #include "mozilla/dom/StructuredCloneUtils.h" @@ -37,7 +39,7 @@ BroadcastChannelChild::~BroadcastChannelChild() } bool -BroadcastChannelChild::RecvNotify(const BroadcastChannelMessageData& aData) +BroadcastChannelChild::RecvNotify(const ClonedMessageData& aData) { nsCOMPtr helper = mBC; nsCOMPtr eventTarget = do_QueryInterface(helper); @@ -76,6 +78,18 @@ BroadcastChannelChild::RecvNotify(const BroadcastChannelMessageData& aData) cloneData.mData = buffer.data; cloneData.mDataLength = buffer.dataLength; + if (!aData.blobsChild().IsEmpty()) { + cloneData.mClosure.mBlobs.SetCapacity(aData.blobsChild().Length()); + + for (uint32_t i = 0, len = aData.blobsChild().Length(); i < len; ++i) { + nsRefPtr impl = + static_cast(aData.blobsChild()[i])->GetBlobImpl(); + + nsRefPtr blob = new File(mBC->GetOwner(), impl); + cloneData.mClosure.mBlobs.AppendElement(blob); + } + } + JS::Rooted value(cx, JS::NullValue()); if (cloneData.mDataLength && !ReadStructuredClone(cx, cloneData, &value)) { JS_ClearPendingException(cx); diff --git a/dom/broadcastchannel/BroadcastChannelChild.h b/dom/broadcastchannel/BroadcastChannelChild.h index 26ab6886043..8f7a2209262 100644 --- a/dom/broadcastchannel/BroadcastChannelChild.h +++ b/dom/broadcastchannel/BroadcastChannelChild.h @@ -29,8 +29,7 @@ public: mBC = aBC; } - virtual bool RecvNotify(const BroadcastChannelMessageData& aData) - MOZ_OVERRIDE; + virtual bool RecvNotify(const ClonedMessageData& aData) MOZ_OVERRIDE; bool IsActorDestroyed() const { diff --git a/dom/broadcastchannel/BroadcastChannelParent.cpp b/dom/broadcastchannel/BroadcastChannelParent.cpp index 83b360a7a1d..a85929d1185 100644 --- a/dom/broadcastchannel/BroadcastChannelParent.cpp +++ b/dom/broadcastchannel/BroadcastChannelParent.cpp @@ -5,6 +5,8 @@ #include "BroadcastChannelParent.h" #include "BroadcastChannelService.h" +#include "mozilla/dom/File.h" +#include "mozilla/dom/ipc/BlobParent.h" #include "mozilla/ipc/BackgroundParent.h" #include "mozilla/unused.h" @@ -31,8 +33,7 @@ BroadcastChannelParent::~BroadcastChannelParent() } bool -BroadcastChannelParent::RecvPostMessage( - const BroadcastChannelMessageData& aData) +BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData) { AssertIsOnBackgroundThread(); @@ -74,15 +75,37 @@ BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy) } void -BroadcastChannelParent::CheckAndDeliver( - const BroadcastChannelMessageData& aData, - const nsString& aOrigin, - const nsString& aChannel) +BroadcastChannelParent::CheckAndDeliver(const ClonedMessageData& aData, + const nsString& aOrigin, + const nsString& aChannel) { AssertIsOnBackgroundThread(); if (aOrigin == mOrigin && aChannel == mChannel) { - unused << SendNotify(aData); + // We need to duplicate data only if we have blobs. + if (aData.blobsParent().IsEmpty()) { + unused << SendNotify(aData); + return; + } + + // Duplicate the data for this parent. + ClonedMessageData newData(aData); + + // Ricreate the BlobParent for this new message. + for (uint32_t i = 0, len = newData.blobsParent().Length(); i < len; ++i) { + nsRefPtr impl = + static_cast(newData.blobsParent()[i])->GetBlobImpl(); + + PBlobParent* blobParent = + BackgroundParent::GetOrCreateActorForBlobImpl(Manager(), impl); + if (!blobParent) { + return; + } + + newData.blobsParent()[i] = blobParent; + } + + unused << SendNotify(newData); } } diff --git a/dom/broadcastchannel/BroadcastChannelParent.h b/dom/broadcastchannel/BroadcastChannelParent.h index 752d34612e2..193af8b5c37 100644 --- a/dom/broadcastchannel/BroadcastChannelParent.h +++ b/dom/broadcastchannel/BroadcastChannelParent.h @@ -22,7 +22,7 @@ class BroadcastChannelParent MOZ_FINAL : public PBroadcastChannelParent friend class mozilla::ipc::BackgroundParentImpl; public: - void CheckAndDeliver(const BroadcastChannelMessageData& aData, + void CheckAndDeliver(const ClonedMessageData& aData, const nsString& aOrigin, const nsString& aChannel); @@ -32,7 +32,7 @@ private: ~BroadcastChannelParent(); virtual bool - RecvPostMessage(const BroadcastChannelMessageData& aData) MOZ_OVERRIDE; + RecvPostMessage(const ClonedMessageData& aData) MOZ_OVERRIDE; virtual bool RecvClose() MOZ_OVERRIDE; diff --git a/dom/broadcastchannel/BroadcastChannelService.cpp b/dom/broadcastchannel/BroadcastChannelService.cpp index e215d36aa0d..d63c6cbfc7d 100644 --- a/dom/broadcastchannel/BroadcastChannelService.cpp +++ b/dom/broadcastchannel/BroadcastChannelService.cpp @@ -75,7 +75,7 @@ namespace { struct MOZ_STACK_CLASS PostMessageData MOZ_FINAL { PostMessageData(BroadcastChannelParent* aParent, - const BroadcastChannelMessageData& aData, + const ClonedMessageData& aData, const nsAString& aOrigin, const nsAString& aChannel) : mParent(aParent) @@ -93,7 +93,7 @@ struct MOZ_STACK_CLASS PostMessageData MOZ_FINAL } BroadcastChannelParent* mParent; - const BroadcastChannelMessageData& mData; + const ClonedMessageData& mData; const nsString mOrigin; const nsString mChannel; }; @@ -118,7 +118,7 @@ PostMessageEnumerator(nsPtrHashKey* aKey, void* aPtr) void BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent, - const BroadcastChannelMessageData& aData, + const ClonedMessageData& aData, const nsAString& aOrigin, const nsAString& aChannel) { diff --git a/dom/broadcastchannel/BroadcastChannelService.h b/dom/broadcastchannel/BroadcastChannelService.h index 83341d81aa9..01f60079a3e 100644 --- a/dom/broadcastchannel/BroadcastChannelService.h +++ b/dom/broadcastchannel/BroadcastChannelService.h @@ -13,7 +13,7 @@ namespace mozilla { namespace dom { class BroadcastChannelParent; -class BroadcastChannelMessageData; +class ClonedMessageData; class BroadcastChannelService MOZ_FINAL { @@ -26,7 +26,7 @@ public: void UnregisterActor(BroadcastChannelParent* aParent); void PostMessage(BroadcastChannelParent* aParent, - const BroadcastChannelMessageData& aData, + const ClonedMessageData& aData, const nsAString& aOrigin, const nsAString& aChannel); diff --git a/dom/broadcastchannel/PBroadcastChannel.ipdl b/dom/broadcastchannel/PBroadcastChannel.ipdl index 8115283f94e..e06115092b2 100644 --- a/dom/broadcastchannel/PBroadcastChannel.ipdl +++ b/dom/broadcastchannel/PBroadcastChannel.ipdl @@ -3,28 +3,25 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PBackground; +include protocol PBlob; +include DOMTypes; using struct mozilla::SerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h"; namespace mozilla { namespace dom { -struct BroadcastChannelMessageData -{ - SerializedStructuredCloneBuffer data; -}; - // This protocol is used for the BroadcastChannel API protocol PBroadcastChannel { manager PBackground; parent: - PostMessage(BroadcastChannelMessageData message); + PostMessage(ClonedMessageData message); Close(); child: - Notify(BroadcastChannelMessageData message); + Notify(ClonedMessageData message); __delete__(); }; diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_any.html b/dom/broadcastchannel/tests/test_broadcastchannel_any.html index 748f321ac37..e1bbd703408 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_any.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_any.html @@ -19,6 +19,7 @@ var tests = [ new Date(), [ 1, 'test', true, new Date() ], { a: true, b: null, c: new Date(), d: [ true, false, {} ] }, + new Blob([123], { type: 'plain/text' }) ]; var currentTest = null; diff --git a/dom/ipc/StructuredCloneUtils.cpp b/dom/ipc/StructuredCloneUtils.cpp index 349e3ea95c2..724bf779fc0 100644 --- a/dom/ipc/StructuredCloneUtils.cpp +++ b/dom/ipc/StructuredCloneUtils.cpp @@ -26,15 +26,17 @@ namespace { void Error(JSContext* aCx, uint32_t aErrorId) { - MOZ_ASSERT(NS_IsMainThread()); - NS_DOMStructuredCloneError(aCx, aErrorId); + if (NS_IsMainThread()) { + NS_DOMStructuredCloneError(aCx, aErrorId); + } else { + Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR); + } } JSObject* Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, uint32_t aData, void* aClosure) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aClosure); StructuredCloneClosure* closure = @@ -80,7 +82,6 @@ bool Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, JS::Handle aObj, void* aClosure) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aClosure); StructuredCloneClosure* closure =