Chromium Code Reviews| 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::EnsureConnected() { | |
| 84 if (!socket_->IsConnected()) { | |
| 85 // Try to close devtools frontend and then reconnect. | |
| 86 Status status = frontend_closer_func_.Run(); | |
|
kkania
2013/03/04 23:33:57
do we want to try to connect before closing all th
chrisgao (Use stgao instead)
2013/03/05 06:58:17
Done.
| |
| 87 if (status.IsError()) | |
| 88 return status; | |
| 89 if (!socket_->Connect(url_)) | |
| 90 return Status(kDisconnected, "unable to connect to renderer"); | |
| 91 | |
| 92 // OnConnected notification will be sent out in method ReceiveNextMessage. | |
| 93 listeners_for_on_connected_ = listeners_; | |
| 94 } | |
| 95 return Status(kOk); | |
| 96 } | |
| 97 | |
| 81 Status DevToolsClientImpl::SendCommand( | 98 Status DevToolsClientImpl::SendCommand( |
| 82 const std::string& method, | 99 const std::string& method, |
| 83 const base::DictionaryValue& params) { | 100 const base::DictionaryValue& params) { |
| 84 scoped_ptr<base::DictionaryValue> result; | 101 scoped_ptr<base::DictionaryValue> result; |
| 85 return SendCommandInternal(method, params, &result); | 102 return SendCommandInternal(method, params, &result); |
| 86 } | 103 } |
| 87 | 104 |
| 88 Status DevToolsClientImpl::SendCommandAndGetResult( | 105 Status DevToolsClientImpl::SendCommandAndGetResult( |
| 89 const std::string& method, | 106 const std::string& method, |
| 90 const base::DictionaryValue& params, | 107 const base::DictionaryValue& params, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 115 if (status.IsError()) | 132 if (status.IsError()) |
| 116 return status; | 133 return status; |
| 117 } | 134 } |
| 118 return Status(kOk); | 135 return Status(kOk); |
| 119 } | 136 } |
| 120 | 137 |
| 121 Status DevToolsClientImpl::SendCommandInternal( | 138 Status DevToolsClientImpl::SendCommandInternal( |
| 122 const std::string& method, | 139 const std::string& method, |
| 123 const base::DictionaryValue& params, | 140 const base::DictionaryValue& params, |
| 124 scoped_ptr<base::DictionaryValue>* result) { | 141 scoped_ptr<base::DictionaryValue>* result) { |
| 125 if (!connected_) { | 142 if (!socket_->IsConnected()) |
| 126 if (!socket_->Connect(url_)) | 143 return Status(kDisconnected, "unable to connect to renderer"); |
| 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 | 144 |
| 134 int command_id = next_id_++; | 145 int command_id = next_id_++; |
| 135 base::DictionaryValue command; | 146 base::DictionaryValue command; |
| 136 command.SetInteger("id", command_id); | 147 command.SetInteger("id", command_id); |
| 137 command.SetString("method", method); | 148 command.SetString("method", method); |
| 138 command.Set("params", params.DeepCopy()); | 149 command.Set("params", params.DeepCopy()); |
| 139 std::string message; | 150 std::string message; |
| 140 base::JSONWriter::Write(&command, &message); | 151 base::JSONWriter::Write(&command, &message); |
| 141 if (!socket_->Send(message)) { | 152 if (!socket_->Send(message)) |
| 142 connected_ = false; | |
| 143 return Status(kDisconnected, "unable to send message to renderer"); | 153 return Status(kDisconnected, "unable to send message to renderer"); |
| 144 } | |
| 145 return ReceiveCommandResponse(command_id, result); | 154 return ReceiveCommandResponse(command_id, result); |
| 146 } | 155 } |
| 147 | 156 |
| 148 Status DevToolsClientImpl::ReceiveCommandResponse( | 157 Status DevToolsClientImpl::ReceiveCommandResponse( |
| 149 int command_id, | 158 int command_id, |
| 150 scoped_ptr<base::DictionaryValue>* result) { | 159 scoped_ptr<base::DictionaryValue>* result) { |
| 151 internal::InspectorMessageType type; | 160 internal::InspectorMessageType type; |
| 152 internal::InspectorEvent event; | 161 internal::InspectorEvent event; |
| 153 internal::InspectorCommandResponse response; | 162 internal::InspectorCommandResponse response; |
| 154 cmd_response_map_[command_id] = NULL; | 163 cmd_response_map_[command_id] = NULL; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 173 Status status = listener->OnConnected(); | 182 Status status = listener->OnConnected(); |
| 174 if (status.IsError()) | 183 if (status.IsError()) |
| 175 return status; | 184 return status; |
| 176 } | 185 } |
| 177 // The message might be received already when processing other commands sent | 186 // The message might be received already when processing other commands sent |
| 178 // from DevToolsEventListener::OnConnected. | 187 // from DevToolsEventListener::OnConnected. |
| 179 if (HasReceivedCommandResponse(expected_id)) | 188 if (HasReceivedCommandResponse(expected_id)) |
| 180 return Status(kOk); | 189 return Status(kOk); |
| 181 | 190 |
| 182 std::string message; | 191 std::string message; |
| 183 if (!socket_->ReceiveNextMessage(&message)) { | 192 if (!socket_->ReceiveNextMessage(&message)) |
| 184 connected_ = false; | 193 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)) | 194 if (!parser_func_.Run(message, expected_id, type, event, response)) |
| 189 return Status(kUnknownError, "bad inspector message: " + message); | 195 return Status(kUnknownError, "bad inspector message: " + message); |
| 190 if (*type == internal::kEventMessageType) | 196 if (*type == internal::kEventMessageType) |
| 191 return NotifyEventListeners(event->method, *event->params); | 197 return NotifyEventListeners(event->method, *event->params); |
| 192 if (*type == internal::kCommandResponseMessageType) { | 198 if (*type == internal::kCommandResponseMessageType) { |
| 193 if (cmd_response_map_.count(response->id) == 0) { | 199 if (cmd_response_map_.count(response->id) == 0) { |
| 194 return Status(kUnknownError, "unexpected command message"); | 200 return Status(kUnknownError, "unexpected command message"); |
| 195 } else if (response->result) { | 201 } else if (response->result) { |
| 196 cmd_response_map_[response->id] = response->result.release(); | 202 cmd_response_map_[response->id] = response->result.release(); |
| 197 } else { | 203 } else { |
| 198 cmd_response_map_.erase(response->id); | 204 cmd_response_map_.erase(response->id); |
| 199 return ParseInspectorError(response->error); | 205 return ParseInspectorError(response->error); |
| 200 } | 206 } |
| 201 } | 207 } |
| 202 return Status(kOk); | 208 return Status(kOk); |
| 203 } | 209 } |
| 204 | 210 |
| 205 bool DevToolsClientImpl::HasReceivedCommandResponse(int cmd_id) { | 211 bool DevToolsClientImpl::HasReceivedCommandResponse(int cmd_id) { |
| 206 return cmd_response_map_.find(cmd_id) != cmd_response_map_.end() | 212 return cmd_response_map_.find(cmd_id) != cmd_response_map_.end() |
| 207 && cmd_response_map_[cmd_id] != NULL; | 213 && cmd_response_map_[cmd_id] != NULL; |
| 208 } | 214 } |
| 209 | 215 |
| 210 Status DevToolsClientImpl::NotifyEventListeners( | 216 Status DevToolsClientImpl::NotifyEventListeners( |
| 211 const std::string& method, | 217 const std::string& method, |
| 212 const base::DictionaryValue& params) { | 218 const base::DictionaryValue& params) { |
| 213 for (std::list<DevToolsEventListener*>::iterator iter = listeners_.begin(); | 219 for (std::list<DevToolsEventListener*>::iterator iter = listeners_.begin(); |
| 214 iter != listeners_.end(); ++iter) { | 220 iter != listeners_.end(); ++iter) { |
| 215 (*iter)->OnEvent(method, params); | 221 (*iter)->OnEvent(method, params); |
| 216 } | 222 } |
| 217 if (method == "Inspector.detached") { | 223 if (method == "Inspector.detached") |
| 218 connected_ = false; | |
| 219 return Status(kDisconnected, "received Inspector.detached event"); | 224 return Status(kDisconnected, "received Inspector.detached event"); |
| 220 } | |
| 221 return Status(kOk); | 225 return Status(kOk); |
| 222 } | 226 } |
| 223 | 227 |
| 224 namespace internal { | 228 namespace internal { |
| 225 | 229 |
| 226 bool ParseInspectorMessage( | 230 bool ParseInspectorMessage( |
| 227 const std::string& message, | 231 const std::string& message, |
| 228 int expected_id, | 232 int expected_id, |
| 229 InspectorMessageType* type, | 233 InspectorMessageType* type, |
| 230 InspectorEvent* event, | 234 InspectorEvent* event, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 261 if (unscoped_result) | 265 if (unscoped_result) |
| 262 command_response->result.reset(unscoped_result->DeepCopy()); | 266 command_response->result.reset(unscoped_result->DeepCopy()); |
| 263 else | 267 else |
| 264 base::JSONWriter::Write(unscoped_error, &command_response->error); | 268 base::JSONWriter::Write(unscoped_error, &command_response->error); |
| 265 return true; | 269 return true; |
| 266 } | 270 } |
| 267 return false; | 271 return false; |
| 268 } | 272 } |
| 269 | 273 |
| 270 } // namespace internal | 274 } // namespace internal |
| OLD | NEW |