devtools_client_impl.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/stringprintf.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_event_listener.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/log.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/chromedriver/net/sync_websocket.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/chromedriver/net/url_request_context_getter.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* kInspectorContextError = 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Execution context with given id not found."; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status ParseInspectorError(const std::string& error_json) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> error(base::JSONReader::Read(error_json)); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* error_dict; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!error || !error->GetAsDictionary(&error_dict)) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "inspector error with no error message"); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_message; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_dict->GetString("message", &error_message) && 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message == kInspectorContextError) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kNoSuchExecutionContext); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "unhandled inspector error: " + error_json); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedIncrementer { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ScopedIncrementer(int* count) : count_(count) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*count_)++; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedIncrementer() { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*count_)--; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* count_; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InspectorEvent::InspectorEvent() {} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InspectorEvent::~InspectorEvent() {} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InspectorCommandResponse::InspectorCommandResponse() {} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InspectorCommandResponse::~InspectorCommandResponse() {} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internal 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsClientImpl::DevToolsClientImpl( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SyncWebSocketFactory& factory, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& id, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FrontendCloserFunc& frontend_closer_func, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log* log) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(factory.Run().Pass()), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_(url), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(id), 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frontend_closer_func_(frontend_closer_func), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_(log), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser_func_(base::Bind(&internal::ParseInspectorMessage)), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_(NULL), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_id_(1), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_count_(0) {} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsClientImpl::DevToolsClientImpl( 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SyncWebSocketFactory& factory, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& id, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FrontendCloserFunc& frontend_closer_func, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log* log, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ParserFunc& parser_func) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(factory.Run().Pass()), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_(url), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(id), 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frontend_closer_func_(frontend_closer_func), 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_(log), 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser_func_(parser_func), 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_(NULL), 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_id_(1), 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_count_(0) {} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsClientImpl::~DevToolsClientImpl() {} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsClientImpl::SetParserFuncForTesting( 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ParserFunc& parser_func) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser_func_ = parser_func; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& DevToolsClientImpl::GetId() { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::ConnectIfNecessary() { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_count_) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "cannot connect when nested"); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_->IsConnected()) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->Connect(url_)) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to close devtools frontend and then reconnect. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = frontend_closer_func_.Run(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->Connect(url_)) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "unable to connect to renderer"); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_connect_listeners_ = listeners_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_listeners_.clear(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info_map_.clear(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify all listeners of the new connection. Do this now so that any errors 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that occur are reported now instead of later during some unrelated call. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also gives listeners a chance to send commands before other clients. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnsureListenersNotifiedOfConnect(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::SendCommand( 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue& params) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> result; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SendCommandInternal(method, params, &result); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::SendCommandAndGetResult( 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue& params, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue>* result) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> intermediate_result; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = SendCommandInternal(method, params, &intermediate_result); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!intermediate_result) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "inspector response missing result"); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->reset(intermediate_result.release()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsClientImpl::AddListener(DevToolsEventListener* listener) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(listener); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.push_back(listener); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::HandleReceivedEvents() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->IsConnected()) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "not connected to DevTools"); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->HasNextMessage()) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = ProcessNextMessage(-1); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::HandleEventsUntil( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ConditionalFunc& conditional_func, const base::TimeDelta& timeout) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->IsConnected()) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "not connected to DevTools"); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks deadline = base::TimeTicks::Now() + timeout; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::TimeTicks::Now() >= deadline) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kTimeout, base::StringPrintf( 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "exceeded %dms", static_cast<int>(timeout.InMilliseconds()))); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->HasNextMessage()) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_condition_met; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = conditional_func.Run(&is_condition_met); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_condition_met) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To keep this simple, we don't pass the delta time to 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProcessNextMessage. As a result, we may not immediately 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return after |timeout|ms. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = ProcessNextMessage(-1); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError() && status.code() != kTimeout) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsClientImpl::ResponseInfo::ResponseInfo(const std::string& method) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : state(kWaiting), method(method) {} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsClientImpl::ResponseInfo::~ResponseInfo() {} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::SendCommandInternal( 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& method, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue& params, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue>* result) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->IsConnected()) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "not connected to DevTools"); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int command_id = next_id_++; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue command; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command.SetInteger("id", command_id); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command.SetString("method", method); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command.Set("params", params.DeepCopy()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSONWriter::Write(&command, &message); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_->AddEntry(Log::kDebug, "sending Inspector command " + message); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->Send(message)) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "unable to send message to renderer"); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<ResponseInfo> response_info = 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ResponseInfo(method)); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info_map_[command_id] = response_info; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (response_info->state == kWaiting) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = ProcessNextMessage(command_id); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_info->state == kReceived) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info_map_.erase(command_id); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_info->state == kBlocked) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info->state = kIgnored; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnexpectedAlertOpen); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(response_info->state, kReceived); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal::InspectorCommandResponse& response = response_info->response; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response.result) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ParseInspectorError(response.error); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = response.result.Pass(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::ProcessNextMessage(int expected_id) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedIncrementer increment_stack_count(&stack_count_); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = EnsureListenersNotifiedOfConnect(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = EnsureListenersNotifiedOfEvent(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = EnsureListenersNotifiedOfCommandResponse(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The command response may have already been received or blocked while 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifying listeners. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected_id != -1 && response_info_map_[expected_id]->state != kWaiting) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (socket_->ReceiveNextMessage(&message, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(1))) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SyncWebSocket::kOk: 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_->AddEntry(Log::kDebug, "received Inspector response " + message); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SyncWebSocket::kDisconnected: 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message = "unable to receive message from renderer"; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_->AddEntry(Log::kDebug, message); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, message); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SyncWebSocket::kTimeout: 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message = "timed out receiving message from renderer"; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_->AddEntry(Log::kDebug, message); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kTimeout, message); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal::InspectorMessageType type; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal::InspectorEvent event; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal::InspectorCommandResponse response; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parser_func_.Run(message, expected_id, &type, &event, &response)) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "bad inspector message: " + message); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == internal::kEventMessageType) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessEvent(event); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(type, internal::kCommandResponseMessageType); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessCommandResponse(response); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::ProcessEvent(const internal::InspectorEvent& event) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_listeners_ = listeners_; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_ = &event; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = EnsureListenersNotifiedOfEvent(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_ = NULL; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.method == "Inspector.detached") 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "received Inspector.detached event"); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.method == "Inspector.targetCrashed") 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kDisconnected, "page crashed"); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.method == "Page.javascriptDialogOpening") { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A command may have opened the dialog, which will block the response. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To find out which one (if any), do a round trip with a simple command 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the renderer and afterwards see if any of the commands still haven't 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // received a response. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This relies on the fact that DevTools commands are processed 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sequentially. This may break if any of the commands are asynchronous. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If for some reason the round trip command fails, mark all the waiting 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // commands as blocked and return the error. This is better than risking 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a hang. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_id = next_id_; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue enable_params; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_params.SetString("purpose", "detect if alert blocked any cmds"); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status enable_status = SendCommand("Inspector.enable", enable_params); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ResponseInfoMap::const_iterator iter = response_info_map_.begin(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != response_info_map_.end(); ++iter) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->first > max_id) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second->state == kWaiting) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->state = kBlocked; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enable_status.IsError()) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::ProcessCommandResponse( 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const internal::InspectorCommandResponse& response) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_info_map_.count(response.id) == 0) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "unexpected command response"); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<ResponseInfo> response_info = response_info_map_[response.id]; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_info->state == kReceived) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kUnknownError, "received multiple command responses"); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_info->state == kIgnored) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info_map_.erase(response.id); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info->state = kReceived; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info->response.id = response.id; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info->response.error = response.error; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response.result) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info->response.result.reset(response.result->DeepCopy()); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response.result) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_cmd_response_listeners_ = listeners_; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_cmd_response_info_ = response_info; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = EnsureListenersNotifiedOfCommandResponse(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_cmd_response_info_.reset(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::EnsureListenersNotifiedOfConnect() { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unnotified_connect_listeners_.size()) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DevToolsEventListener* listener = unnotified_connect_listeners_.front(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_connect_listeners_.pop_front(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = listener->OnConnected(this); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::EnsureListenersNotifiedOfEvent() { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unnotified_event_listeners_.size()) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DevToolsEventListener* listener = unnotified_event_listeners_.front(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_event_listeners_.pop_front(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = listener->OnEvent( 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, unnotified_event_->method, *unnotified_event_->params); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status DevToolsClientImpl::EnsureListenersNotifiedOfCommandResponse() { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unnotified_cmd_response_listeners_.size()) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DevToolsEventListener* listener = 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_cmd_response_listeners_.front(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unnotified_cmd_response_listeners_.pop_front(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status status = 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener->OnCommandSuccess(this, unnotified_cmd_response_info_->method); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsError()) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status(kOk); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseInspectorMessage( 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& message, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int expected_id, 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InspectorMessageType* type, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InspectorEvent* event, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InspectorCommandResponse* command_response) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> message_value(base::JSONReader::Read(message)); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* message_dict; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message_value || !message_value->GetAsDictionary(&message_dict)) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message_dict->HasKey("id")) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string method; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message_dict->GetString("method", &method)) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* params = NULL; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_dict->GetDictionary("params", ¶ms); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kEventMessageType; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->method = method; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->params.reset(params->DeepCopy()); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->params.reset(new base::DictionaryValue()); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (message_dict->GetInteger("id", &id)) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* unscoped_error = NULL; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* unscoped_result = NULL; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message_dict->GetDictionary("error", &unscoped_error) && 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !message_dict->GetDictionary("result", &unscoped_result)) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kCommandResponseMessageType; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_response->id = id; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unscoped_result) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_response->result.reset(unscoped_result->DeepCopy()); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSONWriter::Write(unscoped_error, &command_response->error); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internal 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)