Bug 966439 - BroadcastChannel API - patch 2 - close() method, r=smaug

This commit is contained in:
Andrea Marchesini 2015-01-14 11:50:34 +00:00
parent 65afdf13d8
commit 9a3e22bc9c
5 changed files with 112 additions and 3 deletions

View File

@ -219,6 +219,7 @@ BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow,
, mChannel(aChannel)
, mIsKeptAlive(false)
, mInnerID(0)
, mState(StateActive)
{
// Window can be null in workers
}
@ -322,7 +323,18 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
}
void
BroadcastChannel::PostMessage(const nsAString& aMessage)
BroadcastChannel::PostMessage(const nsAString& aMessage, ErrorResult& aRv)
{
if (mState != StateActive) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
PostMessageInternal(aMessage);
}
void
BroadcastChannel::PostMessageInternal(const nsAString& aMessage)
{
if (mActor) {
nsRefPtr<PostMessageRunnable> runnable =
@ -338,6 +350,21 @@ BroadcastChannel::PostMessage(const nsAString& aMessage)
mPendingMessages.AppendElement(aMessage);
}
void
BroadcastChannel::Close()
{
if (mState != StateActive) {
return;
}
if (mPendingMessages.IsEmpty()) {
Shutdown();
} else {
MOZ_ASSERT(!mActor);
mState = StateClosing;
}
}
void
BroadcastChannel::ActorFailed()
{
@ -349,6 +376,10 @@ BroadcastChannel::ActorCreated(ipc::PBackgroundChild* aActor)
{
MOZ_ASSERT(aActor);
if (mState == StateClosed) {
return;
}
PBroadcastChannelChild* actor =
aActor->SendPBroadcastChannelConstructor(mPrincipalInfo, mOrigin, mChannel);
@ -359,15 +390,21 @@ BroadcastChannel::ActorCreated(ipc::PBackgroundChild* aActor)
// Flush pending messages.
for (uint32_t i = 0; i < mPendingMessages.Length(); ++i) {
PostMessage(mPendingMessages[i]);
PostMessageInternal(mPendingMessages[i]);
}
mPendingMessages.Clear();
if (mState == StateClosing) {
Shutdown();
}
}
void
BroadcastChannel::Shutdown()
{
mState = StateClosed;
// If shutdown() is called we have to release the reference if we still keep
// it.
if (mIsKeptAlive) {

View File

@ -53,7 +53,9 @@ public:
aName = mChannel;
}
void PostMessage(const nsAString& aMessage);
void PostMessage(const nsAString& aMessage, ErrorResult& aRv);
void Close();
EventHandlerNonNull* GetOnmessage();
void SetOnmessage(EventHandlerNonNull* aCallback);
@ -81,6 +83,8 @@ private:
~BroadcastChannel();
void PostMessageInternal(const nsAString& aMessage);
void UpdateMustKeepAlive();
nsRefPtr<BroadcastChannelChild> mActor;
@ -95,6 +99,12 @@ private:
bool mIsKeptAlive;
uint64_t mInnerID;
enum {
StateActive,
StateClosing,
StateClosed
} mState;
};
} // namespace dom

View File

@ -6,3 +6,4 @@ support-files =
[test_broadcastchannel_basic.html]
[test_broadcastchannel_self.html]
[test_broadcastchannel_worker.html]
[test_broadcastchannel_close.html]

View File

@ -0,0 +1,58 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for BroadcastChannel</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">
SimpleTest.waitForExplicitFinish();
var receiver = new BroadcastChannel('foo');
var sequence = [ '2', 'done' ];
receiver.onmessage = function(e) {
if (!sequence.length) {
ok (false, 'No more data is expected');
return;
}
var data = sequence.shift();
is(e.data, data);
if (!sequence.length) {
SimpleTest.executeSoon(function() {
SimpleTest.finish();
});
}
}
var x = new BroadcastChannel('foo');
x.close();
try {
x.postMessage('1');
ok(false, "PostMessage should throw if called after a close().");
} catch(e) {
ok(true, "PostMessage should throw if called after a close().");
}
var y = new BroadcastChannel('foo');
y.postMessage('2');
y.close();
try {
y.postMessage('3');
ok(false, "PostMessage should throw if called after a close().");
} catch(e) {
ok(true, "PostMessage should throw if called after a close().");
}
var z = new BroadcastChannel('foo');
z.postMessage('done');
</script>
</body>
</html>

View File

@ -12,7 +12,10 @@
interface BroadcastChannel : EventTarget {
readonly attribute DOMString name;
[Throws]
void postMessage(DOMString message);
void close();
attribute EventHandler onmessage;
};