Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/test/chromedriver/net/sync_websocket_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/location.h"
     10 #include "base/single_thread_task_runner.h"
     11 #include "base/synchronization/waitable_event.h"
     12 #include "net/base/net_errors.h"
     13 #include "net/url_request/url_request_context_getter.h"
     14 #include "url/gurl.h"
     15 
     16 SyncWebSocketImpl::SyncWebSocketImpl(
     17     net::URLRequestContextGetter* context_getter)
     18     : core_(new Core(context_getter)) {}
     19 
     20 SyncWebSocketImpl::~SyncWebSocketImpl() {}
     21 
     22 bool SyncWebSocketImpl::IsConnected() {
     23   return core_->IsConnected();
     24 }
     25 
     26 bool SyncWebSocketImpl::Connect(const GURL& url) {
     27   return core_->Connect(url);
     28 }
     29 
     30 bool SyncWebSocketImpl::Send(const std::string& message) {
     31   return core_->Send(message);
     32 }
     33 
     34 SyncWebSocket::StatusCode SyncWebSocketImpl::ReceiveNextMessage(
     35     std::string* message, const base::TimeDelta& timeout) {
     36   return core_->ReceiveNextMessage(message, timeout);
     37 }
     38 
     39 bool SyncWebSocketImpl::HasNextMessage() {
     40   return core_->HasNextMessage();
     41 }
     42 
     43 SyncWebSocketImpl::Core::Core(net::URLRequestContextGetter* context_getter)
     44     : context_getter_(context_getter),
     45       is_connected_(false),
     46       on_update_event_(&lock_) {}
     47 
     48 bool SyncWebSocketImpl::Core::IsConnected() {
     49   base::AutoLock lock(lock_);
     50   return is_connected_;
     51 }
     52 
     53 bool SyncWebSocketImpl::Core::Connect(const GURL& url) {
     54   bool success = false;
     55   base::WaitableEvent event(false, false);
     56   context_getter_->GetNetworkTaskRunner()->PostTask(
     57       FROM_HERE,
     58       base::Bind(&SyncWebSocketImpl::Core::ConnectOnIO,
     59                  this, url, &success, &event));
     60   event.Wait();
     61   return success;
     62 }
     63 
     64 bool SyncWebSocketImpl::Core::Send(const std::string& message) {
     65   bool success = false;
     66   base::WaitableEvent event(false, false);
     67   context_getter_->GetNetworkTaskRunner()->PostTask(
     68       FROM_HERE,
     69       base::Bind(&SyncWebSocketImpl::Core::SendOnIO,
     70                  this, message, &success, &event));
     71   event.Wait();
     72   return success;
     73 }
     74 
     75 SyncWebSocket::StatusCode SyncWebSocketImpl::Core::ReceiveNextMessage(
     76     std::string* message,
     77     const base::TimeDelta& timeout) {
     78   base::AutoLock lock(lock_);
     79   base::TimeTicks deadline = base::TimeTicks::Now() + timeout;
     80   base::TimeDelta next_wait = timeout;
     81   while (received_queue_.empty() && is_connected_) {
     82     if (next_wait <= base::TimeDelta())
     83       return SyncWebSocket::kTimeout;
     84     on_update_event_.TimedWait(next_wait);
     85     next_wait = deadline - base::TimeTicks::Now();
     86   }
     87   if (!is_connected_)
     88     return SyncWebSocket::kDisconnected;
     89   *message = received_queue_.front();
     90   received_queue_.pop_front();
     91   return SyncWebSocket::kOk;
     92 }
     93 
     94 bool SyncWebSocketImpl::Core::HasNextMessage() {
     95   base::AutoLock lock(lock_);
     96   return !received_queue_.empty();
     97 }
     98 
     99 void SyncWebSocketImpl::Core::OnMessageReceived(const std::string& message) {
    100   base::AutoLock lock(lock_);
    101   received_queue_.push_back(message);
    102   on_update_event_.Signal();
    103 }
    104 
    105 void SyncWebSocketImpl::Core::OnClose() {
    106   base::AutoLock lock(lock_);
    107   is_connected_ = false;
    108   on_update_event_.Signal();
    109 }
    110 
    111 SyncWebSocketImpl::Core::~Core() { }
    112 
    113 void SyncWebSocketImpl::Core::ConnectOnIO(
    114     const GURL& url,
    115     bool* success,
    116     base::WaitableEvent* event) {
    117   {
    118     base::AutoLock lock(lock_);
    119     received_queue_.clear();
    120   }
    121   socket_.reset(new WebSocket(url, this));
    122   socket_->Connect(base::Bind(
    123       &SyncWebSocketImpl::Core::OnConnectCompletedOnIO,
    124       this, success, event));
    125 }
    126 
    127 void SyncWebSocketImpl::Core::OnConnectCompletedOnIO(
    128     bool* success,
    129     base::WaitableEvent* event,
    130     int error) {
    131   *success = (error == net::OK);
    132   if (*success) {
    133     base::AutoLock lock(lock_);
    134     is_connected_ = true;
    135   }
    136   event->Signal();
    137 }
    138 
    139 void SyncWebSocketImpl::Core::SendOnIO(
    140     const std::string& message,
    141     bool* success,
    142     base::WaitableEvent* event) {
    143   *success = socket_->Send(message);
    144   event->Signal();
    145 }
    146 
    147 void SyncWebSocketImpl::Core::OnDestruct() const {
    148   scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
    149       context_getter_->GetNetworkTaskRunner();
    150   if (network_task_runner->BelongsToCurrentThread())
    151     delete this;
    152   else
    153     network_task_runner->DeleteSoon(FROM_HERE, this);
    154 }
    155