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; return NS_OK;
} }
uint16_t messageType = nsIWebSocketEventListener::TYPE_STRING;
// Create appropriate JS object for message // Create appropriate JS object for message
JS::Rooted<JS::Value> jsData(aCx); JS::Rooted<JS::Value> jsData(aCx);
if (aIsBinary) { if (aIsBinary) {
if (mBinaryType == dom::BinaryType::Blob) { if (mBinaryType == dom::BinaryType::Blob) {
messageType = nsIWebSocketEventListener::TYPE_BLOB;
nsresult rv = nsContentUtils::CreateBlobBuffer(aCx, GetOwner(), aData, nsresult rv = nsContentUtils::CreateBlobBuffer(aCx, GetOwner(), aData,
&jsData); &jsData);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else if (mBinaryType == dom::BinaryType::Arraybuffer) { } else if (mBinaryType == dom::BinaryType::Arraybuffer) {
messageType = nsIWebSocketEventListener::TYPE_ARRAYBUFFER;
JS::Rooted<JSObject*> arrayBuf(aCx); JS::Rooted<JSObject*> arrayBuf(aCx);
nsresult rv = nsContentUtils::CreateArrayBuffer(aCx, aData, nsresult rv = nsContentUtils::CreateArrayBuffer(aCx, aData,
arrayBuf.address()); arrayBuf.address());
@ -1879,6 +1885,10 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
jsData.setString(jsString); jsData.setString(jsString);
} }
mImpl->mService->WebSocketMessageAvailable(mImpl->mChannel->Serial(),
mImpl->mInnerWindowID,
aData, messageType);
// create an event that uses the MessageEvent interface, // create an event that uses the MessageEvent interface,
// which does not bubble, is not cancelable, and has no default action // 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 frameSentCounter = 0;
var webSocketCreatedCounter = 0; var webSocketCreatedCounter = 0;
var webSocketOpenedCounter = 0; var webSocketOpenedCounter = 0;
var webSocketMessageAvailableCounter = 0;
var webSocketClosedCounter = 0; var webSocketClosedCounter = 0;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -25,7 +26,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var tests = [ var tests = [
{ payload: "Hello world!" }, { payload: "Hello world!" },
{ payload: (function() { var buffer = ""; for (var i = 0; i < 120; ++i) buffer += i; return buffer; }()) }, { payload: (function() { var buffer = ""; for (var i = 0; i < 120; ++i) buffer += i; return buffer; }()) },
{ payload: "end" },
] ]
var innerId = var innerId =
@ -59,6 +59,24 @@ var listener = {
webSocketOpenedCounter++; 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, webSocketClosed: function(aWebSocketSerialID, aWasClean,
aCode, aReason) { aCode, aReason) {
info("WebSocketClosed"); info("WebSocketClosed");
@ -84,15 +102,6 @@ var listener = {
is(aFrame.maskBit, false, "Checking maskBit"); is(aFrame.maskBit, false, "Checking maskBit");
is(aFrame.mask, 0, "Checking mask"); is(aFrame.mask, 0, "Checking mask");
is(aFrame.payload, tests[0].payload, "Checking payload: " + aFrame.payload); 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++; frameReceivedCounter++;
@ -111,15 +120,6 @@ var listener = {
is(aFrame.maskBit, true, "Checking maskBit"); is(aFrame.maskBit, true, "Checking maskBit");
ok(!!aFrame.mask, "Checking mask: " + aFrame.mask); ok(!!aFrame.mask, "Checking mask: " + aFrame.mask);
is(aFrame.payload, tests[0].payload, "Checking payload: " + aFrame.payload); 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++; frameSentCounter++;
@ -136,6 +136,7 @@ function checkListener() {
ok(frameSentCounter, "We sent some frames!"); ok(frameSentCounter, "We sent some frames!");
ok(webSocketCreatedCounter, "We have a create notification"); ok(webSocketCreatedCounter, "We have a create notification");
ok(webSocketOpenedCounter, "We have a open notification"); ok(webSocketOpenedCounter, "We have a open notification");
ok(webSocketMessageAvailableCounter, "We have a messageAvailable notification");
ok(webSocketClosedCounter, "We have a close notification"); ok(webSocketClosedCounter, "We have a close notification");
SimpleTest.finish(); SimpleTest.finish();
} }
@ -153,11 +154,8 @@ ws.onclose = function(e) {
ws.onmessage = function(e) { ws.onmessage = function(e) {
info("onmessage"); info("onmessage");
is(e.data, tests[0].payload, "Wrong data");
tests.shift();
if (tests.length) { 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 aProtocols,
nsCString aExtensions); nsCString aExtensions);
WebSocketMessageAvailable(uint32_t awebSocketSerialID,
nsCString aData,
uint16_t aMessageType);
WebSocketClosed(uint32_t awebSocketSerialID, WebSocketClosed(uint32_t awebSocketSerialID,
bool aWasClean, bool aWasClean,
uint16_t aCode, uint16_t aCode,

View File

@ -49,6 +49,19 @@ WebSocketEventListenerChild::RecvWebSocketOpened(const uint32_t& aWebSocketSeria
return true; 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 bool
WebSocketEventListenerChild::RecvWebSocketClosed(const uint32_t& aWebSocketSerialID, WebSocketEventListenerChild::RecvWebSocketClosed(const uint32_t& aWebSocketSerialID,
const bool& aWasClean, const bool& aWasClean,

View File

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

View File

@ -88,6 +88,16 @@ WebSocketEventListenerParent::WebSocketClosed(uint32_t aWebSocketSerialID,
return NS_OK; 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 NS_IMETHODIMP
WebSocketEventListenerParent::FrameReceived(uint32_t aWebSocketSerialID, WebSocketEventListenerParent::FrameReceived(uint32_t aWebSocketSerialID,
nsIWebSocketFrame* aFrame) nsIWebSocketFrame* aFrame)

View File

@ -149,6 +149,30 @@ private:
const nsCString mExtensions; 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 class WebSocketClosedRunnable final : public WebSocketBaseRunnable
{ {
public: public:
@ -252,6 +276,24 @@ WebSocketEventService::WebSocketOpened(uint32_t aWebSocketSerialID,
NS_WARN_IF(NS_FAILED(rv)); 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 void
WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID, WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID,
uint64_t aInnerWindowID, uint64_t aInnerWindowID,

View File

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

View File

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