Backed out changeset 0659c9235136 (bug 1274363) for memory leaks

--HG--
extra : rebase_source : 7fd1df522bb0cab48ca51d29140036f6a5a6a7cc
This commit is contained in:
Carsten "Tomcat" Book 2016-05-24 09:37:23 +02:00
parent 7ee9eb0799
commit 0ed94efabc
7 changed files with 63 additions and 144 deletions

View File

@ -18,12 +18,16 @@ using namespace ipc;
namespace dom {
BroadcastChannelParent::BroadcastChannelParent(const nsAString& aOriginChannelKey)
BroadcastChannelParent::BroadcastChannelParent(const nsACString& aOrigin,
const nsAString& aChannel,
bool aPrivateBrowsing)
: mService(BroadcastChannelService::GetOrCreate())
, mOriginChannelKey(aOriginChannelKey)
, mOrigin(aOrigin)
, mChannel(aChannel)
, mPrivateBrowsing(aPrivateBrowsing)
{
AssertIsOnBackgroundThread();
mService->RegisterActor(this, mOriginChannelKey);
mService->RegisterActor(this);
}
BroadcastChannelParent::~BroadcastChannelParent()
@ -40,7 +44,7 @@ BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData)
return false;
}
mService->PostMessage(this, aData, mOriginChannelKey);
mService->PostMessage(this, aData, mOrigin, mChannel, mPrivateBrowsing);
return true;
}
@ -53,7 +57,7 @@ BroadcastChannelParent::RecvClose()
return false;
}
mService->UnregisterActor(this, mOriginChannelKey);
mService->UnregisterActor(this);
mService = nullptr;
Unused << Send__delete__(this);
@ -69,33 +73,40 @@ BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy)
if (mService) {
// This object is about to be released and with it, also mService will be
// released too.
mService->UnregisterActor(this, mOriginChannelKey);
mService->UnregisterActor(this);
}
}
void
BroadcastChannelParent::Deliver(const ClonedMessageData& aData)
BroadcastChannelParent::CheckAndDeliver(const ClonedMessageData& aData,
const nsCString& aOrigin,
const nsString& aChannel,
bool aPrivateBrowsing)
{
AssertIsOnBackgroundThread();
// Duplicate the data for this parent.
ClonedMessageData newData(aData);
if (aOrigin == mOrigin &&
aChannel == mChannel &&
aPrivateBrowsing == mPrivateBrowsing) {
// Duplicate the data for this parent.
ClonedMessageData newData(aData);
// Create new BlobParent objects for this message.
for (uint32_t i = 0, len = newData.blobsParent().Length(); i < len; ++i) {
RefPtr<BlobImpl> impl =
static_cast<BlobParent*>(newData.blobsParent()[i])->GetBlobImpl();
// Ricreate the BlobParent for this new message.
for (uint32_t i = 0, len = newData.blobsParent().Length(); i < len; ++i) {
RefPtr<BlobImpl> impl =
static_cast<BlobParent*>(newData.blobsParent()[i])->GetBlobImpl();
PBlobParent* blobParent =
BackgroundParent::GetOrCreateActorForBlobImpl(Manager(), impl);
if (!blobParent) {
return;
PBlobParent* blobParent =
BackgroundParent::GetOrCreateActorForBlobImpl(Manager(), impl);
if (!blobParent) {
return;
}
newData.blobsParent()[i] = blobParent;
}
newData.blobsParent()[i] = blobParent;
Unused << SendNotify(newData);
}
Unused << SendNotify(newData);
}
} // namespace dom

View File

@ -27,10 +27,15 @@ class BroadcastChannelParent final : public PBroadcastChannelParent
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
public:
void Deliver(const ClonedMessageData& aData);
void CheckAndDeliver(const ClonedMessageData& aData,
const nsCString& aOrigin,
const nsString& aChannel,
bool aPrivateBrowsing);
private:
explicit BroadcastChannelParent(const nsAString& aOriginChannelKey);
BroadcastChannelParent(const nsACString& aOrigin,
const nsAString& aChannel,
bool aPrivateBrowsing);
~BroadcastChannelParent();
virtual bool
@ -41,7 +46,9 @@ private:
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
RefPtr<BroadcastChannelService> mService;
nsString mOriginChannelKey;
nsCString mOrigin;
nsString mChannel;
bool mPrivateBrowsing;
};
} // namespace dom

View File

