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.
5 #include "chrome/test/chromedriver/net/sync_websocket_impl.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"
16 SyncWebSocketImpl::SyncWebSocketImpl(
17 net::URLRequestContextGetter
* context_getter
)
18 : core_(new Core(context_getter
)) {}
20 SyncWebSocketImpl::~SyncWebSocketImpl() {}
22 bool SyncWebSocketImpl::IsConnected() {
23 return core_
->IsConnected();
26 bool SyncWebSocketImpl::Connect(const GURL
& url
) {
27 return core_
->Connect(url
);
30 bool SyncWebSocketImpl::Send(const std::string
& message
) {
31 return core_
->Send(message
);
34 SyncWebSocket::StatusCode
SyncWebSocketImpl::ReceiveNextMessage(
35 std::string
* message
, const base::TimeDelta
& timeout
) {
36 return core_
->ReceiveNextMessage(message
, timeout
);
39 bool SyncWebSocketImpl::HasNextMessage() {
40 return core_
->HasNextMessage();
43 SyncWebSocketImpl::Core::Core(net::URLRequestContextGetter
* context_getter
)
44 : context_getter_(context_getter
),
46 on_update_event_(&lock_
) {}
48 bool SyncWebSocketImpl::Core::IsConnected() {
49 base::AutoLock
lock(lock_
);
53 bool SyncWebSocketImpl::Core::Connect(const GURL
& url
) {
55 base::WaitableEvent
event(false, false);
56 context_getter_
->GetNetworkTaskRunner()->PostTask(
58 base::Bind(&SyncWebSocketImpl::Core::ConnectOnIO
,
59 this, url
, &success
, &event
));
64 bool SyncWebSocketImpl::Core::Send(const std::string
& message
) {
66 base::WaitableEvent
event(false, false);
67 context_getter_
->GetNetworkTaskRunner()->PostTask(
69 base::Bind(&SyncWebSocketImpl::Core::SendOnIO
,
70 this, message
, &success
, &event
));
75 SyncWebSocket::StatusCode
SyncWebSocketImpl::Core::ReceiveNextMessage(
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();
88 return SyncWebSocket::kDisconnected
;
89 *message
= received_queue_
.front();
90 received_queue_
.pop_front();
91 return SyncWebSocket::kOk
;
94 bool SyncWebSocketImpl::Core::HasNextMessage() {
95 base::AutoLock
lock(lock_
);
96 return !received_queue_
.empty();
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();
105 void SyncWebSocketImpl::Core::OnClose() {
106 base::AutoLock
lock(lock_
);
107 is_connected_
= false;
108 on_update_event_
.Signal();
111 SyncWebSocketImpl::Core::~Core() { }
113 void SyncWebSocketImpl::Core::ConnectOnIO(
116 base::WaitableEvent
* event
) {
118 base::AutoLock
lock(lock_
);
119 received_queue_
.clear();
121 socket_
.reset(new WebSocket(url
, this));
122 socket_
->Connect(base::Bind(
123 &SyncWebSocketImpl::Core::OnConnectCompletedOnIO
,
124 this, success
, event
));
127 void SyncWebSocketImpl::Core::OnConnectCompletedOnIO(
129 base::WaitableEvent
* event
,
131 *success
= (error
== net::OK
);
133 base::AutoLock
lock(lock_
);
134 is_connected_
= true;
139 void SyncWebSocketImpl::Core::SendOnIO(
140 const std::string
& message
,
142 base::WaitableEvent
* event
) {
143 *success
= socket_
->Send(message
);
147 void SyncWebSocketImpl::Core::OnDestruct() const {
148 scoped_refptr
<base::SingleThreadTaskRunner
> network_task_runner
=
149 context_getter_
->GetNetworkTaskRunner();
150 if (network_task_runner
->BelongsToCurrentThread())
153 network_task_runner
->DeleteSoon(FROM_HERE
, this);