Bug 1215092 - WebSocketEventService and WebSocket discovering - part 4 - MessageAvailable event, r=michal

This commit is contained in:
Andrea Marchesini 2015-10-28 19:11:25 +00:00
parent 2e6a2a322f
commit 24c39d6717
9 changed files with 125 additions and 31 deletions

View File

@ -1852,14 +1852,20 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
return NS_OK;
}
uint16_t messageType = nsIWebSocketEventListener::TYPE_STRING;
// Create appropriate JS object for message
JS::Rooted<JS::Value> jsData(aCx);
if (aIsBinary) {
if (mBinaryType == dom::BinaryType::Blob) {
messageType = nsIWebSocketEventListener::TYPE_BLOB;
nsresult rv = nsContentUtils::CreateBlobBuffer(aCx, GetOwner(), aData,
&jsData);
NS_ENSURE_SUCCESS(rv, rv);
} else if (mBinaryType == dom::BinaryType::Arraybuffer) {
messageType = nsIWebSocketEventListener::TYPE_ARRAYBUFFER;
JS::Rooted<JSObject*> arrayBuf(aCx);
nsresult rv = nsContentUtils::CreateArrayBuffer(aCx, aData,
arrayBuf.address());
@ -1879,6 +1885,10 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
jsData.setString(jsString);
}
mImpl->mService->WebSocketMessageAvailable(mImpl->mChannel->Serial(),
mImpl->mInnerWindowID,
aData, messageType);
// create an event that uses the MessageEvent interface,
// which does not bubble, is not cancelable, and has no default action

View File

@ -18,6 +18,7 @@ var frameReceivedCounter = 0;
var frameSentCounter = 0;
var webSocketCreatedCounter = 0;
var webSocketOpenedCounter = 0;
var webSocketMessageAvailableCounter = 0;
var webSocketClosedCounter = 0;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -25,7 +26,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var tests = [
{ payload: "Hello world!" },
{ payload: (function() { var buffer = ""; for (var i = 0; i < 120; ++i) buffer += i; return buffer; }()) },
{ payload: "end" },
]
var innerId =
@ -59,6 +59,24 @@ var listener = {
webSocketOpenedCounter++;
},
webSocketMessageAvailable: function(aWebSocketSerialID, aData, aMessageType) {
info("WebSocketMessageAvailable");
if (tests.length) {
is(aData, tests[0].payload, "Message matches!");
is(aMessageType, Ci.nsIWebSocketEventListener.TYPE_STRING, "The type is 'string'");
webSocketMessageAvailableCounter++;
tests.shift();
if (tests.length) {
ws.send(tests[0].payload);
} else {
ws.send("end");
}
}
},
webSocketClosed: function(aWebSocketSerialID, aWasClean,
aCode, aReason) {
info("WebSocketClosed");
@ -84,15 +102,6 @@ var listener = {
is(aFrame.maskBit, false, "Checking maskBit");
is(aFrame.mask, 0, "Checking mask");
is(aFrame.payload, tests[0].payload, "Checking payload: " + aFrame.payload);
} else {
ok(aFrame.timeStamp, "Checking timeStamp: " + aFrame.timeStamp);
is(aFrame.finBit, true, "Checking finBit");
is(aFrame.rsvBit1, false, "Checking rsvBit1");
is(aFrame.rsvBit2, false, "Checking rsvBit2");
is(aFrame.rsvBit3, false, "Checking rsvBit3");
is(aFrame.opCode, aFrame.OPCODE_CLOSE, "Checking opCode");
is(aFrame.maskBit, false, "Checking maskBit");
is(aFrame.mask, 0, "Checking mask");
}
frameReceivedCounter++;
@ -111,15 +120,6 @@ var listener = {
is(aFrame.maskBit, true, "Checking maskBit");
ok(!!aFrame.mask, "Checking mask: " + aFrame.mask);
is(aFrame.payload, tests[0].payload, "Checking payload: " + aFrame.payload);
} else {
ok(aFrame.timeStamp, "Checking timeStamp: " + aFrame.timeStamp);
is(aFrame.finBit, true, "Checking finBit");
is(aFrame.rsvBit1, false, "Checking rsvBit1");
is(aFrame.rsvBit2, false, "Checking rsvBit2");
is(aFrame.rsvBit3, false, "Checking rsvBit3");
is(aFrame.opCode, aFrame.OPCODE_CLOSE, "Checking opCode");
is(aFrame.maskBit, true, "Checking maskBit");
ok(!!aFrame.mask, "Checking mask: " + aFrame.mask);
}
frameSentCounter++;
@ -136,6 +136,7 @@ function checkListener() {
ok(frameSentCounter, "We sent some frames!");
ok(webSocketCreatedCounter, "We have a create notification");
ok(webSocketOpenedCounter, "We have a open notification");
ok(webSocketMessageAvailableCounter, "We have a messageAvailable notification");
ok(webSocketClosedCounter, "We have a close notification");
SimpleTest.finish();
}
@ -153,11 +154,8 @@ ws.onclose = function(e) {
ws.onmessage = function(e) {
info("onmessage");
is(e.data, tests[0].payload, "Wrong data");
tests.shift();
if (tests.length) {
ws.send(tests[0].payload);
is(e.data, tests[0].payload, "Wrong data");
}
}

View File

@ -26,6 +26,10 @@ child:
nsCString aProtocols,
nsCString aExtensions);
WebSocketMessageAvailable(uint32_t awebSocketSerialID,
nsCString aData,
uint16_t aMessageType);
WebSocketClosed(uint32_t awebSocketSerialID,
bool aWasClean,
uint16_t aCode,

View File

@ -49,6 +49,19 @@ WebSocketEventListenerChild::RecvWebSocketOpened(const uint32_t& aWebSocketSeria
return true;
}
bool
WebSocketEventListenerChild::RecvWebSocketMessageAvailable(const uint32_t& aWebSocketSerialID,
const nsCString& aData,
const uint16_t& aMessageType)
{
if (mService) {
mService->WebSocketMessageAvailable(aWebSocketSerialID, mInnerWindowID,
aData, aMessageType);
}
return true;
}
bool
WebSocketEventListenerChild::RecvWebSocketClosed(const uint32_t& aWebSocketSerialID,
const bool& aWasClean,

View File

@ -30,6 +30,10 @@ public:
const nsCString& aProtocols,
const nsCString& aExtensions) override;
bool RecvWebSocketMessageAvailable(const uint32_t& aWebSocketSerialID,
const nsCString& aData,
const uint16_t& aMessageType) override;
bool RecvWebSocketClosed(const uint32_t& aWebSocketSerialID,
const bool& aWasClean,
const uint16_t& aCode,

View File

@ -88,6 +88,16 @@ WebSocketEventListenerParent::WebSocketClosed(uint32_t aWebSocketSerialID,
return NS_OK;
}
NS_IMETHODIMP
WebSocketEventListenerParent::WebSocketMessageAvailable(uint32_t aWebSocketSerialID,
const nsACString& aData,
uint16_t aMessageType)
{
unused << SendWebSocketMessageAvailable(aWebSocketSerialID, nsCString(aData),
aMessageType);
return NS_OK;
}
NS_IMETHODIMP
WebSocketEventListenerParent::FrameReceived(uint32_t aWebSocketSerialID,
nsIWebSocketFrame* aFrame)

View File

@ -149,6 +149,30 @@ private:
const nsCString mExtensions;
};
class WebSocketMessageAvailableRunnable final : public WebSocketBaseRunnable
{
public:
WebSocketMessageAvailableRunnable(uint32_t aWebSocketSerialID,
uint64_t aInnerWindowID,
const nsACString& aData,
uint16_t aMessageType)
: WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID)
, mData(aData)
, mMessageType(aMessageType)
{}
private:
virtual void DoWork(nsIWebSocketEventListener* aListener) override
{
nsresult rv = aListener->WebSocketMessageAvailable(mWebSocketSerialID,
mData, mMessageType);
NS_WARN_IF(NS_FAILED(rv));
}
const nsCString mData;
uint16_t mMessageType;
};
class WebSocketClosedRunnable final : public WebSocketBaseRunnable
{
public:
@ -252,6 +276,24 @@ WebSocketEventService::WebSocketOpened(uint32_t aWebSocketSerialID,
NS_WARN_IF(NS_FAILED(rv));
}
void
WebSocketEventService::WebSocketMessageAvailable(uint32_t aWebSocketSerialID,
uint64_t aInnerWindowID,
const nsACString& aData,
uint16_t aMessageType)
{
// Let's continue only if we have some listeners.
if (!HasListeners()) {
return;
}
RefPtr<WebSocketMessageAvailableRunnable> runnable =
new WebSocketMessageAvailableRunnable(aWebSocketSerialID, aInnerWindowID,
aData, aMessageType);
nsresult rv = NS_DispatchToMainThread(runnable);
NS_WARN_IF(NS_FAILED(rv));
}
void
WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID,
uint64_t aInnerWindowID,

View File

@ -46,6 +46,11 @@ public:
const nsACString& aProtocols,
const nsACString& aExtensions);
void WebSocketMessageAvailable(uint32_t aWebSocketSerialID,
uint64_t aInnerWindowID,
const nsACString& aData,
uint16_t aMessageType);
void WebSocketClosed(uint32_t aWebSocketSerialID,
uint64_t aInnerWindowID,
bool aWasClean,

View File

@ -6,7 +6,7 @@
#include "domstubs.idl"
#include "nsISupports.idl"
[scriptable, builtinclass, uuid(470133f3-a04f-48a9-82bd-8d1bc7eb6f9c)]
[scriptable, builtinclass, uuid(6714a6be-2265-4f73-a988-d78a12416037)]
interface nsIWebSocketFrame : nsISupports
{
readonly attribute DOMHighResTimeStamp timeStamp;
@ -26,17 +26,17 @@ interface nsIWebSocketFrame : nsISupports
readonly attribute ACString payload;
// Non-Control opCode values:
const long OPCODE_CONTINUATION = 0x0;
const long OPCODE_TEXT = 0x1;
const long OPCODE_BINARY = 0x2;
const unsigned short OPCODE_CONTINUATION = 0x0;
const unsigned short OPCODE_TEXT = 0x1;
const unsigned short OPCODE_BINARY = 0x2;
// Control opCode values:
const long OPCODE_CLOSE = 0x8;
const long OPCODE_PING = 0x9;
const long OPCODE_PONG = 0xA;
const unsigned short OPCODE_CLOSE = 0x8;
const unsigned short OPCODE_PING = 0x9;
const unsigned short OPCODE_PONG = 0xA;
};
[scriptable, uuid(ccbd96ae-2b7d-42fc-9ee5-116fa8e1723a)]
[scriptable, uuid(e7c005ab-e694-489b-b741-96db43ffb16f)]
interface nsIWebSocketEventListener : nsISupports
{
void webSocketCreated(in unsigned long aWebSocketSerialID,
@ -48,6 +48,14 @@ interface nsIWebSocketEventListener : nsISupports
in ACString aProtocols,
in ACString aExtensions);
const unsigned short TYPE_STRING = 0x0;
const unsigned short TYPE_BLOB = 0x1;
const unsigned short TYPE_ARRAYBUFFER = 0x2;
void webSocketMessageAvailable(in unsigned long aWebSocketSerialID,
in ACString aMessage,
in unsigned short aType);
void webSocketClosed(in unsigned long aWebSocketSerialID,
in boolean aWasClean,
in unsigned short aCode,