| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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, "disconnected from DevTools"); |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |