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 "content/browser/devtools/devtools_browser_target.h" | 5 #include "content/browser/devtools/devtools_browser_target.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/location.h" | 10 #include "base/location.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/message_loop_proxy.h" | 13 #include "base/message_loop_proxy.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "net/server/http_server.h" | 15 #include "net/server/http_server.h" |
16 | 16 |
17 namespace content { | |
18 | |
19 namespace { | 17 namespace { |
20 | 18 |
21 class NotifierImpl : public DevToolsBrowserTarget::Notifier { | 19 base::Value* CreateErrorObject(int error_code, const std::string& message) { |
22 public: | 20 base::DictionaryValue* error_object = new base::DictionaryValue(); |
23 NotifierImpl( | 21 error_object->SetInteger("code", error_code); |
24 base::MessageLoopProxy* message_loop_proxy, | 22 error_object->SetString("message", message); |
25 net::HttpServer* http_server, | 23 return error_object; |
26 int connection_id) | 24 } |
27 : message_loop_proxy_(message_loop_proxy), | |
28 server_(http_server), | |
29 connection_id_(connection_id) { | |
30 } | |
31 | |
32 virtual ~NotifierImpl() {} | |
33 | |
34 // DevToolsBrowserTarget::Notifier | |
35 virtual void Notify(const std::string& data) OVERRIDE { | |
36 message_loop_proxy_->PostTask( | |
37 FROM_HERE, | |
38 base::Bind(&net::HttpServer::SendOverWebSocket, | |
39 server_, | |
40 connection_id_, | |
41 data)); | |
42 } | |
43 | |
44 private: | |
45 base::MessageLoopProxy* const message_loop_proxy_; | |
46 net::HttpServer* const server_; | |
47 const int connection_id_; | |
48 | |
49 DISALLOW_COPY_AND_ASSIGN(NotifierImpl); | |
50 }; | |
51 | 25 |
52 } // namespace | 26 } // namespace |
53 | 27 |
54 DevToolsBrowserTarget::Handler::Handler() | 28 namespace content { |
55 : notifier_(NULL) { | 29 |
| 30 DevToolsBrowserTarget::DomainHandler::~DomainHandler() { |
56 } | 31 } |
57 | 32 |
58 DevToolsBrowserTarget::Handler::~Handler() { | 33 void DevToolsBrowserTarget::DomainHandler::RegisterCommandHandler( |
| 34 const std::string& command, |
| 35 CommandHandler handler) { |
| 36 command_handlers_[command] = handler; |
59 } | 37 } |
60 | 38 |
61 void DevToolsBrowserTarget::Handler::set_notifier( | 39 DevToolsBrowserTarget::DomainHandler::DomainHandler(const std::string& domain) |
62 DevToolsBrowserTarget::Notifier* notifier) { | 40 : domain_(domain) { |
63 notifier_ = notifier; | |
64 } | 41 } |
65 | 42 |
66 DevToolsBrowserTarget::Notifier* DevToolsBrowserTarget::Handler::notifier() | 43 base::DictionaryValue* DevToolsBrowserTarget::DomainHandler::HandleCommand( |
67 const { | 44 const std::string& command, |
68 return notifier_; | 45 const base::DictionaryValue* params, |
| 46 base::Value** error_out) { |
| 47 CommandHandlers::iterator it = command_handlers_.find(command); |
| 48 if (it == command_handlers_.end()) { |
| 49 *error_out = CreateErrorObject(-1, "Invalid method"); |
| 50 return NULL; |
| 51 } |
| 52 return (it->second).Run(params, error_out); |
| 53 } |
| 54 |
| 55 void DevToolsBrowserTarget::DomainHandler::SendNotification( |
| 56 const std::string& method, |
| 57 base::DictionaryValue* params, |
| 58 base::Value* error) { |
| 59 notifier_.Run(method, params, error); |
69 } | 60 } |
70 | 61 |
71 DevToolsBrowserTarget::DevToolsBrowserTarget( | 62 DevToolsBrowserTarget::DevToolsBrowserTarget( |
72 base::MessageLoopProxy* message_loop_proxy, | 63 base::MessageLoopProxy* message_loop_proxy, |
73 net::HttpServer* http_server, | 64 net::HttpServer* http_server, |
74 int connection_id) | 65 int connection_id) |
75 : notifier_( | 66 : message_loop_proxy_(message_loop_proxy), |
76 new NotifierImpl(message_loop_proxy, http_server, connection_id)), | 67 http_server_(http_server), |
77 connection_id_(connection_id) { | 68 connection_id_(connection_id), |
| 69 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
78 } | 70 } |
79 | 71 |
80 DevToolsBrowserTarget::~DevToolsBrowserTarget() { | 72 DevToolsBrowserTarget::~DevToolsBrowserTarget() { |
81 for (HandlersMap::iterator i = handlers_.begin(); i != handlers_.end(); ++i) | 73 for (DomainHandlerMap::iterator i = handlers_.begin(); i != handlers_.end(); |
| 74 ++i) |
82 delete i->second; | 75 delete i->second; |
83 } | 76 } |
84 | 77 |
85 void DevToolsBrowserTarget::RegisterHandler(Handler* handler) { | 78 void DevToolsBrowserTarget::RegisterDomainHandler(DomainHandler* handler) { |
86 std::string domain = handler->Domain(); | 79 std::string domain = handler->domain(); |
87 DCHECK(handlers_.find(domain) == handlers_.end()); | 80 DCHECK(handlers_.find(domain) == handlers_.end()); |
88 handlers_[domain] = handler; | 81 handlers_[domain] = handler; |
89 handler->set_notifier(notifier_.get()); | 82 handler->set_notifier(Bind(&DevToolsBrowserTarget::SendNotification, |
| 83 weak_factory_.GetWeakPtr())); |
90 } | 84 } |
91 | 85 |
92 std::string DevToolsBrowserTarget::HandleMessage(const std::string& data) { | 86 std::string DevToolsBrowserTarget::HandleMessage(const std::string& data) { |
93 int error_code; | 87 int error_code; |
94 std::string error_message; | 88 std::string error_message; |
95 scoped_ptr<base::Value> command( | 89 scoped_ptr<base::Value> command( |
96 base::JSONReader::ReadAndReturnError( | 90 base::JSONReader::ReadAndReturnError( |
97 data, 0, &error_code, &error_message)); | 91 data, 0, &error_code, &error_message)); |
98 | 92 |
99 if (!command || !command->IsType(base::Value::TYPE_DICTIONARY)) | 93 if (!command || !command->IsType(base::Value::TYPE_DICTIONARY)) |
(...skipping 19 matching lines...) Expand all Loading... |
119 if (pos == std::string::npos) | 113 if (pos == std::string::npos) |
120 return SerializeErrorResponse( | 114 return SerializeErrorResponse( |
121 request_id, CreateErrorObject(-1, "Method unsupported")); | 115 request_id, CreateErrorObject(-1, "Method unsupported")); |
122 | 116 |
123 domain = method.substr(0, pos); | 117 domain = method.substr(0, pos); |
124 if (domain.empty() || handlers_.find(domain) == handlers_.end()) | 118 if (domain.empty() || handlers_.find(domain) == handlers_.end()) |
125 return SerializeErrorResponse( | 119 return SerializeErrorResponse( |
126 request_id, CreateErrorObject(-1, "Domain unsupported")); | 120 request_id, CreateErrorObject(-1, "Domain unsupported")); |
127 | 121 |
128 base::Value* error_object = NULL; | 122 base::Value* error_object = NULL; |
129 base::Value* domain_result = handlers_[domain]->OnProtocolCommand( | 123 base::DictionaryValue* domain_result = handlers_[domain]->HandleCommand( |
130 method, params, &error_object); | 124 method, params, &error_object); |
131 | 125 |
132 if (error_object) | 126 if (error_object) |
133 return SerializeErrorResponse(request_id, error_object); | 127 return SerializeErrorResponse(request_id, error_object); |
134 | 128 |
135 if (!domain_result) | 129 return SerializeResponse(request_id, domain_result); |
136 return SerializeErrorResponse( | 130 } |
137 request_id, CreateErrorObject(-1, "Invalid call")); | |
138 | 131 |
139 DictionaryValue* response = new DictionaryValue(); | 132 void DevToolsBrowserTarget::SendNotification(const std::string& method, |
140 response->Set("result", domain_result); | 133 DictionaryValue* params, |
141 return SerializeResponse(request_id, response); | 134 Value* error) { |
| 135 scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue()); |
| 136 response->SetString("method", method); |
| 137 if (error) |
| 138 response->Set("error", error); |
| 139 else if (params) |
| 140 response->Set("params", params); |
| 141 |
| 142 // Serialize response. |
| 143 std::string json_response; |
| 144 base::JSONWriter::Write(response.get(), &json_response); |
| 145 |
| 146 message_loop_proxy_->PostTask( |
| 147 FROM_HERE, |
| 148 base::Bind(&net::HttpServer::SendOverWebSocket, |
| 149 http_server_, |
| 150 connection_id_, |
| 151 json_response)); |
142 } | 152 } |
143 | 153 |
144 std::string DevToolsBrowserTarget::SerializeErrorResponse( | 154 std::string DevToolsBrowserTarget::SerializeErrorResponse( |
145 int request_id, base::Value* error_object) { | 155 int request_id, base::Value* error_object) { |
146 scoped_ptr<base::DictionaryValue> error_response(new base::DictionaryValue()); | 156 scoped_ptr<base::DictionaryValue> error_response(new base::DictionaryValue()); |
147 error_response->SetInteger("id", request_id); | 157 error_response->SetInteger("id", request_id); |
148 error_response->Set("error", error_object); | 158 error_response->Set("error", error_object); |
149 // Serialize response. | 159 // Serialize response. |
150 std::string json_response; | 160 std::string json_response; |
151 base::JSONWriter::Write(error_response.get(), &json_response); | 161 base::JSONWriter::Write(error_response.get(), &json_response); |
152 return json_response; | 162 return json_response; |
153 } | 163 } |
154 | 164 |
155 base::Value* DevToolsBrowserTarget::CreateErrorObject( | |
156 int error_code, const std::string& message) { | |
157 base::DictionaryValue* error_object = new base::DictionaryValue(); | |
158 error_object->SetInteger("code", error_code); | |
159 error_object->SetString("message", message); | |
160 return error_object; | |
161 } | |
162 | |
163 std::string DevToolsBrowserTarget::SerializeResponse( | 165 std::string DevToolsBrowserTarget::SerializeResponse( |
164 int request_id, base::Value* response) { | 166 int request_id, base::DictionaryValue* result) { |
165 scoped_ptr<base::DictionaryValue> ret(new base::DictionaryValue()); | 167 scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue()); |
166 ret->SetInteger("id", request_id); | 168 response->SetInteger("id", request_id); |
167 ret->Set("response", response); | 169 if (result) |
| 170 response->Set("result", result); |
168 | 171 |
169 // Serialize response. | 172 // Serialize response. |
170 std::string json_response; | 173 std::string json_response; |
171 base::JSONWriter::Write(ret.get(), &json_response); | 174 base::JSONWriter::Write(response.get(), &json_response); |
172 return json_response; | 175 return json_response; |
173 } | 176 } |
174 | 177 |
175 } // namespace content | 178 } // namespace content |
OLD | NEW |