| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 { | 90 { |
| 91 return m_sendRequestResult; | 91 return m_sendRequestResult; |
| 92 } | 92 } |
| 93 | 93 |
| 94 // This should be called after all setters are called and before any | 94 // This should be called after all setters are called and before any |
| 95 // getters are called. | 95 // getters are called. |
| 96 void signalWorkerThread() | 96 void signalWorkerThread() |
| 97 { | 97 { |
| 98 m_event->signal(); | 98 m_event->signal(); |
| 99 } | 99 } |
| 100 | 100 void wait() |
| 101 blink::WebWaitableEvent* event() const | |
| 102 { | 101 { |
| 103 return m_event.get(); | 102 m_event->wait(); |
| 104 } | 103 } |
| 105 | 104 |
| 106 void trace(Visitor* visitor) { } | 105 void trace(Visitor* visitor) { } |
| 107 | 106 |
| 108 private: | 107 private: |
| 109 explicit ThreadableWebSocketChannelSyncHelper(PassOwnPtr<blink::WebWaitableE
vent> event) | 108 explicit ThreadableWebSocketChannelSyncHelper(PassOwnPtr<blink::WebWaitableE
vent> event) |
| 110 : m_event(event) | 109 : m_event(event) |
| 111 , m_connectRequestResult(false) | 110 , m_connectRequestResult(false) |
| 112 , m_sendRequestResult(WebSocketChannel::SendFail) | 111 , m_sendRequestResult(WebSocketChannel::SendFail) |
| 113 { | 112 { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 m_bridge.clear(); | 193 m_bridge.clear(); |
| 195 } | 194 } |
| 196 | 195 |
| 197 void WorkerThreadableWebSocketChannel::trace(Visitor* visitor) | 196 void WorkerThreadableWebSocketChannel::trace(Visitor* visitor) |
| 198 { | 197 { |
| 199 visitor->trace(m_bridge); | 198 visitor->trace(m_bridge); |
| 200 visitor->trace(m_workerClientWrapper); | 199 visitor->trace(m_workerClientWrapper); |
| 201 WebSocketChannel::trace(visitor); | 200 WebSocketChannel::trace(visitor); |
| 202 } | 201 } |
| 203 | 202 |
| 204 #if ENABLE(OILPAN) | 203 Peer::Peer(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> clien
tWrapper, WorkerLoaderProxy& loaderProxy, PassRefPtrWillBeRawPtr<ThreadableWebSo
cketChannelSyncHelper> syncHelper) |
| 205 Peer::Peer(RawPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, Worker
LoaderProxy& loaderProxy, ExecutionContext* context, const String& sourceURL, un
signed lineNumber, RawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) | |
| 206 #else | |
| 207 Peer::Peer(PassRefPtr<WeakReference<Peer> > reference, PassRefPtr<ThreadableWebS
ocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, Execut
ionContext* context, const String& sourceURL, unsigned lineNumber, PassRefPtr<Th
readableWebSocketChannelSyncHelper> syncHelper) | |
| 208 #endif | |
| 209 : m_workerClientWrapper(clientWrapper) | 204 : m_workerClientWrapper(clientWrapper) |
| 210 , m_loaderProxy(loaderProxy) | 205 , m_loaderProxy(loaderProxy) |
| 211 , m_mainWebSocketChannel(nullptr) | 206 , m_mainWebSocketChannel(nullptr) |
| 212 , m_syncHelper(syncHelper) | 207 , m_syncHelper(syncHelper) |
| 213 #if ENABLE(OILPAN) | 208 { |
| 214 , m_keepAlive(this) | 209 ASSERT(!isMainThread()); |
| 215 #else | 210 } |
| 216 , m_weakFactory(reference, this) | 211 |
| 217 #endif | 212 Peer::~Peer() |
| 213 { |
| 214 ASSERT(!isMainThread()); |
| 215 } |
| 216 |
| 217 PassOwnPtrWillBeRawPtr<Peer> Peer::create(PassRefPtrWillBeRawPtr<ThreadableWebSo
cketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, PassRef
PtrWillBeRawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) |
| 218 { |
| 219 return adoptPtrWillBeNoop(new Peer(clientWrapper, loaderProxy, syncHelper)); |
| 220 } |
| 221 |
| 222 void Peer::initializeInternal(ExecutionContext* context, const String& sourceURL
, unsigned lineNumber) |
| 218 { | 223 { |
| 219 ASSERT(isMainThread()); | 224 ASSERT(isMainThread()); |
| 220 ASSERT(m_workerClientWrapper.get()); | |
| 221 | |
| 222 Document* document = toDocument(context); | 225 Document* document = toDocument(context); |
| 223 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) { | 226 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) { |
| 224 m_mainWebSocketChannel = NewWebSocketChannelImpl::create(document, this,
sourceURL, lineNumber); | 227 m_mainWebSocketChannel = NewWebSocketChannelImpl::create(document, this,
sourceURL, lineNumber); |
| 225 } else { | 228 } else { |
| 226 m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, th
is, sourceURL, lineNumber); | 229 m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, th
is, sourceURL, lineNumber); |
| 227 } | 230 } |
| 228 } | |
| 229 | |
| 230 Peer::~Peer() | |
| 231 { | |
| 232 ASSERT(isMainThread()); | |
| 233 } | |
| 234 | |
| 235 #if ENABLE(OILPAN) | |
| 236 void Peer::initialize(ExecutionContext* context, WeakMember<Peer>* reference, Wo
rkerLoaderProxy* loaderProxy, RawPtr<ThreadableWebSocketChannelClientWrapper> cl
ientWrapper, const String& sourceURLAtConnection, unsigned lineNumberAtConnectio
n, RawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) | |
| 237 { | |
| 238 // The caller must call destroy() to free the peer. | |
| 239 *reference = new Peer(clientWrapper, *loaderProxy, context, sourceURLAtConne
ction, lineNumberAtConnection, syncHelper); | |
| 240 syncHelper->signalWorkerThread(); | |
| 241 } | |
| 242 #else | |
| 243 void Peer::initialize(ExecutionContext* context, PassRefPtr<WeakReference<Peer>
> reference, WorkerLoaderProxy* loaderProxy, PassRefPtr<ThreadableWebSocketChann
elClientWrapper> clientWrapper, const String& sourceURLAtConnection, unsigned li
neNumberAtConnection, PassRefPtr<ThreadableWebSocketChannelSyncHelper> prpSyncHe
lper) | |
| 244 { | |
| 245 RefPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = prpSyncHelper; | |
| 246 // The caller must call destroy() to free the peer. | |
| 247 new Peer(reference, clientWrapper, *loaderProxy, context, sourceURLAtConnect
ion, lineNumberAtConnection, syncHelper); | |
| 248 syncHelper->signalWorkerThread(); | |
| 249 } | |
| 250 #endif | |
| 251 | |
| 252 void Peer::destroy() | |
| 253 { | |
| 254 ASSERT(isMainThread()); | |
| 255 disconnect(); | |
| 256 | |
| 257 #if ENABLE(OILPAN) | |
| 258 m_keepAlive = nullptr; | |
| 259 m_syncHelper->signalWorkerThread(); | 231 m_syncHelper->signalWorkerThread(); |
| 260 m_syncHelper = nullptr; | |
| 261 #else | |
| 262 delete this; | |
| 263 #endif | |
| 264 } | 232 } |
| 265 | 233 |
| 266 void Peer::connect(const KURL& url, const String& protocol) | 234 void Peer::connect(const KURL& url, const String& protocol) |
| 267 { | 235 { |
| 268 ASSERT(isMainThread()); | 236 ASSERT(isMainThread()); |
| 269 ASSERT(m_syncHelper); | 237 ASSERT(m_syncHelper); |
| 270 if (!m_mainWebSocketChannel) { | 238 if (!m_mainWebSocketChannel) { |
| 271 m_syncHelper->setConnectRequestResult(false); | 239 m_syncHelper->setConnectRequestResult(false); |
| 272 } else { | 240 } else { |
| 273 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco
l); | 241 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco
l); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 ASSERT(m_syncHelper); | 298 ASSERT(m_syncHelper); |
| 331 if (!m_mainWebSocketChannel) | 299 if (!m_mainWebSocketChannel) |
| 332 return; | 300 return; |
| 333 m_mainWebSocketChannel->fail(reason, level, sourceURL, lineNumber); | 301 m_mainWebSocketChannel->fail(reason, level, sourceURL, lineNumber); |
| 334 } | 302 } |
| 335 | 303 |
| 336 void Peer::disconnect() | 304 void Peer::disconnect() |
| 337 { | 305 { |
| 338 ASSERT(isMainThread()); | 306 ASSERT(isMainThread()); |
| 339 ASSERT(m_syncHelper); | 307 ASSERT(m_syncHelper); |
| 340 if (!m_mainWebSocketChannel) | 308 if (m_mainWebSocketChannel) { |
| 341 return; | 309 m_mainWebSocketChannel->disconnect(); |
| 342 m_mainWebSocketChannel->disconnect(); | 310 m_mainWebSocketChannel = nullptr; |
| 343 m_mainWebSocketChannel = nullptr; | 311 } |
| 312 m_syncHelper->signalWorkerThread(); |
| 344 } | 313 } |
| 345 | 314 |
| 346 static void workerGlobalScopeDidConnect(ExecutionContext* context, PassRefPtrWil
lBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const St
ring& subprotocol, const String& extensions) | 315 static void workerGlobalScopeDidConnect(ExecutionContext* context, PassRefPtrWil
lBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const St
ring& subprotocol, const String& extensions) |
| 347 { | 316 { |
| 348 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 317 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 349 workerClientWrapper->didConnect(subprotocol, extensions); | 318 workerClientWrapper->didConnect(subprotocol, extensions); |
| 350 } | 319 } |
| 351 | 320 |
| 352 void Peer::didConnect(const String& subprotocol, const String& extensions) | 321 void Peer::didConnect(const String& subprotocol, const String& extensions) |
| 353 { | 322 { |
| 354 ASSERT(isMainThread()); | 323 ASSERT(isMainThread()); |
| 355 // It is important to seprate task creation from posting | 324 // It is important to seprate task creation from posting |
| 356 // the task. See the above comment. | 325 // the task. See the above comment. |
| 357 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConnect, m_workerClientWrapper.get(), subprotocol, extensions); | 326 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConnect, m_workerClientWrapper, subprotocol, extensions); |
| 358 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 327 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 359 } | 328 } |
| 360 | 329 |
| 361 static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRe
fPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, c
onst String& message) | 330 static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRe
fPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, c
onst String& message) |
| 362 { | 331 { |
| 363 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 332 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 364 workerClientWrapper->didReceiveMessage(message); | 333 workerClientWrapper->didReceiveMessage(message); |
| 365 } | 334 } |
| 366 | 335 |
| 367 void Peer::didReceiveMessage(const String& message) | 336 void Peer::didReceiveMessage(const String& message) |
| 368 { | 337 { |
| 369 ASSERT(isMainThread()); | 338 ASSERT(isMainThread()); |
| 370 // It is important to seprate task creation from posting | 339 // It is important to seprate task creation from posting |
| 371 // the task. See the above comment. | 340 // the task. See the above comment. |
| 372 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessage, m_workerClientWrapper.get(), message); | 341 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessage, m_workerClientWrapper, message); |
| 373 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 342 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 374 } | 343 } |
| 375 | 344 |
| 376 static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, Pas
sRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper
, PassOwnPtr<Vector<char> > binaryData) | 345 static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, Pas
sRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper
, PassOwnPtr<Vector<char> > binaryData) |
| 377 { | 346 { |
| 378 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 347 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 379 workerClientWrapper->didReceiveBinaryData(binaryData); | 348 workerClientWrapper->didReceiveBinaryData(binaryData); |
| 380 } | 349 } |
| 381 | 350 |
| 382 void Peer::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) | 351 void Peer::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) |
| 383 { | 352 { |
| 384 ASSERT(isMainThread()); | 353 ASSERT(isMainThread()); |
| 385 // It is important to seprate task creation from posting | 354 // It is important to seprate task creation from posting |
| 386 // the task. See the above comment. | 355 // the task. See the above comment. |
| 387 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveBinaryData, m_workerClientWrapper.get(), binaryData); | 356 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveBinaryData, m_workerClientWrapper, binaryData); |
| 388 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 357 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 389 } | 358 } |
| 390 | 359 |
| 391 static void workerGlobalScopeDidConsumeBufferedAmount(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper, unsigned long consumed) | 360 static void workerGlobalScopeDidConsumeBufferedAmount(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper, unsigned long consumed) |
| 392 { | 361 { |
| 393 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 362 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 394 workerClientWrapper->didConsumeBufferedAmount(consumed); | 363 workerClientWrapper->didConsumeBufferedAmount(consumed); |
| 395 } | 364 } |
| 396 | 365 |
| 397 void Peer::didConsumeBufferedAmount(unsigned long consumed) | 366 void Peer::didConsumeBufferedAmount(unsigned long consumed) |
| 398 { | 367 { |
| 399 ASSERT(isMainThread()); | 368 ASSERT(isMainThread()); |
| 400 // It is important to seprate task creation from posting | 369 // It is important to seprate task creation from posting |
| 401 // the task. See the above comment. | 370 // the task. See the above comment. |
| 402 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConsumeBufferedAmount, m_workerClientWrapper.get(), consumed); | 371 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConsumeBufferedAmount, m_workerClientWrapper, consumed); |
| 403 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 372 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 404 } | 373 } |
| 405 | 374 |
| 406 static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper) | 375 static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper) |
| 407 { | 376 { |
| 408 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 377 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 409 workerClientWrapper->didStartClosingHandshake(); | 378 workerClientWrapper->didStartClosingHandshake(); |
| 410 } | 379 } |
| 411 | 380 |
| 412 void Peer::didStartClosingHandshake() | 381 void Peer::didStartClosingHandshake() |
| 413 { | 382 { |
| 414 ASSERT(isMainThread()); | 383 ASSERT(isMainThread()); |
| 415 // It is important to seprate task creation from posting | 384 // It is important to seprate task creation from posting |
| 416 // the task. See the above comment. | 385 // the task. See the above comment. |
| 417 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidStartClosingHandshake, m_workerClientWrapper.get()); | 386 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidStartClosingHandshake, m_workerClientWrapper); |
| 418 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 387 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 419 } | 388 } |
| 420 | 389 |
| 421 static void workerGlobalScopeDidClose(ExecutionContext* context, PassRefPtrWillB
eRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WebSocketC
hannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsig
ned short code, const String& reason) | 390 static void workerGlobalScopeDidClose(ExecutionContext* context, PassRefPtrWillB
eRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WebSocketC
hannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsig
ned short code, const String& reason) |
| 422 { | 391 { |
| 423 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 392 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 424 workerClientWrapper->didClose(closingHandshakeCompletion, code, reason); | 393 workerClientWrapper->didClose(closingHandshakeCompletion, code, reason); |
| 425 } | 394 } |
| 426 | 395 |
| 427 void Peer::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion,
unsigned short code, const String& reason) | 396 void Peer::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion,
unsigned short code, const String& reason) |
| 428 { | 397 { |
| 429 ASSERT(isMainThread()); | 398 ASSERT(isMainThread()); |
| 430 m_mainWebSocketChannel = nullptr; | 399 if (m_mainWebSocketChannel) { |
| 400 m_mainWebSocketChannel->disconnect(); |
| 401 m_mainWebSocketChannel = nullptr; |
| 402 } |
| 431 // It is important to seprate task creation from posting | 403 // It is important to seprate task creation from posting |
| 432 // the task. See the above comment. | 404 // the task. See the above comment. |
| 433 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidClose, m_workerClientWrapper.get(), closingHandshakeCompletion, code, reason)
; | 405 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidClose, m_workerClientWrapper, closingHandshakeCompletion, code, reason); |
| 434 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 406 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 435 } | 407 } |
| 436 | 408 |
| 437 static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, P
assRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapp
er) | 409 static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, P
assRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapp
er) |
| 438 { | 410 { |
| 439 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 411 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
| 440 workerClientWrapper->didReceiveMessageError(); | 412 workerClientWrapper->didReceiveMessageError(); |
| 441 } | 413 } |
| 442 | 414 |
| 443 void Peer::didReceiveMessageError() | 415 void Peer::didReceiveMessageError() |
| 444 { | 416 { |
| 445 ASSERT(isMainThread()); | 417 ASSERT(isMainThread()); |
| 446 // It is important to seprate task creation from posting | 418 // It is important to seprate task creation from posting |
| 447 // the task. See the above comment. | 419 // the task. See the above comment. |
| 448 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessageError, m_workerClientWrapper.get()); | 420 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessageError, m_workerClientWrapper); |
| 449 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 421 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
| 450 } | 422 } |
| 451 | 423 |
| 452 void Peer::trace(Visitor* visitor) | 424 void Peer::trace(Visitor* visitor) |
| 453 { | 425 { |
| 454 visitor->trace(m_workerClientWrapper); | 426 visitor->trace(m_workerClientWrapper); |
| 455 visitor->trace(m_mainWebSocketChannel); | 427 visitor->trace(m_mainWebSocketChannel); |
| 456 visitor->trace(m_syncHelper); | 428 visitor->trace(m_syncHelper); |
| 457 WebSocketChannelClient::trace(visitor); | 429 WebSocketChannelClient::trace(visitor); |
| 458 } | 430 } |
| 459 | 431 |
| 460 Bridge::Bridge(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> w
orkerClientWrapper, WorkerGlobalScope& workerGlobalScope) | 432 Bridge::Bridge(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> w
orkerClientWrapper, WorkerGlobalScope& workerGlobalScope) |
| 461 : m_workerClientWrapper(workerClientWrapper) | 433 : m_workerClientWrapper(workerClientWrapper) |
| 462 , m_workerGlobalScope(workerGlobalScope) | 434 , m_workerGlobalScope(workerGlobalScope) |
| 463 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) | 435 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) |
| 464 , m_syncHelper(nullptr) | 436 , m_syncHelper(ThreadableWebSocketChannelSyncHelper::create(adoptPtr(blink::
Platform::current()->createWaitableEvent()))) |
| 465 , m_peer(nullptr) | 437 , m_peer(Peer::create(m_workerClientWrapper, m_loaderProxy, m_syncHelper)) |
| 466 { | 438 { |
| 467 ASSERT(m_workerClientWrapper.get()); | 439 ASSERT(m_workerClientWrapper.get()); |
| 468 } | 440 } |
| 469 | 441 |
| 470 Bridge::~Bridge() | 442 Bridge::~Bridge() |
| 471 { | 443 { |
| 472 ASSERT(hasTerminatedPeer()); | 444 ASSERT(!m_peer); |
| 473 } | 445 } |
| 474 | 446 |
| 475 void Bridge::initialize(const String& sourceURL, unsigned lineNumber) | 447 void Bridge::initialize(const String& sourceURL, unsigned lineNumber) |
| 476 { | 448 { |
| 477 #if !ENABLE(OILPAN) | |
| 478 RefPtr<WeakReference<Peer> > reference = WeakReference<Peer>::createUnbound(
); | |
| 479 m_peer = WeakPtr<Peer>(reference); | |
| 480 #endif | |
| 481 | |
| 482 RefPtrWillBeRawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = Thread
ableWebSocketChannelSyncHelper::create(adoptPtr(blink::Platform::current()->crea
teWaitableEvent())); | |
| 483 // This pointer is guaranteed to be valid until we call terminatePeer. | |
| 484 m_syncHelper = syncHelper.get(); | |
| 485 | |
| 486 RefPtrWillBeRawPtr<Bridge> protect(this); | 449 RefPtrWillBeRawPtr<Bridge> protect(this); |
| 487 #if ENABLE(OILPAN) | |
| 488 // In order to assure all temporary objects to be destroyed before | 450 // In order to assure all temporary objects to be destroyed before |
| 489 // posting the task, we separate task creation and posting. | 451 // posting the task, we separate task creation and posting. |
| 490 // In other words, it is dangerous to have a complicated expression | 452 // In other words, it is dangerous to have a complicated expression |
| 491 // as a waitForMethodCompletion argument. | 453 // as a waitForMethodCompletion argument. |
| 492 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
&m_peer, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(), s
ourceURL, lineNumber, syncHelper.get()); | 454 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
AllowCrossThreadAccess(m_peer.get()), sourceURL, lineNumber); |
| 493 #else | |
| 494 // See the above comment. | |
| 495 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
reference, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(),
sourceURL, lineNumber, syncHelper.get()); | |
| 496 #endif | |
| 497 if (!waitForMethodCompletion(task.release())) { | 455 if (!waitForMethodCompletion(task.release())) { |
| 498 // The worker thread has been signalled to shutdown before method comple
tion. | 456 // The worker thread has been signalled to shutdown before method comple
tion. |
| 499 disconnect(); | 457 disconnect(); |
| 500 } | 458 } |
| 501 } | 459 } |
| 502 | 460 |
| 503 bool Bridge::connect(const KURL& url, const String& protocol) | 461 bool Bridge::connect(const KURL& url, const String& protocol) |
| 504 { | 462 { |
| 505 if (hasTerminatedPeer()) | 463 if (!m_peer) |
| 506 return false; | 464 return false; |
| 507 | 465 |
| 508 RefPtrWillBeRawPtr<Bridge> protect(this); | 466 RefPtrWillBeRawPtr<Bridge> protect(this); |
| 509 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, m_peer, u
rl, protocol))) | 467 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, m_peer.ge
t(), url, protocol))) |
| 510 return false; | 468 return false; |
| 511 | 469 |
| 512 return m_syncHelper->connectRequestResult(); | 470 return m_syncHelper->connectRequestResult(); |
| 513 } | 471 } |
| 514 | 472 |
| 515 WebSocketChannel::SendResult Bridge::send(const String& message) | 473 WebSocketChannel::SendResult Bridge::send(const String& message) |
| 516 { | 474 { |
| 517 if (hasTerminatedPeer()) | 475 if (!m_peer) |
| 518 return WebSocketChannel::SendFail; | 476 return WebSocketChannel::SendFail; |
| 519 | 477 |
| 520 RefPtrWillBeRawPtr<Bridge> protect(this); | 478 RefPtrWillBeRawPtr<Bridge> protect(this); |
| 521 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::send, m_peer, mess
age))) | 479 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::send, m_peer.get()
, message))) |
| 522 return WebSocketChannel::SendFail; | 480 return WebSocketChannel::SendFail; |
| 523 | 481 |
| 524 return m_syncHelper->sendRequestResult(); | 482 return m_syncHelper->sendRequestResult(); |
| 525 } | 483 } |
| 526 | 484 |
| 527 WebSocketChannel::SendResult Bridge::send(const ArrayBuffer& binaryData, unsigne
d byteOffset, unsigned byteLength) | 485 WebSocketChannel::SendResult Bridge::send(const ArrayBuffer& binaryData, unsigne
d byteOffset, unsigned byteLength) |
| 528 { | 486 { |
| 529 if (hasTerminatedPeer()) | 487 if (!m_peer) |
| 530 return WebSocketChannel::SendFail; | 488 return WebSocketChannel::SendFail; |
| 531 | 489 |
| 532 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied
into Vector<char>. | 490 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied
into Vector<char>. |
| 533 OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); | 491 OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); |
| 534 if (binaryData.byteLength()) | 492 if (binaryData.byteLength()) |
| 535 memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteO
ffset, byteLength); | 493 memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteO
ffset, byteLength); |
| 536 | 494 |
| 537 RefPtrWillBeRawPtr<Bridge> protect(this); | 495 RefPtrWillBeRawPtr<Bridge> protect(this); |
| 538 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendArrayBuffer, m
_peer, data.release()))) | 496 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendArrayBuffer, m
_peer.get(), data.release()))) |
| 539 return WebSocketChannel::SendFail; | 497 return WebSocketChannel::SendFail; |
| 540 | 498 |
| 541 return m_syncHelper->sendRequestResult(); | 499 return m_syncHelper->sendRequestResult(); |
| 542 } | 500 } |
| 543 | 501 |
| 544 WebSocketChannel::SendResult Bridge::send(PassRefPtr<BlobDataHandle> data) | 502 WebSocketChannel::SendResult Bridge::send(PassRefPtr<BlobDataHandle> data) |
| 545 { | 503 { |
| 546 if (hasTerminatedPeer()) | 504 if (!m_peer) |
| 547 return WebSocketChannel::SendFail; | 505 return WebSocketChannel::SendFail; |
| 548 | 506 |
| 549 RefPtrWillBeRawPtr<Bridge> protect(this); | 507 RefPtrWillBeRawPtr<Bridge> protect(this); |
| 550 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendBlob, m_peer,
data))) | 508 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendBlob, m_peer.g
et(), data))) |
| 551 return WebSocketChannel::SendFail; | 509 return WebSocketChannel::SendFail; |
| 552 | 510 |
| 553 return m_syncHelper->sendRequestResult(); | 511 return m_syncHelper->sendRequestResult(); |
| 554 } | 512 } |
| 555 | 513 |
| 556 void Bridge::close(int code, const String& reason) | 514 void Bridge::close(int code, const String& reason) |
| 557 { | 515 { |
| 558 if (hasTerminatedPeer()) | 516 if (!m_peer) |
| 559 return; | 517 return; |
| 560 | 518 |
| 561 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::close, m_peer, c
ode, reason)); | 519 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::close, m_peer.ge
t(), code, reason)); |
| 562 } | 520 } |
| 563 | 521 |
| 564 void Bridge::fail(const String& reason, MessageLevel level, const String& source
URL, unsigned lineNumber) | 522 void Bridge::fail(const String& reason, MessageLevel level, const String& source
URL, unsigned lineNumber) |
| 565 { | 523 { |
| 566 if (hasTerminatedPeer()) | 524 if (!m_peer) |
| 567 return; | 525 return; |
| 568 | 526 |
| 569 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::fail, m_peer, re
ason, level, sourceURL, lineNumber)); | 527 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::fail, m_peer.get
(), reason, level, sourceURL, lineNumber)); |
| 570 } | 528 } |
| 571 | 529 |
| 572 void Bridge::disconnect() | 530 void Bridge::disconnect() |
| 573 { | 531 { |
| 574 if (hasTerminatedPeer()) | 532 if (!m_peer) |
| 575 return; | 533 return; |
| 576 | 534 |
| 577 clearClientWrapper(); | 535 m_workerClientWrapper->clearClient(); |
| 578 terminatePeer(); | 536 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, m_peer.get(
))); |
| 579 } | 537 // Here |m_peer| is detached from the main thread and we can delete it. |
| 580 | 538 |
| 581 void Bridge::clearClientWrapper() | 539 m_peer = nullptr; |
| 582 { | 540 m_syncHelper = nullptr; |
| 583 m_workerClientWrapper->clearClient(); | 541 // We won't use this any more. |
| 542 m_workerGlobalScope.clear(); |
| 584 } | 543 } |
| 585 | 544 |
| 586 // Caller of this function should hold a reference to the bridge, because this f
unction may call WebSocket::didClose() in the end, | 545 // Caller of this function should hold a reference to the bridge, because this f
unction may call WebSocket::didClose() in the end, |
| 587 // which causes the bridge to get disconnected from the WebSocket and deleted if
there is no other reference. | 546 // which causes the bridge to get disconnected from the WebSocket and deleted if
there is no other reference. |
| 588 bool Bridge::waitForMethodCompletion(PassOwnPtr<ExecutionContextTask> task) | 547 bool Bridge::waitForMethodCompletion(PassOwnPtr<ExecutionContextTask> task) |
| 589 { | 548 { |
| 590 ASSERT(m_workerGlobalScope); | 549 ASSERT(m_workerGlobalScope); |
| 591 ASSERT(m_syncHelper); | 550 ASSERT(m_syncHelper); |
| 592 | 551 |
| 593 m_loaderProxy.postTaskToLoader(task); | 552 m_loaderProxy.postTaskToLoader(task); |
| 594 | 553 |
| 595 // We wait for the syncHelper event even if a shutdown event is fired. | 554 // We wait for the syncHelper event even if a shutdown event is fired. |
| 596 // See https://codereview.chromium.org/267323004/#msg43 for why we need to w
ait this. | 555 // See https://codereview.chromium.org/267323004/#msg43 for why we need to w
ait this. |
| 597 Vector<blink::WebWaitableEvent*> events; | |
| 598 events.append(m_syncHelper->event()); | |
| 599 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); | 556 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); |
| 600 blink::Platform::current()->waitMultipleEvents(events); | 557 m_syncHelper->wait(); |
| 601 // This is checking whether a shutdown event is fired or not. | 558 // This is checking whether a shutdown event is fired or not. |
| 602 return !m_workerGlobalScope->thread()->terminated(); | 559 return !m_workerGlobalScope->thread()->terminated(); |
| 603 } | 560 } |
| 604 | 561 |
| 605 void Bridge::terminatePeer() | |
| 606 { | |
| 607 ASSERT(!hasTerminatedPeer()); | |
| 608 | |
| 609 #if ENABLE(OILPAN) | |
| 610 // The worker thread has to wait for the main thread to complete Peer::destr
oy, | |
| 611 // because the worker thread has to make sure that the main thread does not
have any | |
| 612 // references to on-heap objects allocated in the thread heap of the worker
thread | |
| 613 // before the worker thread shuts down. | |
| 614 waitForMethodCompletion(createCrossThreadTask(&Peer::destroy, m_peer)); | |
| 615 #else | |
| 616 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::destroy, m_peer)
); | |
| 617 #endif | |
| 618 | |
| 619 // Peer::destroy() deletes m_peer and then m_syncHelper will be released. | |
| 620 // We must not touch m_syncHelper any more. | |
| 621 m_syncHelper = nullptr; | |
| 622 | |
| 623 // We won't use this any more. | |
| 624 m_workerGlobalScope = nullptr; | |
| 625 } | |
| 626 | |
| 627 void Bridge::trace(Visitor* visitor) | 562 void Bridge::trace(Visitor* visitor) |
| 628 { | 563 { |
| 629 visitor->trace(m_workerClientWrapper); | 564 visitor->trace(m_workerClientWrapper); |
| 630 visitor->trace(m_workerGlobalScope); | 565 visitor->trace(m_workerGlobalScope); |
| 631 visitor->trace(m_syncHelper); | 566 visitor->trace(m_syncHelper); |
| 632 visitor->trace(m_peer); | 567 visitor->trace(m_peer); |
| 633 } | 568 } |
| 634 | 569 |
| 635 } // namespace blink | 570 } // namespace blink |
| OLD | NEW |