12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/sync_websocket_impl.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/single_thread_task_runner.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncWebSocketImpl::SyncWebSocketImpl( 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLRequestContextGetter* context_getter) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : core_(new Core(context_getter)) {} 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncWebSocketImpl::~SyncWebSocketImpl() {} 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::IsConnected() { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return core_->IsConnected(); 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::Connect(const GURL& url) { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return core_->Connect(url); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::Send(const std::string& message) { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return core_->Send(message); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SyncWebSocket::StatusCode SyncWebSocketImpl::ReceiveNextMessage( 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, const base::TimeDelta& timeout) { 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return core_->ReceiveNextMessage(message, timeout); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::HasNextMessage() { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return core_->HasNextMessage(); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncWebSocketImpl::Core::Core(net::URLRequestContextGetter* context_getter) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : context_getter_(context_getter), 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_connected_(false), 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_update_event_(&lock_) {} 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::Core::IsConnected() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_connected_; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::Core::Connect(const GURL& url) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = false; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent event(false, false); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_getter_->GetNetworkTaskRunner()->PostTask( 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SyncWebSocketImpl::Core::ConnectOnIO, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, url, &success, &event)); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event.Wait(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::Core::Send(const std::string& message) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = false; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent event(false, false); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_getter_->GetNetworkTaskRunner()->PostTask( 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SyncWebSocketImpl::Core::SendOnIO, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, message, &success, &event)); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event.Wait(); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SyncWebSocket::StatusCode SyncWebSocketImpl::Core::ReceiveNextMessage( 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) { 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeTicks deadline = base::TimeTicks::Now() + timeout; 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::TimeDelta next_wait = timeout; 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (received_queue_.empty() && is_connected_) { 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (next_wait <= base::TimeDelta()) 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kTimeout; 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) on_update_event_.TimedWait(next_wait); 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) next_wait = deadline - base::TimeTicks::Now(); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_connected_) 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kDisconnected; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *message = received_queue_.front(); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) received_queue_.pop_front(); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kOk; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncWebSocketImpl::Core::HasNextMessage() { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !received_queue_.empty(); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncWebSocketImpl::Core::OnMessageReceived(const std::string& message) { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) received_queue_.push_back(message); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_update_event_.Signal(); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncWebSocketImpl::Core::OnClose() { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_connected_ = false; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_update_event_.Signal(); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncWebSocketImpl::Core::~Core() { } 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncWebSocketImpl::Core::ConnectOnIO( 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* success, 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent* event) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) received_queue_.clear(); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) socket_.reset(new WebSocket(url, this)); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) socket_->Connect(base::Bind( 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &SyncWebSocketImpl::Core::OnConnectCompletedOnIO, 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, success, event)); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncWebSocketImpl::Core::OnConnectCompletedOnIO( 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* success, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent* event, 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int error) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *success = (error == net::OK); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*success) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(lock_); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_connected_ = true; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->Signal(); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncWebSocketImpl::Core::SendOnIO( 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* success, 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent* event) { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *success = socket_->Send(message); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->Signal(); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncWebSocketImpl::Core::OnDestruct() const { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> network_task_runner = 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_getter_->GetNetworkTaskRunner(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (network_task_runner->BelongsToCurrentThread()) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete this; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) network_task_runner->DeleteSoon(FROM_HERE, this); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 155