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#ifndef CHROME_TEST_CHROMEDRIVER_NET_SYNC_WEBSOCKET_IMPL_H_
6#define CHROME_TEST_CHROMEDRIVER_NET_SYNC_WEBSOCKET_IMPL_H_
7
8#include <list>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/synchronization/condition_variable.h"
16#include "base/synchronization/lock.h"
17#include "chrome/test/chromedriver/net/sync_websocket.h"
18#include "chrome/test/chromedriver/net/websocket.h"
19#include "net/base/completion_callback.h"
20#include "net/socket_stream/socket_stream.h"
21
22namespace base {
23class WaitableEvent;
24}
25
26namespace net {
27class URLRequestContextGetter;
28}
29
30class GURL;
31
32class SyncWebSocketImpl : public SyncWebSocket {
33 public:
34  explicit SyncWebSocketImpl(net::URLRequestContextGetter* context_getter);
35  virtual ~SyncWebSocketImpl();
36
37  // Overridden from SyncWebSocket:
38  virtual bool IsConnected() OVERRIDE;
39  virtual bool Connect(const GURL& url) OVERRIDE;
40  virtual bool Send(const std::string& message) OVERRIDE;
41  virtual StatusCode ReceiveNextMessage(
42      std::string* message,
43      const base::TimeDelta& timeout) OVERRIDE;
44  virtual bool HasNextMessage() OVERRIDE;
45
46 private:
47  struct CoreTraits;
48  class Core : public WebSocketListener,
49               public base::RefCountedThreadSafe<Core, CoreTraits> {
50   public:
51    explicit Core(net::URLRequestContextGetter* context_getter);
52
53    bool IsConnected();
54    bool Connect(const GURL& url);
55    bool Send(const std::string& message);
56    SyncWebSocket::StatusCode ReceiveNextMessage(
57        std::string* message,
58        const base::TimeDelta& timeout);
59    bool HasNextMessage();
60
61    // Overriden from WebSocketListener:
62    virtual void OnMessageReceived(const std::string& message) OVERRIDE;
63    virtual void OnClose() OVERRIDE;
64
65   private:
66    friend class base::RefCountedThreadSafe<Core, CoreTraits>;
67    friend class base::DeleteHelper<Core>;
68    friend struct CoreTraits;
69
70    virtual ~Core();
71
72    void ConnectOnIO(const GURL& url,
73                     bool* success,
74                     base::WaitableEvent* event);
75    void OnConnectCompletedOnIO(bool* connected,
76                                base::WaitableEvent* event,
77                                int error);
78    void SendOnIO(const std::string& message,
79                  bool* result,
80                  base::WaitableEvent* event);
81
82    // OnDestruct is meant to ensure deletion on the IO thread.
83    void OnDestruct() const;
84
85    scoped_refptr<net::URLRequestContextGetter> context_getter_;
86
87    // Only accessed on IO thread.
88    scoped_ptr<WebSocket> socket_;
89
90    base::Lock lock_;
91
92    // Protected by |lock_|.
93    bool is_connected_;
94
95    // Protected by |lock_|.
96    std::list<std::string> received_queue_;
97
98    // Protected by |lock_|.
99    // Signaled when the socket closes or a message is received.
100    base::ConditionVariable on_update_event_;
101  };
102
103  scoped_refptr<Core> core_;
104};
105
106struct SyncWebSocketImpl::CoreTraits {
107  static void Destruct(const SyncWebSocketImpl::Core* core) {
108    core->OnDestruct();
109  }
110};
111
112#endif  // CHROME_TEST_CHROMEDRIVER_NET_SYNC_WEBSOCKET_IMPL_H_
113