| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 { | 222 { |
| 223 ScriptWrappable::init(this); | 223 ScriptWrappable::init(this); |
| 224 } | 224 } |
| 225 | 225 |
| 226 WebSocket::~WebSocket() | 226 WebSocket::~WebSocket() |
| 227 { | 227 { |
| 228 if (m_channel) | 228 if (m_channel) |
| 229 m_channel->disconnect(); | 229 m_channel->disconnect(); |
| 230 } | 230 } |
| 231 | 231 |
| 232 PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String&
url, ExceptionState& es) | 232 PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String&
url, ExceptionState& exceptionState) |
| 233 { | 233 { |
| 234 Vector<String> protocols; | 234 Vector<String> protocols; |
| 235 return create(context, url, protocols, es); | 235 return create(context, url, protocols, exceptionState); |
| 236 } | 236 } |
| 237 | 237 |
| 238 PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String&
url, const Vector<String>& protocols, ExceptionState& es) | 238 PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String&
url, const Vector<String>& protocols, ExceptionState& exceptionState) |
| 239 { | 239 { |
| 240 if (url.isNull()) { | 240 if (url.isNull()) { |
| 241 es.throwDOMException(SyntaxError, "Failed to create a WebSocket: the pro
vided URL is invalid."); | 241 exceptionState.throwDOMException(SyntaxError, "Failed to create a WebSoc
ket: the provided URL is invalid."); |
| 242 return 0; | 242 return 0; |
| 243 } | 243 } |
| 244 | 244 |
| 245 RefPtr<WebSocket> webSocket(adoptRef(new WebSocket(context))); | 245 RefPtr<WebSocket> webSocket(adoptRef(new WebSocket(context))); |
| 246 webSocket->suspendIfNeeded(); | 246 webSocket->suspendIfNeeded(); |
| 247 | 247 |
| 248 webSocket->connect(context->completeURL(url), protocols, es); | 248 webSocket->connect(context->completeURL(url), protocols, exceptionState); |
| 249 if (es.hadException()) | 249 if (exceptionState.hadException()) |
| 250 return 0; | 250 return 0; |
| 251 | 251 |
| 252 return webSocket.release(); | 252 return webSocket.release(); |
| 253 } | 253 } |
| 254 | 254 |
| 255 PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String&
url, const String& protocol, ExceptionState& es) | 255 PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String&
url, const String& protocol, ExceptionState& exceptionState) |
| 256 { | 256 { |
| 257 Vector<String> protocols; | 257 Vector<String> protocols; |
| 258 protocols.append(protocol); | 258 protocols.append(protocol); |
| 259 return create(context, url, protocols, es); | 259 return create(context, url, protocols, exceptionState); |
| 260 } | 260 } |
| 261 | 261 |
| 262 void WebSocket::connect(const String& url, ExceptionState& es) | 262 void WebSocket::connect(const String& url, ExceptionState& exceptionState) |
| 263 { | 263 { |
| 264 Vector<String> protocols; | 264 Vector<String> protocols; |
| 265 connect(url, protocols, es); | 265 connect(url, protocols, exceptionState); |
| 266 } | 266 } |
| 267 | 267 |
| 268 void WebSocket::connect(const String& url, const String& protocol, ExceptionStat
e& es) | 268 void WebSocket::connect(const String& url, const String& protocol, ExceptionStat
e& exceptionState) |
| 269 { | 269 { |
| 270 Vector<String> protocols; | 270 Vector<String> protocols; |
| 271 protocols.append(protocol); | 271 protocols.append(protocol); |
| 272 connect(url, protocols, es); | 272 connect(url, protocols, exceptionState); |
| 273 } | 273 } |
| 274 | 274 |
| 275 void WebSocket::connect(const String& url, const Vector<String>& protocols, Exce
ptionState& es) | 275 void WebSocket::connect(const String& url, const Vector<String>& protocols, Exce
ptionState& exceptionState) |
| 276 { | 276 { |
| 277 LOG(Network, "WebSocket %p connect() url='%s'", this, url.utf8().data()); | 277 LOG(Network, "WebSocket %p connect() url='%s'", this, url.utf8().data()); |
| 278 m_url = KURL(KURL(), url); | 278 m_url = KURL(KURL(), url); |
| 279 | 279 |
| 280 if (!m_url.isValid()) { | 280 if (!m_url.isValid()) { |
| 281 m_state = CLOSED; | 281 m_state = CLOSED; |
| 282 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute("co
nnect", "WebSocket", "the URL '" + url + "' is invalid.")); | 282 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("connect", "WebSocket", "the URL '" + url + "' is invalid.")); |
| 283 return; | 283 return; |
| 284 } | 284 } |
| 285 if (!m_url.protocolIs("ws") && !m_url.protocolIs("wss")) { | 285 if (!m_url.protocolIs("ws") && !m_url.protocolIs("wss")) { |
| 286 m_state = CLOSED; | 286 m_state = CLOSED; |
| 287 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute("co
nnect", "WebSocket", "The URL's scheme must be either 'ws' or 'wss'. '" + m_url.
protocol() + "' is not allowed.")); | 287 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("connect", "WebSocket", "The URL's scheme must be either 'ws' or 'wss'.
'" + m_url.protocol() + "' is not allowed.")); |
| 288 return; | 288 return; |
| 289 } | 289 } |
| 290 if (m_url.hasFragmentIdentifier()) { | 290 if (m_url.hasFragmentIdentifier()) { |
| 291 m_state = CLOSED; | 291 m_state = CLOSED; |
| 292 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute("co
nnect", "WebSocket", "The URL contains a fragment identifier ('" + m_url.fragmen
tIdentifier() + "'). Fragment identifiers are not allowed in WebSocket URLs.")); | 292 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("connect", "WebSocket", "The URL contains a fragment identifier ('" + m
_url.fragmentIdentifier() + "'). Fragment identifiers are not allowed in WebSock
et URLs.")); |
| 293 return; | 293 return; |
| 294 } | 294 } |
| 295 if (!portAllowed(m_url)) { | 295 if (!portAllowed(m_url)) { |
| 296 m_state = CLOSED; | 296 m_state = CLOSED; |
| 297 es.throwSecurityError(ExceptionMessages::failedToExecute("connect", "Web
Socket", "The port " + String::number(m_url.port()) + " is not allowed.")); | 297 exceptionState.throwSecurityError(ExceptionMessages::failedToExecute("co
nnect", "WebSocket", "The port " + String::number(m_url.port()) + " is not allow
ed.")); |
| 298 return; | 298 return; |
| 299 } | 299 } |
| 300 | 300 |
| 301 // FIXME: Convert this to check the isolated world's Content Security Policy
once webkit.org/b/104520 is solved. | 301 // FIXME: Convert this to check the isolated world's Content Security Policy
once webkit.org/b/104520 is solved. |
| 302 bool shouldBypassMainWorldContentSecurityPolicy = false; | 302 bool shouldBypassMainWorldContentSecurityPolicy = false; |
| 303 if (executionContext()->isDocument()) { | 303 if (executionContext()->isDocument()) { |
| 304 Document* document = toDocument(executionContext()); | 304 Document* document = toDocument(executionContext()); |
| 305 shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()
.shouldBypassMainWorldContentSecurityPolicy(); | 305 shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()
.shouldBypassMainWorldContentSecurityPolicy(); |
| 306 } | 306 } |
| 307 if (!shouldBypassMainWorldContentSecurityPolicy && !executionContext()->cont
entSecurityPolicy()->allowConnectToSource(m_url)) { | 307 if (!shouldBypassMainWorldContentSecurityPolicy && !executionContext()->cont
entSecurityPolicy()->allowConnectToSource(m_url)) { |
| 308 m_state = CLOSED; | 308 m_state = CLOSED; |
| 309 // The URL is safe to expose to JavaScript, as this check happens synchr
onously before redirection. | 309 // The URL is safe to expose to JavaScript, as this check happens synchr
onously before redirection. |
| 310 es.throwSecurityError(ExceptionMessages::failedToExecute("connect", "Web
Socket", "Refused to connect to '" + m_url.elidedString() + "' because it violat
es the document's Content Security Policy.")); | 310 exceptionState.throwSecurityError(ExceptionMessages::failedToExecute("co
nnect", "WebSocket", "Refused to connect to '" + m_url.elidedString() + "' becau
se it violates the document's Content Security Policy.")); |
| 311 return; | 311 return; |
| 312 } | 312 } |
| 313 | 313 |
| 314 m_channel = WebSocketChannel::create(executionContext(), this); | 314 m_channel = WebSocketChannel::create(executionContext(), this); |
| 315 | 315 |
| 316 // FIXME: There is a disagreement about restriction of subprotocols between
WebSocket API and hybi-10 protocol | 316 // FIXME: There is a disagreement about restriction of subprotocols between
WebSocket API and hybi-10 protocol |
| 317 // draft. The former simply says "only characters in the range U+0021 to U+0
07E are allowed," while the latter | 317 // draft. The former simply says "only characters in the range U+0021 to U+0
07E are allowed," while the latter |
| 318 // imposes a stricter rule: "the elements MUST be non-empty strings with cha
racters as defined in [RFC2616], | 318 // imposes a stricter rule: "the elements MUST be non-empty strings with cha
racters as defined in [RFC2616], |
| 319 // and MUST all be unique strings." | 319 // and MUST all be unique strings." |
| 320 // | 320 // |
| 321 // Here, we throw SyntaxError if the given protocols do not meet the latter
criteria. This behavior does not | 321 // Here, we throw SyntaxError if the given protocols do not meet the latter
criteria. This behavior does not |
| 322 // comply with WebSocket API specification, but it seems to be the only reas
onable way to handle this conflict. | 322 // comply with WebSocket API specification, but it seems to be the only reas
onable way to handle this conflict. |
| 323 for (size_t i = 0; i < protocols.size(); ++i) { | 323 for (size_t i = 0; i < protocols.size(); ++i) { |
| 324 if (!isValidProtocolString(protocols[i])) { | 324 if (!isValidProtocolString(protocols[i])) { |
| 325 m_state = CLOSED; | 325 m_state = CLOSED; |
| 326 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute
("connect", "WebSocket", "The subprotocol '" + encodeProtocolString(protocols[i]
) + "' is invalid.")); | 326 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::fai
ledToExecute("connect", "WebSocket", "The subprotocol '" + encodeProtocolString(
protocols[i]) + "' is invalid.")); |
| 327 return; | 327 return; |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 HashSet<String> visited; | 330 HashSet<String> visited; |
| 331 for (size_t i = 0; i < protocols.size(); ++i) { | 331 for (size_t i = 0; i < protocols.size(); ++i) { |
| 332 if (!visited.add(protocols[i]).isNewEntry) { | 332 if (!visited.add(protocols[i]).isNewEntry) { |
| 333 m_state = CLOSED; | 333 m_state = CLOSED; |
| 334 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute
("connect", "WebSocket", "The subprotocol '" + encodeProtocolString(protocols[i]
) + "' is duplicated.")); | 334 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::fai
ledToExecute("connect", "WebSocket", "The subprotocol '" + encodeProtocolString(
protocols[i]) + "' is duplicated.")); |
| 335 return; | 335 return; |
| 336 } | 336 } |
| 337 } | 337 } |
| 338 | 338 |
| 339 String protocolString; | 339 String protocolString; |
| 340 if (!protocols.isEmpty()) | 340 if (!protocols.isEmpty()) |
| 341 protocolString = joinStrings(protocols, subProtocolSeperator()); | 341 protocolString = joinStrings(protocols, subProtocolSeperator()); |
| 342 | 342 |
| 343 m_channel->connect(m_url, protocolString); | 343 m_channel->connect(m_url, protocolString); |
| 344 ActiveDOMObject::setPendingActivity(this); | 344 ActiveDOMObject::setPendingActivity(this); |
| 345 } | 345 } |
| 346 | 346 |
| 347 void WebSocket::handleSendResult(WebSocketChannel::SendResult result, ExceptionS
tate& es) | 347 void WebSocket::handleSendResult(WebSocketChannel::SendResult result, ExceptionS
tate& exceptionState) |
| 348 { | 348 { |
| 349 switch (result) { | 349 switch (result) { |
| 350 case WebSocketChannel::InvalidMessage: | 350 case WebSocketChannel::InvalidMessage: |
| 351 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute("se
nd", "WebSocket", "the message contains invalid characters.")); | 351 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("send", "WebSocket", "the message contains invalid characters.")); |
| 352 return; | 352 return; |
| 353 case WebSocketChannel::SendFail: | 353 case WebSocketChannel::SendFail: |
| 354 executionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel
, "WebSocket send() failed."); | 354 executionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel
, "WebSocket send() failed."); |
| 355 return; | 355 return; |
| 356 case WebSocketChannel::SendSuccess: | 356 case WebSocketChannel::SendSuccess: |
| 357 return; | 357 return; |
| 358 } | 358 } |
| 359 ASSERT_NOT_REACHED(); | 359 ASSERT_NOT_REACHED(); |
| 360 } | 360 } |
| 361 | 361 |
| 362 void WebSocket::updateBufferedAmountAfterClose(unsigned long payloadSize) | 362 void WebSocket::updateBufferedAmountAfterClose(unsigned long payloadSize) |
| 363 { | 363 { |
| 364 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, payload
Size); | 364 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, payload
Size); |
| 365 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, getFram
ingOverhead(payloadSize)); | 365 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, getFram
ingOverhead(payloadSize)); |
| 366 | 366 |
| 367 executionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "W
ebSocket is already in CLOSING or CLOSED state."); | 367 executionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "W
ebSocket is already in CLOSING or CLOSED state."); |
| 368 } | 368 } |
| 369 | 369 |
| 370 void WebSocket::send(const String& message, ExceptionState& es) | 370 void WebSocket::send(const String& message, ExceptionState& exceptionState) |
| 371 { | 371 { |
| 372 LOG(Network, "WebSocket %p send() Sending String '%s'", this, message.utf8()
.data()); | 372 LOG(Network, "WebSocket %p send() Sending String '%s'", this, message.utf8()
.data()); |
| 373 if (m_state == CONNECTING) { | 373 if (m_state == CONNECTING) { |
| 374 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("send", "WebSocket", "already in CONNECTING state.")); | 374 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("send", "WebSocket", "already in CONNECTING state.")); |
| 375 return; | 375 return; |
| 376 } | 376 } |
| 377 // No exception is raised if the connection was once established but has sub
sequently been closed. | 377 // No exception is raised if the connection was once established but has sub
sequently been closed. |
| 378 if (m_state == CLOSING || m_state == CLOSED) { | 378 if (m_state == CLOSING || m_state == CLOSED) { |
| 379 updateBufferedAmountAfterClose(message.utf8().length()); | 379 updateBufferedAmountAfterClose(message.utf8().length()); |
| 380 return; | 380 return; |
| 381 } | 381 } |
| 382 ASSERT(m_channel); | 382 ASSERT(m_channel); |
| 383 handleSendResult(m_channel->send(message), es); | 383 handleSendResult(m_channel->send(message), exceptionState); |
| 384 } | 384 } |
| 385 | 385 |
| 386 void WebSocket::send(ArrayBuffer* binaryData, ExceptionState& es) | 386 void WebSocket::send(ArrayBuffer* binaryData, ExceptionState& exceptionState) |
| 387 { | 387 { |
| 388 LOG(Network, "WebSocket %p send() Sending ArrayBuffer %p", this, binaryData)
; | 388 LOG(Network, "WebSocket %p send() Sending ArrayBuffer %p", this, binaryData)
; |
| 389 ASSERT(binaryData); | 389 ASSERT(binaryData); |
| 390 if (m_state == CONNECTING) { | 390 if (m_state == CONNECTING) { |
| 391 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("send", "WebSocket", "already in CONNECTING state.")); | 391 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("send", "WebSocket", "already in CONNECTING state.")); |
| 392 return; | 392 return; |
| 393 } | 393 } |
| 394 if (m_state == CLOSING || m_state == CLOSED) { | 394 if (m_state == CLOSING || m_state == CLOSED) { |
| 395 updateBufferedAmountAfterClose(binaryData->byteLength()); | 395 updateBufferedAmountAfterClose(binaryData->byteLength()); |
| 396 return; | 396 return; |
| 397 } | 397 } |
| 398 ASSERT(m_channel); | 398 ASSERT(m_channel); |
| 399 handleSendResult(m_channel->send(*binaryData, 0, binaryData->byteLength()),
es); | 399 handleSendResult(m_channel->send(*binaryData, 0, binaryData->byteLength()),
exceptionState); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void WebSocket::send(ArrayBufferView* arrayBufferView, ExceptionState& es) | 402 void WebSocket::send(ArrayBufferView* arrayBufferView, ExceptionState& exception
State) |
| 403 { | 403 { |
| 404 LOG(Network, "WebSocket %p send() Sending ArrayBufferView %p", this, arrayBu
fferView); | 404 LOG(Network, "WebSocket %p send() Sending ArrayBufferView %p", this, arrayBu
fferView); |
| 405 ASSERT(arrayBufferView); | 405 ASSERT(arrayBufferView); |
| 406 if (m_state == CONNECTING) { | 406 if (m_state == CONNECTING) { |
| 407 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("send", "WebSocket", "already in CONNECTING state.")); | 407 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("send", "WebSocket", "already in CONNECTING state.")); |
| 408 return; | 408 return; |
| 409 } | 409 } |
| 410 if (m_state == CLOSING || m_state == CLOSED) { | 410 if (m_state == CLOSING || m_state == CLOSED) { |
| 411 updateBufferedAmountAfterClose(arrayBufferView->byteLength()); | 411 updateBufferedAmountAfterClose(arrayBufferView->byteLength()); |
| 412 return; | 412 return; |
| 413 } | 413 } |
| 414 ASSERT(m_channel); | 414 ASSERT(m_channel); |
| 415 RefPtr<ArrayBuffer> arrayBuffer(arrayBufferView->buffer()); | 415 RefPtr<ArrayBuffer> arrayBuffer(arrayBufferView->buffer()); |
| 416 handleSendResult(m_channel->send(*arrayBuffer, arrayBufferView->byteOffset()
, arrayBufferView->byteLength()), es); | 416 handleSendResult(m_channel->send(*arrayBuffer, arrayBufferView->byteOffset()
, arrayBufferView->byteLength()), exceptionState); |
| 417 } | 417 } |
| 418 | 418 |
| 419 void WebSocket::send(Blob* binaryData, ExceptionState& es) | 419 void WebSocket::send(Blob* binaryData, ExceptionState& exceptionState) |
| 420 { | 420 { |
| 421 LOG(Network, "WebSocket %p send() Sending Blob '%s'", this, binaryData->uuid
().utf8().data()); | 421 LOG(Network, "WebSocket %p send() Sending Blob '%s'", this, binaryData->uuid
().utf8().data()); |
| 422 ASSERT(binaryData); | 422 ASSERT(binaryData); |
| 423 if (m_state == CONNECTING) { | 423 if (m_state == CONNECTING) { |
| 424 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("send", "WebSocket", "already in CONNECTING state.")); | 424 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("send", "WebSocket", "already in CONNECTING state.")); |
| 425 return; | 425 return; |
| 426 } | 426 } |
| 427 if (m_state == CLOSING || m_state == CLOSED) { | 427 if (m_state == CLOSING || m_state == CLOSED) { |
| 428 updateBufferedAmountAfterClose(static_cast<unsigned long>(binaryData->si
ze())); | 428 updateBufferedAmountAfterClose(static_cast<unsigned long>(binaryData->si
ze())); |
| 429 return; | 429 return; |
| 430 } | 430 } |
| 431 ASSERT(m_channel); | 431 ASSERT(m_channel); |
| 432 handleSendResult(m_channel->send(binaryData->blobDataHandle()), es); | 432 handleSendResult(m_channel->send(binaryData->blobDataHandle()), exceptionSta
te); |
| 433 } | 433 } |
| 434 | 434 |
| 435 void WebSocket::close(unsigned short code, const String& reason, ExceptionState&
es) | 435 void WebSocket::close(unsigned short code, const String& reason, ExceptionState&
exceptionState) |
| 436 { | 436 { |
| 437 closeInternal(code, reason, es); | 437 closeInternal(code, reason, exceptionState); |
| 438 } | 438 } |
| 439 | 439 |
| 440 void WebSocket::close(ExceptionState& es) | 440 void WebSocket::close(ExceptionState& exceptionState) |
| 441 { | 441 { |
| 442 closeInternal(WebSocketChannel::CloseEventCodeNotSpecified, String(), es); | 442 closeInternal(WebSocketChannel::CloseEventCodeNotSpecified, String(), except
ionState); |
| 443 } | 443 } |
| 444 | 444 |
| 445 void WebSocket::close(unsigned short code, ExceptionState& es) | 445 void WebSocket::close(unsigned short code, ExceptionState& exceptionState) |
| 446 { | 446 { |
| 447 closeInternal(code, String(), es); | 447 closeInternal(code, String(), exceptionState); |
| 448 } | 448 } |
| 449 | 449 |
| 450 void WebSocket::closeInternal(int code, const String& reason, ExceptionState& es
) | 450 void WebSocket::closeInternal(int code, const String& reason, ExceptionState& ex
ceptionState) |
| 451 { | 451 { |
| 452 if (code == WebSocketChannel::CloseEventCodeNotSpecified) { | 452 if (code == WebSocketChannel::CloseEventCodeNotSpecified) { |
| 453 LOG(Network, "WebSocket %p close() without code and reason", this); | 453 LOG(Network, "WebSocket %p close() without code and reason", this); |
| 454 } else { | 454 } else { |
| 455 LOG(Network, "WebSocket %p close() code=%d reason='%s'", this, code, rea
son.utf8().data()); | 455 LOG(Network, "WebSocket %p close() code=%d reason='%s'", this, code, rea
son.utf8().data()); |
| 456 if (!(code == WebSocketChannel::CloseEventCodeNormalClosure || (WebSocke
tChannel::CloseEventCodeMinimumUserDefined <= code && code <= WebSocketChannel::
CloseEventCodeMaximumUserDefined))) { | 456 if (!(code == WebSocketChannel::CloseEventCodeNormalClosure || (WebSocke
tChannel::CloseEventCodeMinimumUserDefined <= code && code <= WebSocketChannel::
CloseEventCodeMaximumUserDefined))) { |
| 457 es.throwDOMException(InvalidAccessError, ExceptionMessages::failedTo
Execute("close", "WebSocket", "the code must be either 1000, or between 3000 and
4999. " + String::number(code) + " is neither.")); | 457 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessag
es::failedToExecute("close", "WebSocket", "the code must be either 1000, or betw
een 3000 and 4999. " + String::number(code) + " is neither.")); |
| 458 return; | 458 return; |
| 459 } | 459 } |
| 460 CString utf8 = reason.utf8(String::StrictConversionReplacingUnpairedSurr
ogatesWithFFFD); | 460 CString utf8 = reason.utf8(String::StrictConversionReplacingUnpairedSurr
ogatesWithFFFD); |
| 461 if (utf8.length() > maxReasonSizeInBytes) { | 461 if (utf8.length() > maxReasonSizeInBytes) { |
| 462 es.throwDOMException(SyntaxError, ExceptionMessages::failedToExecute
("close", "WebSocket", "the message must be smaller than " + String::number(maxR
easonSizeInBytes) + " bytes.")); | 462 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::fai
ledToExecute("close", "WebSocket", "the message must be smaller than " + String:
:number(maxReasonSizeInBytes) + " bytes.")); |
| 463 return; | 463 return; |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 if (m_state == CLOSING || m_state == CLOSED) | 467 if (m_state == CLOSING || m_state == CLOSED) |
| 468 return; | 468 return; |
| 469 if (m_state == CONNECTING) { | 469 if (m_state == CONNECTING) { |
| 470 m_state = CLOSING; | 470 m_state = CLOSING; |
| 471 m_channel->fail("WebSocket is closed before the connection is establishe
d.", WarningMessageLevel); | 471 m_channel->fail("WebSocket is closed before the connection is establishe
d.", WarningMessageLevel); |
| 472 return; | 472 return; |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 static const size_t minimumPayloadSizeWithEightByteExtendedPayloadLength = 0
x10000; | 674 static const size_t minimumPayloadSizeWithEightByteExtendedPayloadLength = 0
x10000; |
| 675 size_t overhead = hybiBaseFramingOverhead + hybiMaskingKeyLength; | 675 size_t overhead = hybiBaseFramingOverhead + hybiMaskingKeyLength; |
| 676 if (payloadSize >= minimumPayloadSizeWithEightByteExtendedPayloadLength) | 676 if (payloadSize >= minimumPayloadSizeWithEightByteExtendedPayloadLength) |
| 677 overhead += 8; | 677 overhead += 8; |
| 678 else if (payloadSize >= minimumPayloadSizeWithTwoByteExtendedPayloadLength) | 678 else if (payloadSize >= minimumPayloadSizeWithTwoByteExtendedPayloadLength) |
| 679 overhead += 2; | 679 overhead += 2; |
| 680 return overhead; | 680 return overhead; |
| 681 } | 681 } |
| 682 | 682 |
| 683 } // namespace WebCore | 683 } // namespace WebCore |
| OLD | NEW |