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

Side by Side Diff: chrome/browser/debugger/debugger_remote_service.cc

Issue 7274031: Wholesale move of debugger sources to content. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add OWNERS and DEPS. Created 9 years, 5 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
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This file contains implementations of the DebuggerRemoteService methods,
6 // defines DebuggerRemoteService and DebuggerRemoteServiceCommand constants.
7
8 #include "chrome/browser/debugger/debugger_remote_service.h"
9
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/stringprintf.h"
13 #include "base/string_number_conversions.h"
14 #include "base/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/debugger/devtools_manager.h"
17 #include "chrome/browser/debugger/devtools_protocol_handler.h"
18 #include "chrome/browser/debugger/devtools_remote_message.h"
19 #include "chrome/browser/debugger/inspectable_tab_proxy.h"
20 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
21 #include "chrome/common/render_messages.h"
22 #include "content/browser/renderer_host/render_view_host.h"
23 #include "content/browser/tab_contents/tab_contents.h"
24 #include "content/common/devtools_messages.h"
25
26 namespace {
27
28 // Constants for the "data", "result", and "command" JSON message fields.
29 const char kDataKey[] = "data";
30 const char kResultKey[] = "result";
31 const char kCommandKey[] = "command";
32
33 } // namespace
34
35 const std::string DebuggerRemoteServiceCommand::kAttach = "attach";
36 const std::string DebuggerRemoteServiceCommand::kDetach = "detach";
37 const std::string DebuggerRemoteServiceCommand::kDebuggerCommand =
38 "debugger_command";
39 const std::string DebuggerRemoteServiceCommand::kEvaluateJavascript =
40 "evaluate_javascript";
41 const std::string DebuggerRemoteServiceCommand::kFrameNavigate =
42 "navigated";
43 const std::string DebuggerRemoteServiceCommand::kTabClosed =
44 "closed";
45
46 const std::string DebuggerRemoteService::kToolName = "V8Debugger";
47
48 DebuggerRemoteService::DebuggerRemoteService(DevToolsProtocolHandler* delegate)
49 : delegate_(delegate) {}
50
51 DebuggerRemoteService::~DebuggerRemoteService() {}
52
53 // This method handles the V8Debugger tool commands which are
54 // retrieved from the request "command" field. If an operation result
55 // is ready off-hand (synchronously), it is sent back to the remote debugger.
56 // Otherwise the corresponding response is received through IPC from the
57 // V8 debugger via DevToolsClientHost.
58 void DebuggerRemoteService::HandleMessage(
59 const DevToolsRemoteMessage& message) {
60 const std::string destination = message.destination();
61 scoped_ptr<Value> request(base::JSONReader::Read(message.content(), true));
62 if (request.get() == NULL) {
63 // Bad JSON
64 NOTREACHED();
65 return;
66 }
67 DictionaryValue* content;
68 if (!request->IsType(Value::TYPE_DICTIONARY)) {
69 NOTREACHED(); // Broken protocol :(
70 return;
71 }
72 content = static_cast<DictionaryValue*>(request.get());
73 if (!content->HasKey(kCommandKey)) {
74 NOTREACHED(); // Broken protocol :(
75 return;
76 }
77 std::string command;
78 DictionaryValue response;
79
80 content->GetString(kCommandKey, &command);
81 response.SetString(kCommandKey, command);
82 bool send_response = true;
83 if (destination.empty()) {
84 // Unknown command (bad format?)
85 NOTREACHED();
86 response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND);
87 SendResponse(response, message.tool(), message.destination());
88 return;
89 }
90 int32 tab_uid = -1;
91 base::StringToInt(destination, &tab_uid);
92
93 if (command == DebuggerRemoteServiceCommand::kAttach) {
94 // TODO(apavlov): handle 0 for a new tab
95 response.SetString(kCommandKey, DebuggerRemoteServiceCommand::kAttach);
96 AttachToTab(destination, &response);
97 } else if (command == DebuggerRemoteServiceCommand::kDetach) {
98 response.SetString(kCommandKey, DebuggerRemoteServiceCommand::kDetach);
99 DetachFromTab(destination, &response);
100 } else if (command == DebuggerRemoteServiceCommand::kDebuggerCommand) {
101 send_response = DispatchDebuggerCommand(tab_uid, content, &response);
102 } else if (command == DebuggerRemoteServiceCommand::kEvaluateJavascript) {
103 send_response = DispatchEvaluateJavascript(tab_uid, content, &response);
104 } else {
105 // Unknown command
106 NOTREACHED();
107 response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND);
108 }
109
110 if (send_response) {
111 SendResponse(response, message.tool(), message.destination());
112 }
113 }
114
115 void DebuggerRemoteService::OnConnectionLost() {
116 delegate_->inspectable_tab_proxy()->OnRemoteDebuggerDetached();
117 }
118
119 // Sends a JSON response to the remote debugger using |response| as content,
120 // |tool| and |destination| as the respective header values.
121 void DebuggerRemoteService::SendResponse(const Value& response,
122 const std::string& tool,
123 const std::string& destination) {
124 std::string response_content;
125 base::JSONWriter::Write(&response, false, &response_content);
126 scoped_ptr<DevToolsRemoteMessage> response_message(
127 DevToolsRemoteMessageBuilder::instance().Create(tool,
128 destination,
129 response_content));
130 delegate_->Send(*response_message.get());
131 }
132
133 // Gets a TabContents instance corresponding to the |tab_uid| using the
134 // InspectableTabProxy controllers map, or NULL if none found.
135 TabContents* DebuggerRemoteService::ToTabContents(int32 tab_uid) {
136 const InspectableTabProxy::TabMap& tab_map =
137 delegate_->inspectable_tab_proxy()->tab_map();
138 InspectableTabProxy::TabMap::const_iterator it = tab_map.find(tab_uid);
139 if (it != tab_map.end()) {
140 TabContents* tab_contents = it->second->tab_contents();
141 if (tab_contents == NULL) {
142 return NULL;
143 } else {
144 return tab_contents;
145 }
146 } else {
147 return NULL;
148 }
149 }
150
151 // Gets invoked from a DevToolsClientHost callback whenever
152 // a message from the V8 VM debugger corresponding to |tab_id| is received.
153 // Composes a Chrome Developer Tools Protocol JSON response and sends it
154 // to the remote debugger.
155 void DebuggerRemoteService::DebuggerOutput(int32 tab_uid,
156 const std::string& message) {
157 std::string content = StringPrintf(
158 "{\"command\":\"%s\",\"result\":%s,\"data\":%s}",
159 DebuggerRemoteServiceCommand::kDebuggerCommand.c_str(),
160 base::IntToString(RESULT_OK).c_str(),
161 message.c_str());
162 scoped_ptr<DevToolsRemoteMessage> response_message(
163 DevToolsRemoteMessageBuilder::instance().Create(
164 kToolName,
165 base::IntToString(tab_uid),
166 content));
167 delegate_->Send(*(response_message.get()));
168 }
169
170 // Gets invoked from a DevToolsClientHost callback whenever
171 // a tab corresponding to |tab_id| changes its URL. |url| is the new
172 // URL of the tab (may be the same as the previous one if the tab is reloaded).
173 // Sends the corresponding message to the remote debugger.
174 void DebuggerRemoteService::FrameNavigate(int32 tab_uid,
175 const std::string& url) {
176 DictionaryValue value;
177 value.SetString(kCommandKey, DebuggerRemoteServiceCommand::kFrameNavigate);
178 value.SetInteger(kResultKey, RESULT_OK);
179 value.SetString(kDataKey, url);
180 SendResponse(value, kToolName, base::IntToString(tab_uid));
181 }
182
183 // Gets invoked from a DevToolsClientHost callback whenever
184 // a tab corresponding to |tab_id| gets closed.
185 // Sends the corresponding message to the remote debugger.
186 void DebuggerRemoteService::TabClosed(int32 tab_id) {
187 DictionaryValue value;
188 value.SetString(kCommandKey, DebuggerRemoteServiceCommand::kTabClosed);
189 value.SetInteger(kResultKey, RESULT_OK);
190 SendResponse(value, kToolName, base::IntToString(tab_id));
191 }
192
193 // Attaches a remote debugger to the target tab specified by |destination|
194 // by posting the DevToolsAgentMsg_Attach message and sends a response
195 // to the remote debugger immediately.
196 void DebuggerRemoteService::AttachToTab(const std::string& destination,
197 DictionaryValue* response) {
198 int32 tab_uid = -1;
199 base::StringToInt(destination, &tab_uid);
200 if (tab_uid < 0) {
201 // Bad tab_uid received from remote debugger (perhaps NaN)
202 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
203 return;
204 }
205 if (tab_uid == 0) { // single tab_uid
206 // We've been asked to open a new tab with URL
207 // TODO(apavlov): implement
208 NOTIMPLEMENTED();
209 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
210 return;
211 }
212 TabContents* tab_contents = ToTabContents(tab_uid);
213 if (tab_contents == NULL) {
214 // No active tab contents with tab_uid
215 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
216 return;
217 }
218 RenderViewHost* target_host = tab_contents->render_view_host();
219 DevToolsClientHost* client_host =
220 delegate_->inspectable_tab_proxy()->ClientHostForTabId(tab_uid);
221 if (client_host == NULL) {
222 client_host =
223 delegate_->inspectable_tab_proxy()->NewClientHost(tab_uid, this);
224 DevToolsManager* manager = DevToolsManager::GetInstance();
225 if (manager != NULL) {
226 manager->RegisterDevToolsClientHostFor(target_host, client_host);
227 response->SetInteger(kResultKey, RESULT_OK);
228 } else {
229 response->SetInteger(kResultKey, RESULT_DEBUGGER_ERROR);
230 }
231 } else {
232 // DevToolsClientHost for this tab is already registered
233 response->SetInteger(kResultKey, RESULT_ILLEGAL_TAB_STATE);
234 }
235 }
236
237 // Detaches a remote debugger from the target tab specified by |destination|
238 // by posting the DevToolsAgentMsg_Detach message and sends a response
239 // to the remote debugger immediately.
240 void DebuggerRemoteService::DetachFromTab(const std::string& destination,
241 DictionaryValue* response) {
242 int32 tab_uid = -1;
243 base::StringToInt(destination, &tab_uid);
244 if (tab_uid == -1) {
245 // Bad tab_uid received from remote debugger (NaN)
246 if (response != NULL) {
247 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
248 }
249 return;
250 }
251 int result_code;
252 DevToolsClientHostImpl* client_host =
253 delegate_->inspectable_tab_proxy()->ClientHostForTabId(tab_uid);
254 if (client_host != NULL) {
255 client_host->Close();
256 result_code = RESULT_OK;
257 } else {
258 // No client host registered for |tab_uid|.
259 result_code = RESULT_UNKNOWN_TAB;
260 }
261 if (response != NULL) {
262 response->SetInteger(kResultKey, result_code);
263 }
264 }
265
266 // Sends a V8 debugger command to the target tab V8 debugger.
267 // Does not send back a response (which is received asynchronously
268 // through IPC) unless an error occurs before the command has actually
269 // been sent.
270 bool DebuggerRemoteService::DispatchDebuggerCommand(int tab_uid,
271 DictionaryValue* content,
272 DictionaryValue* response) {
273 if (tab_uid == -1) {
274 // Invalid tab_uid from remote debugger (perhaps NaN)
275 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
276 return true;
277 }
278 DevToolsManager* manager = DevToolsManager::GetInstance();
279 if (manager == NULL) {
280 response->SetInteger(kResultKey, RESULT_DEBUGGER_ERROR);
281 return true;
282 }
283 TabContents* tab_contents = ToTabContents(tab_uid);
284 if (tab_contents == NULL) {
285 // Unknown tab_uid from remote debugger
286 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
287 return true;
288 }
289 DevToolsClientHost* client_host =
290 manager->GetDevToolsClientHostFor(tab_contents->render_view_host());
291 if (client_host == NULL) {
292 // tab_uid is not being debugged (Attach has not been invoked)
293 response->SetInteger(kResultKey, RESULT_ILLEGAL_TAB_STATE);
294 return true;
295 }
296 std::string v8_command;
297 DictionaryValue* v8_command_value;
298 content->GetDictionary(kDataKey, &v8_command_value);
299 base::JSONWriter::Write(v8_command_value, false, &v8_command);
300 manager->ForwardToDevToolsAgent(
301 client_host, DevToolsAgentMsg_DebuggerCommand(v8_command));
302 // Do not send the response right now, as the JSON will be received from
303 // the V8 debugger asynchronously.
304 return false;
305 }
306
307 // Sends the immediate "evaluate Javascript" command to the V8 debugger.
308 // The evaluation result is not sent back to the client as this command
309 // is in fact needed to invoke processing of queued debugger commands.
310 bool DebuggerRemoteService::DispatchEvaluateJavascript(
311 int tab_uid,
312 DictionaryValue* content,
313 DictionaryValue* response) {
314 if (tab_uid == -1) {
315 // Invalid tab_uid from remote debugger (perhaps NaN)
316 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
317 return true;
318 }
319 TabContents* tab_contents = ToTabContents(tab_uid);
320 if (tab_contents == NULL) {
321 // Unknown tab_uid from remote debugger
322 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
323 return true;
324 }
325 RenderViewHost* render_view_host = tab_contents->render_view_host();
326 if (render_view_host == NULL) {
327 // No RenderViewHost
328 response->SetInteger(kResultKey, RESULT_UNKNOWN_TAB);
329 return true;
330 }
331 std::string javascript;
332 content->GetString(kDataKey, &javascript);
333 render_view_host->ExecuteJavascriptInWebFrame(string16(),
334 UTF8ToUTF16(javascript));
335 return false;
336 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698