Fixes #8213: Implement Blob variant of WebSocket.send()

This commit is contained in:
Nikki 2015-10-26 21:22:27 -06:00
parent 6c051ce828
commit 1d280289f1
7 changed files with 86 additions and 52 deletions

View file

@ -72,6 +72,11 @@ impl Blob {
pub fn read_out_buffer(&self, send: Sender<Vec<u8>>) { pub fn read_out_buffer(&self, send: Sender<Vec<u8>>) {
send.send(self.bytes.clone().unwrap_or(vec![])).unwrap(); send.send(self.bytes.clone().unwrap_or(vec![])).unwrap();
} }
// simpler to use version of read_out_buffer
pub fn clone_bytes(&self) -> Vec<u8> {
self.bytes.clone().unwrap_or(vec![])
}
} }
impl BlobMethods for Blob { impl BlobMethods for Blob {

View file

@ -29,8 +29,7 @@ interface WebSocket : EventTarget {
attribute EventHandler onmessage; attribute EventHandler onmessage;
attribute BinaryType binaryType; attribute BinaryType binaryType;
[Throws] void send(USVString data); [Throws] void send(USVString data);
//void send(Blob data); [Throws] void send(Blob data);
//void send(ArrayBuffer data); //void send(ArrayBuffer data);
//void send(ArrayBufferView data); //void send(ArrayBufferView data);
}; };

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WebSocketBinding; use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::{BinaryType, WebSocketMethods}; use dom::bindings::codegen::Bindings::WebSocketBinding::{BinaryType, WebSocketMethods};
@ -291,6 +292,56 @@ impl WebSocket {
// Step 7. // Step 7.
Ok(ws) Ok(ws)
} }
// https://html.spec.whatwg.org/multipage/#dom-websocket-send
fn Send_Impl(&self, data_byte_len: u64) -> Fallible<bool> {
let mut return_after_buffer = false;
match self.ready_state.get() {
WebSocketRequestState::Connecting => {
return Err(Error::InvalidState);
},
WebSocketRequestState::Open => (),
WebSocketRequestState::Closing | WebSocketRequestState::Closed => {
return_after_buffer = true;
}
}
let global = self.global.root();
let chan = global.r().script_chan();
let address = Trusted::new(global.r().get_cx(), self, chan.clone());
let new_buffer_amount = (self.buffered_amount.get() as u64) + data_byte_len;
if new_buffer_amount > (u32::max_value() as u64) {
self.buffered_amount.set(u32::max_value());
self.full.set(true);
let _ = self.Close(None, None);
return Ok(false);
} else {
self.buffered_amount.set(new_buffer_amount as u32);
}
if return_after_buffer {
return Ok(false);
}
if !self.clearing_buffer.get() &&
self.ready_state.get() == WebSocketRequestState::Open {
self.clearing_buffer.set(true);
let task = box BufferedAmountTask {
addr: address,
};
chan.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)).unwrap();
}
Ok(true)
}
} }
impl WebSocketMethods for WebSocket { impl WebSocketMethods for WebSocket {
@ -333,40 +384,33 @@ impl WebSocketMethods for WebSocket {
// https://html.spec.whatwg.org/multipage/#dom-websocket-send // https://html.spec.whatwg.org/multipage/#dom-websocket-send
fn Send(&self, data: USVString) -> Fallible<()> { fn Send(&self, data: USVString) -> Fallible<()> {
match self.ready_state.get() {
WebSocketRequestState::Connecting => { let data_byte_len = data.0.as_bytes().len() as u64;
return Err(Error::InvalidState); let send_data = try!(self.Send_Impl(data_byte_len));
},
WebSocketRequestState::Open => (), if send_data {
WebSocketRequestState::Closing | WebSocketRequestState::Closed => { let mut other_sender = self.sender.borrow_mut();
// TODO: Update bufferedAmount. let my_sender = other_sender.as_mut().unwrap();
return Ok(()); let _ = my_sender.lock().unwrap().send_message(Message::Text(data.0));
}
} }
/*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for Ok(())
"If argument is a string" }
TODO: Need to buffer data
TODO: The send function needs to flag when full by using the following // https://html.spec.whatwg.org/multipage/#dom-websocket-send
self.full.set(true). This needs to be done when the buffer is full fn Send_(&self, data: &Blob) -> Fallible<()> {
/* As per https://html.spec.whatwg.org/multipage/#websocket
the buffered amount needs to be clamped to u32, even though Blob.Size() is u64
If the buffer limit is reached in the first place, there are likely other major problems
*/ */
let mut other_sender = self.sender.borrow_mut(); let data_byte_len = data.Size();
let my_sender = other_sender.as_mut().unwrap(); let send_data = try!(self.Send_Impl(data_byte_len));
self.buffered_amount.set(self.buffered_amount.get() + (data.0.as_bytes().len() as u32)); if send_data {
let mut other_sender = self.sender.borrow_mut();
let _ = my_sender.lock().unwrap().send_message(Message::Text(data.0)); let my_sender = other_sender.as_mut().unwrap();
let _ = my_sender.lock().unwrap().send_message(Message::Binary(data.clone_bytes()));
if !self.clearing_buffer.get() && self.ready_state.get() == WebSocketRequestState::Open {
self.clearing_buffer.set(true);
let global = self.global.root();
let task = box BufferedAmountTask {
addr: Trusted::new(global.r().get_cx(), self, global.r().script_chan()),
};
let chan = global.r().script_chan();
chan.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)).unwrap();
} }
Ok(()) Ok(())

View file

@ -1,9 +0,0 @@
[Secure-Send-binary-blob.htm]
type: testharness
expected: TIMEOUT
[W3C WebSocket API - Send binary data on a Secure WebSocket - Blob - Message should be received]
expected: FAIL
[W3C WebSocket API - Send binary data on a Secure WebSocket - Blob - Connection should be closed]
expected: NOTRUN

View file

@ -1,9 +0,0 @@
[Send-binary-blob.htm]
type: testharness
expected: TIMEOUT
[W3C WebSocket API - Send binary data on a WebSocket - Blob - Message should be received]
expected: FAIL
[W3C WebSocket API - Send binary data on a WebSocket - Blob - Connection should be closed]
expected: NOTRUN

View file

@ -22,7 +22,9 @@
wsocket.addEventListener('open', testOpen.step_func(function (evt) { wsocket.addEventListener('open', testOpen.step_func(function (evt) {
wsocket.binaryType = "blob"; wsocket.binaryType = "blob";
data = new ArrayBuffer(datasize); for (var i = 0; i < datasize; i++)
data += String.fromCharCode(0);
data = new Blob([data]);
isOpenCalled = true; isOpenCalled = true;
wsocket.send(data); wsocket.send(data);
testOpen.done(); testOpen.done();

View file

@ -22,7 +22,9 @@
wsocket.addEventListener('open', testOpen.step_func(function (evt) { wsocket.addEventListener('open', testOpen.step_func(function (evt) {
wsocket.binaryType = "blob"; wsocket.binaryType = "blob";
data = new ArrayBuffer(datasize); for (var i = 0; i < datasize; i++)
data += String.fromCharCode(0);
data = new Blob([data]);
isOpenCalled = true; isOpenCalled = true;
wsocket.send(data); wsocket.send(data);
testOpen.done(); testOpen.done();