@ -58,52 +58,35 @@ BroadcastChannelService::GetOrCreate()
}
void
BroadcastChannelService::RegisterActor(BroadcastChannelParent* aParent,
const nsAString& aOriginChannelKey)
BroadcastChannelService::RegisterActor(BroadcastChannelParent* aParent)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
MOZ_ASSERT(!mAgents.Contains(aParent));
nsTArray<BroadcastChannelParent*>* parents;
if (!mAgents.Get(aOriginChannelKey, &parents)) {
parents = new nsTArray<BroadcastChannelParent*>();
mAgents.Put(aOriginChannelKey, parents);
}
MOZ_ASSERT(!parents->Contains(aParent));
parents->AppendElement(aParent);
mAgents.PutEntry(aParent);
}
void
BroadcastChannelService::UnregisterActor(BroadcastChannelParent* aParent,
const nsAString& aOriginChannelKey)
BroadcastChannelService::UnregisterActor(BroadcastChannelParent* aParent)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
MOZ_ASSERT(mAgents.Contains(aParent));
nsTArray<BroadcastChannelParent*>* parents;
if (!mAgents.Get(aOriginChannelKey, &parents)) {
MOZ_CRASH("Invalid state");
}
parents->RemoveElement(aParent);
if (parents->IsEmpty()) {
mAgents.Remove(aOriginChannelKey);
}
mAgents.RemoveEntry(aParent);
}
void
BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
const ClonedMessageData& aData,
const nsAString& aOriginChannelKey)
const nsACString& aOrigin,
const nsAString& aChannel,
bool aPrivateBrowsing)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
nsTArray<BroadcastChannelParent*>* parents;
if (!mAgents.Get(aOriginChannelKey, &parents)) {
MOZ_CRASH("Invalid state");
}
MOZ_ASSERT(mAgents.Contains(aParent));
// We need to keep the array alive for the life-time of this operation.
nsTArray<RefPtr<BlobImpl>> blobs;
@ -118,12 +101,13 @@ BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
}
}
for (uint32_t i = 0; i < parents->Length(); ++i) {
BroadcastChannelParent* parent = parents->ElementAt(i);
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
BroadcastChannelParent* parent = iter.Get()->GetKey();
MOZ_ASSERT(parent);
if (parent != aParent) {
parent->Deliver(aData);
parent->CheckAndDeliver(aData, PromiseFlatCString(aOrigin),
PromiseFlatString(aChannel), aPrivateBrowsing);
}
}
}

View File

@ -9,7 +9,7 @@
#include "nsISupportsImpl.h"
#include "nsHashKeys.h"
#include "nsDataHashtable.h"
#include "nsTHashtable.h"
#ifdef XP_WIN
#undef PostMessage
@ -28,22 +28,20 @@ public:
static already_AddRefed<BroadcastChannelService> GetOrCreate();
void RegisterActor(BroadcastChannelParent* aParent,
const nsAString& aOriginChannelKey);
void UnregisterActor(BroadcastChannelParent* aParent,
const nsAString& aOriginChannelKey);
void RegisterActor(BroadcastChannelParent* aParent);
void UnregisterActor(BroadcastChannelParent* aParent);
void PostMessage(BroadcastChannelParent* aParent,
const ClonedMessageData& aData,
const nsAString& aOriginChannelKey);
const nsACString& aOrigin,
const nsAString& aChannel,
bool aPrivateBrowsing);
private:
BroadcastChannelService();
~BroadcastChannelService();
// Raw Pointers because the actors keep alive this service.
nsDataHashtable<nsStringHashKey,
nsTArray<BroadcastChannelParent*>*> mAgents;
nsTHashtable<nsPtrHashKey<BroadcastChannelParent>> mAgents;
};
} // namespace dom

View File

@ -25,4 +25,3 @@ skip-if = buildapp != 'mulet'
skip-if = buildapp != 'mulet'
[test_bfcache.html]
[test_invalidState.html]
[test_ordering.html]

View File

@ -1,65 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for BroadcastChannel.postMessage invalid State</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="content"></div>
<script type="application/javascript">
let c1 = new BroadcastChannel('order');
let c2 = new BroadcastChannel('order');
let c3 = new BroadcastChannel('order');
let events = [];
let doneCount = 0;
function whichBC(bc) {
if (bc == c1) return "c1";
if (bc == c2) return "c2";
if (bc == c3) return "c3";
return "What?!?";
}
function handler(e) {
events.push(e);
if (e.data == 'done') {
doneCount++;
if (doneCount == 2) {
is(events.length, 6, "Correct length");
is(whichBC(events[0].target), "c2", 'target for event 0');
is(events[0].data, 'from c1');
is(whichBC(events[1].target), "c3", 'target for event 1');
is(events[1].data, 'from c1');
is(whichBC(events[2].target), "c1", 'target for event 2');
is(events[2].data, 'from c3');
is(whichBC(events[3].target), "c2", 'target for event 3');
is(events[3].data, 'from c3');
is(whichBC(events[4].target), "c1", 'target for event 4');
is(events[4].data, 'done');
is(whichBC(events[5].target), "c3", 'target for event 5');
is(events[5].data, 'done');
SimpleTest.finish();
}
}
}
c1.onmessage = handler;
c2.onmessage = handler;
c3.onmessage = handler;
c1.postMessage('from c1');
c3.postMessage('from c3');
c2.postMessage('done');
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

View File

@ -471,22 +471,7 @@ BackgroundParentImpl::AllocPBroadcastChannelParent(
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
nsString originChannelKey;
// The format of originChannelKey is:
// <channelName>|pb={true,false}|<origin+OriginAttributes>
originChannelKey.Assign(aChannel);
if (aPrivateBrowsing) {
originChannelKey.AppendLiteral("|pb=true|");
} else {
originChannelKey.AppendLiteral("|pb=false|");
}
originChannelKey.Append(NS_ConvertUTF8toUTF16(aOrigin));
return new BroadcastChannelParent(originChannelKey);
return new BroadcastChannelParent(aOrigin, aChannel, aPrivateBrowsing);
}
namespace {