Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: chrome/test/chromedriver/devtools_client_impl.cc

Issue 12321057: [chromedriver] Implement reconnection to DevTools. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase and address comments. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/test/chromedriver/devtools_client_impl.h" 5 #include "chrome/test/chromedriver/devtools_client_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 30 matching lines...) Expand all
41 InspectorEvent::~InspectorEvent() {} 41 InspectorEvent::~InspectorEvent() {}
42 42
43 InspectorCommandResponse::InspectorCommandResponse() {} 43 InspectorCommandResponse::InspectorCommandResponse() {}
44 44
45 InspectorCommandResponse::~InspectorCommandResponse() {} 45 InspectorCommandResponse::~InspectorCommandResponse() {}
46 46
47 } // namespace internal 47 } // namespace internal
48 48
49 DevToolsClientImpl::DevToolsClientImpl( 49 DevToolsClientImpl::DevToolsClientImpl(
50 const SyncWebSocketFactory& factory, 50 const SyncWebSocketFactory& factory,
51 const std::string& url) 51 const std::string& url,
52 const FrontendCloserFunc& frontend_closer_func)
52 : socket_(factory.Run().Pass()), 53 : socket_(factory.Run().Pass()),
53 url_(url), 54 url_(url),
55 frontend_closer_func_(frontend_closer_func),
54 parser_func_(base::Bind(&internal::ParseInspectorMessage)), 56 parser_func_(base::Bind(&internal::ParseInspectorMessage)),
55 connected_(false),
56 next_id_(1) {} 57 next_id_(1) {}
57 58
58 DevToolsClientImpl::DevToolsClientImpl( 59 DevToolsClientImpl::DevToolsClientImpl(
59 const SyncWebSocketFactory& factory, 60 const SyncWebSocketFactory& factory,
60 const std::string& url, 61 const std::string& url,
62 const FrontendCloserFunc& frontend_closer_func,
61 const ParserFunc& parser_func) 63 const ParserFunc& parser_func)
62 : socket_(factory.Run().Pass()), 64 : socket_(factory.Run().Pass()),
63 url_(url), 65 url_(url),
66 frontend_closer_func_(frontend_closer_func),
64 parser_func_(parser_func), 67 parser_func_(parser_func),
65 connected_(false),
66 next_id_(1) {} 68 next_id_(1) {}
67 69
68 DevToolsClientImpl::~DevToolsClientImpl() { 70 DevToolsClientImpl::~DevToolsClientImpl() {
69 for (ResponseMap::iterator iter = cmd_response_map_.begin(); 71 for (ResponseMap::iterator iter = cmd_response_map_.begin();
70 iter != cmd_response_map_.end(); ++iter) { 72 iter != cmd_response_map_.end(); ++iter) {
71 LOG(WARNING) << "Finished with no response for command " << iter->first; 73 LOG(WARNING) << "Finished with no response for command " << iter->first;
72 delete iter->second; 74 delete iter->second;
73 } 75 }
74 } 76 }
75 77
76 void DevToolsClientImpl::SetParserFuncForTesting( 78 void DevToolsClientImpl::SetParserFuncForTesting(
77 const ParserFunc& parser_func) { 79 const ParserFunc& parser_func) {
78 parser_func_ = parser_func; 80 parser_func_ = parser_func;
79 } 81 }
80 82
83 Status DevToolsClientImpl::ConnectIfNecessary() {
84 if (!socket_->IsConnected()) {
85 if (!socket_->Connect(url_)) {
86 // Try to close devtools frontend and then reconnect.
87 Status status = frontend_closer_func_.Run();
88 if (status.IsError())
89 return status;
90 if (!socket_->Connect(url_))
91 return Status(kDisconnected, "unable to connect to renderer");
92 }
93
94 // OnConnected notification will be sent out in method ReceiveNextMessage.
95 listeners_for_on_connected_ = listeners_;
96 }
97 return Status(kOk);
98 }
99
81 Status DevToolsClientImpl::SendCommand( 100 Status DevToolsClientImpl::SendCommand(
82 const std::string& method, 101 const std::string& method,
83 const base::DictionaryValue& params) { 102 const base::DictionaryValue& params) {
84 scoped_ptr<base::DictionaryValue> result; 103 scoped_ptr<base::DictionaryValue> result;
85 return SendCommandInternal(method, params, &result); 104 return SendCommandInternal(method, params, &result);
86 } 105 }
87 106
88 Status DevToolsClientImpl::SendCommandAndGetResult( 107 Status DevToolsClientImpl::SendCommandAndGetResult(
89 const std::string& method, 108 const std::string& method,
90 const base::DictionaryValue& params, 109 const base::DictionaryValue& params,
(...skipping 24 matching lines...) Expand all
115 if (status.IsError()) 134 if (status.IsError())
116 return status; 135 return status;
117 } 136 }
118 return Status(kOk); 137 return Status(kOk);
119 } 138 }
120 139
121 Status DevToolsClientImpl::SendCommandInternal( 140 Status DevToolsClientImpl::SendCommandInternal(
122 const std::string& method, 141 const std::string& method,
123 const base::DictionaryValue& params, 142 const base::DictionaryValue& params,
124 scoped_ptr<base::DictionaryValue>* result) { 143 scoped_ptr<base::DictionaryValue>* result) {
125 if (!connected_) { 144 if (!socket_->IsConnected())
126 if (!socket_->Connect(url_)) 145 return Status(kDisconnected, "unable to connect to renderer");
kkania 2013/03/05 17:01:13 fix the error message; the error isn't that it was
chrisgao (Use stgao instead) 2013/03/06 01:19:54 Done.
127 return Status(kDisconnected, "unable to connect to renderer");
128 connected_ = true;
129
130 // OnConnected notification will be sent out in method ReceiveNextMessage.
131 listeners_for_on_connected_ = listeners_;
132 }
133 146
134 int command_id = next_id_++; 147 int command_id = next_id_++;
135 base::DictionaryValue command; 148 base::DictionaryValue command;
136 command.SetInteger("id", command_id); 149 command.SetInteger("id", command_id);
137 command.SetString("method", method); 150 command.SetString("method", method);
138 command.Set("params", params.DeepCopy()); 151 command.Set("params", params.DeepCopy());
139 std::string message; 152 std::string message;
140 base::JSONWriter::Write(&command, &message); 153 base::JSONWriter::Write(&command, &message);
141 if (!socket_->Send(message)) { 154 if (!socket_->Send(message))
142 connected_ = false;
143 return Status(kDisconnected, "unable to send message to renderer"); 155 return Status(kDisconnected, "unable to send message to renderer");
144 }
145 return ReceiveCommandResponse(command_id, result); 156 return ReceiveCommandResponse(command_id, result);
146 } 157 }
147 158
148 Status DevToolsClientImpl::ReceiveCommandResponse( 159 Status DevToolsClientImpl::ReceiveCommandResponse(
149 int command_id, 160 int command_id,
150 scoped_ptr<base::DictionaryValue>* result) { 161 scoped_ptr<base::DictionaryValue>* result) {
151 internal::InspectorMessageType type; 162 internal::InspectorMessageType type;
152 internal::InspectorEvent event; 163 internal::InspectorEvent event;
153 internal::InspectorCommandResponse response; 164 internal::InspectorCommandResponse response;
154 cmd_response_map_[command_id] = NULL; 165 cmd_response_map_[command_id] = NULL;
(...skipping 18 matching lines...) Expand all
173 Status status = listener->OnConnected(); 184 Status status = listener->OnConnected();
174 if (status.IsError()) 185 if (status.IsError())
175 return status; 186 return status;
176 } 187 }
177 // The message might be received already when processing other commands sent 188 // The message might be received already when processing other commands sent
178 // from DevToolsEventListener::OnConnected. 189 // from DevToolsEventListener::OnConnected.
179 if (HasReceivedCommandResponse(expected_id)) 190 if (HasReceivedCommandResponse(expected_id))
180 return Status(kOk); 191 return Status(kOk);
181 192
182 std::string message; 193 std::string message;
183 if (!socket_->ReceiveNextMessage(&message)) { 194 if (!socket_->ReceiveNextMessage(&message))
184 connected_ = false; 195 return Status(kDisconnected, "unable to receive message from renderer");
185 return Status(kDisconnected,
186 "unable to receive message from renderer");
187 }
188 if (!parser_func_.Run(message, expected_id, type, event, response)) 196 if (!parser_func_.Run(message, expected_id, type, event, response))
189 return Status(kUnknownError, "bad inspector message: " + message); 197 return Status(kUnknownError, "bad inspector message: " + message);
190 if (*type == internal::kEventMessageType) 198 if (*type == internal::kEventMessageType)
191 return NotifyEventListeners(event->method, *event->params); 199 return NotifyEventListeners(event->method, *event->params);
192 if (*type == internal::kCommandResponseMessageType) { 200 if (*type == internal::kCommandResponseMessageType) {
193 if (cmd_response_map_.count(response->id) == 0) { 201 if (cmd_response_map_.count(response->id) == 0) {
194 return Status(kUnknownError, "unexpected command message"); 202 return Status(kUnknownError, "unexpected command message");
195 } else if (response->result) { 203 } else if (response->result) {
196 cmd_response_map_[response->id] = response->result.release(); 204 cmd_response_map_[response->id] = response->result.release();
197 } else { 205 } else {
198 cmd_response_map_.erase(response->id); 206 cmd_response_map_.erase(response->id);
199 return ParseInspectorError(response->error); 207 return ParseInspectorError(response->error);
200 } 208 }
201 } 209 }
202 return Status(kOk); 210 return Status(kOk);
203 } 211 }
204 212
205 bool DevToolsClientImpl::HasReceivedCommandResponse(int cmd_id) { 213 bool DevToolsClientImpl::HasReceivedCommandResponse(int cmd_id) {
206 return cmd_response_map_.find(cmd_id) != cmd_response_map_.end() 214 return cmd_response_map_.find(cmd_id) != cmd_response_map_.end()
207 && cmd_response_map_[cmd_id] != NULL; 215 && cmd_response_map_[cmd_id] != NULL;
208 } 216 }
209 217
210 Status DevToolsClientImpl::NotifyEventListeners( 218 Status DevToolsClientImpl::NotifyEventListeners(
211 const std::string& method, 219 const std::string& method,
212 const base::DictionaryValue& params) { 220 const base::DictionaryValue& params) {
213 for (std::list<DevToolsEventListener*>::iterator iter = listeners_.begin(); 221 for (std::list<DevToolsEventListener*>::iterator iter = listeners_.begin();
214 iter != listeners_.end(); ++iter) { 222 iter != listeners_.end(); ++iter) {
215 (*iter)->OnEvent(method, params); 223 (*iter)->OnEvent(method, params);
216 } 224 }
217 if (method == "Inspector.detached") { 225 if (method == "Inspector.detached")
218 connected_ = false;
219 return Status(kDisconnected, "received Inspector.detached event"); 226 return Status(kDisconnected, "received Inspector.detached event");
220 }
221 return Status(kOk); 227 return Status(kOk);
222 } 228 }
223 229
224 namespace internal { 230 namespace internal {
225 231
226 bool ParseInspectorMessage( 232 bool ParseInspectorMessage(
227 const std::string& message, 233 const std::string& message,
228 int expected_id, 234 int expected_id,
229 InspectorMessageType* type, 235 InspectorMessageType* type,
230 InspectorEvent* event, 236 InspectorEvent* event,
(...skipping 30 matching lines...) Expand all
261 if (unscoped_result) 267 if (unscoped_result)
262 command_response->result.reset(unscoped_result->DeepCopy()); 268 command_response->result.reset(unscoped_result->DeepCopy());
263 else 269 else
264 base::JSONWriter::Write(unscoped_error, &command_response->error); 270 base::JSONWriter::Write(unscoped_error, &command_response->error);
265 return true; 271 return true;
266 } 272 }
267 return false; 273 return false;
268 } 274 }
269 275
270 } // namespace internal 276 } // namespace internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698