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_CHROME_DEVTOOLS_CLIENT_IMPL_H_
6#define CHROME_TEST_CHROMEDRIVER_CHROME_DEVTOOLS_CLIENT_IMPL_H_
7
8#include <list>
9#include <map>
10#include <string>
11
12#include "base/basictypes.h"
13#include "base/callback.h"
14#include "base/compiler_specific.h"
15#include "base/memory/linked_ptr.h"
16#include "base/memory/scoped_ptr.h"
17#include "chrome/test/chromedriver/chrome/devtools_client.h"
18#include "chrome/test/chromedriver/net/sync_websocket_factory.h"
19#include "url/gurl.h"
20
21namespace base {
22class DictionaryValue;
23}
24
25namespace internal {
26
27enum InspectorMessageType {
28  kEventMessageType = 0,
29  kCommandResponseMessageType
30};
31
32struct InspectorEvent {
33  InspectorEvent();
34  ~InspectorEvent();
35  std::string method;
36  scoped_ptr<base::DictionaryValue> params;
37};
38
39struct InspectorCommandResponse {
40  InspectorCommandResponse();
41  ~InspectorCommandResponse();
42  int id;
43  std::string error;
44  scoped_ptr<base::DictionaryValue> result;
45};
46
47}  // namespace internal
48
49class DevToolsEventListener;
50class Status;
51class SyncWebSocket;
52
53class DevToolsClientImpl : public DevToolsClient {
54 public:
55  static const char kBrowserwideDevToolsClientId[];
56
57  DevToolsClientImpl(const SyncWebSocketFactory& factory,
58                     const std::string& url,
59                     const std::string& id);
60
61  typedef base::Callback<Status()> FrontendCloserFunc;
62  DevToolsClientImpl(const SyncWebSocketFactory& factory,
63                     const std::string& url,
64                     const std::string& id,
65                     const FrontendCloserFunc& frontend_closer_func);
66
67  typedef base::Callback<bool(
68      const std::string&,
69      int,
70      internal::InspectorMessageType*,
71      internal::InspectorEvent*,
72      internal::InspectorCommandResponse*)> ParserFunc;
73  DevToolsClientImpl(const SyncWebSocketFactory& factory,
74                     const std::string& url,
75                     const std::string& id,
76                     const FrontendCloserFunc& frontend_closer_func,
77                     const ParserFunc& parser_func);
78
79  virtual ~DevToolsClientImpl();
80
81  void SetParserFuncForTesting(const ParserFunc& parser_func);
82
83  // Overridden from DevToolsClient:
84  virtual const std::string& GetId() OVERRIDE;
85  virtual bool WasCrashed() OVERRIDE;
86  virtual Status ConnectIfNecessary() OVERRIDE;
87  virtual Status SendCommand(const std::string& method,
88                             const base::DictionaryValue& params) OVERRIDE;
89  virtual Status SendCommandAndGetResult(
90      const std::string& method,
91      const base::DictionaryValue& params,
92      scoped_ptr<base::DictionaryValue>* result) OVERRIDE;
93  virtual void AddListener(DevToolsEventListener* listener) OVERRIDE;
94  virtual Status HandleEventsUntil(
95      const ConditionalFunc& conditional_func,
96      const base::TimeDelta& timeout) OVERRIDE;
97  virtual Status HandleReceivedEvents() OVERRIDE;
98
99 private:
100  enum ResponseState {
101    // The client is waiting for the response.
102    kWaiting,
103    // The command response will not be received because it is blocked by an
104    // alert that the command triggered.
105    kBlocked,
106    // The client no longer cares about the response.
107    kIgnored,
108    // The response has been received.
109    kReceived
110  };
111  struct ResponseInfo {
112    explicit ResponseInfo(const std::string& method);
113    ~ResponseInfo();
114
115    ResponseState state;
116    std::string method;
117    internal::InspectorCommandResponse response;
118  };
119  typedef std::map<int, linked_ptr<ResponseInfo> > ResponseInfoMap;
120
121  Status SendCommandInternal(
122      const std::string& method,
123      const base::DictionaryValue& params,
124      scoped_ptr<base::DictionaryValue>* result);
125  Status ProcessNextMessage(int expected_id, const base::TimeDelta& timeout);
126  Status ProcessEvent(const internal::InspectorEvent& event);
127  Status ProcessCommandResponse(
128      const internal::InspectorCommandResponse& response);
129  Status EnsureListenersNotifiedOfConnect();
130  Status EnsureListenersNotifiedOfEvent();
131  Status EnsureListenersNotifiedOfCommandResponse();
132
133  scoped_ptr<SyncWebSocket> socket_;
134  GURL url_;
135  bool crashed_;
136  const std::string id_;
137  FrontendCloserFunc frontend_closer_func_;
138  ParserFunc parser_func_;
139  std::list<DevToolsEventListener*> listeners_;
140  std::list<DevToolsEventListener*> unnotified_connect_listeners_;
141  std::list<DevToolsEventListener*> unnotified_event_listeners_;
142  const internal::InspectorEvent* unnotified_event_;
143  std::list<DevToolsEventListener*> unnotified_cmd_response_listeners_;
144  linked_ptr<ResponseInfo> unnotified_cmd_response_info_;
145  ResponseInfoMap response_info_map_;
146  int next_id_;
147  int stack_count_;
148
149  DISALLOW_COPY_AND_ASSIGN(DevToolsClientImpl);
150};
151
152namespace internal {
153
154bool ParseInspectorMessage(
155    const std::string& message,
156    int expected_id,
157    InspectorMessageType* type,
158    InspectorEvent* event,
159    InspectorCommandResponse* command_response);
160
161}  // namespace internal
162
163#endif  // CHROME_TEST_CHROMEDRIVER_CHROME_DEVTOOLS_CLIENT_IMPL_H_
164