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/renderer/devtools/devtools_agent.h" | 5 #include "content/renderer/devtools/devtools_agent.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/process/process_handle.h" | |
12 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
13 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
14 #include "content/common/devtools_messages.h" | 13 #include "content/common/devtools_messages.h" |
15 #include "content/common/frame_messages.h" | 14 #include "content/common/frame_messages.h" |
16 #include "content/common/view_messages.h" | 15 #include "content/common/view_messages.h" |
17 #include "content/renderer/devtools/devtools_agent_filter.h" | |
18 #include "content/renderer/devtools/devtools_client.h" | 16 #include "content/renderer/devtools/devtools_client.h" |
19 #include "content/renderer/render_view_impl.h" | 17 #include "content/renderer/render_frame_impl.h" |
| 18 #include "content/renderer/render_widget.h" |
20 #include "ipc/ipc_channel.h" | 19 #include "ipc/ipc_channel.h" |
21 #include "third_party/WebKit/public/platform/WebPoint.h" | 20 #include "third_party/WebKit/public/platform/WebPoint.h" |
22 #include "third_party/WebKit/public/platform/WebString.h" | 21 #include "third_party/WebKit/public/platform/WebString.h" |
23 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | 22 #include "third_party/WebKit/public/web/WebConsoleMessage.h" |
24 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | |
25 #include "third_party/WebKit/public/web/WebDevToolsAgent.h" | 23 #include "third_party/WebKit/public/web/WebDevToolsAgent.h" |
26 #include "third_party/WebKit/public/web/WebDeviceEmulationParams.h" | 24 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
27 #include "third_party/WebKit/public/web/WebFrame.h" | |
28 #include "third_party/WebKit/public/web/WebSettings.h" | |
29 #include "third_party/WebKit/public/web/WebView.h" | |
30 | 25 |
31 #if defined(USE_TCMALLOC) | 26 #if defined(USE_TCMALLOC) |
32 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" | 27 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" |
33 #endif | 28 #endif |
34 | 29 |
35 using blink::WebConsoleMessage; | 30 using blink::WebConsoleMessage; |
36 using blink::WebDevToolsAgent; | 31 using blink::WebDevToolsAgent; |
37 using blink::WebDevToolsAgentClient; | 32 using blink::WebDevToolsAgentClient; |
38 using blink::WebFrame; | 33 using blink::WebLocalFrame; |
39 using blink::WebPoint; | 34 using blink::WebPoint; |
40 using blink::WebString; | 35 using blink::WebString; |
41 using blink::WebCString; | |
42 using blink::WebVector; | |
43 using blink::WebView; | |
44 | 36 |
45 using base::trace_event::TraceLog; | 37 using base::trace_event::TraceLog; |
46 using base::trace_event::TraceOptions; | 38 using base::trace_event::TraceOptions; |
47 | 39 |
48 namespace content { | 40 namespace content { |
49 | 41 |
50 base::subtle::AtomicWord DevToolsAgent::event_callback_; | |
51 | |
52 namespace { | 42 namespace { |
53 | 43 |
54 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; | 44 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; |
55 | 45 |
56 class WebKitClientMessageLoopImpl | 46 class WebKitClientMessageLoopImpl |
57 : public WebDevToolsAgentClient::WebKitClientMessageLoop { | 47 : public WebDevToolsAgentClient::WebKitClientMessageLoop { |
58 public: | 48 public: |
59 WebKitClientMessageLoopImpl() : message_loop_(base::MessageLoop::current()) {} | 49 WebKitClientMessageLoopImpl() : message_loop_(base::MessageLoop::current()) {} |
60 virtual ~WebKitClientMessageLoopImpl() { message_loop_ = NULL; } | 50 virtual ~WebKitClientMessageLoopImpl() { message_loop_ = NULL; } |
61 virtual void run() { | 51 virtual void run() { |
62 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_); | 52 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_); |
63 message_loop_->Run(); | 53 message_loop_->Run(); |
64 } | 54 } |
65 virtual void quitNow() { | 55 virtual void quitNow() { |
66 message_loop_->QuitNow(); | 56 message_loop_->QuitNow(); |
67 } | 57 } |
68 private: | 58 private: |
69 base::MessageLoop* message_loop_; | 59 base::MessageLoop* message_loop_; |
70 }; | 60 }; |
71 | 61 |
72 typedef std::map<int, DevToolsAgent*> IdToAgentMap; | 62 typedef std::map<int, DevToolsAgent*> IdToAgentMap; |
73 base::LazyInstance<IdToAgentMap>::Leaky | 63 base::LazyInstance<IdToAgentMap>::Leaky |
74 g_agent_for_routing_id = LAZY_INSTANCE_INITIALIZER; | 64 g_agent_for_routing_id = LAZY_INSTANCE_INITIALIZER; |
75 | 65 |
76 } // namespace | 66 } // namespace |
77 | 67 |
78 DevToolsAgent::DevToolsAgent(RenderFrame* main_render_frame) | 68 DevToolsAgent::DevToolsAgent(RenderFrameImpl* frame) |
79 : RenderFrameObserver(main_render_frame), | 69 : RenderFrameObserver(frame), |
80 is_attached_(false), | 70 is_attached_(false), |
81 is_devtools_client_(false), | 71 is_devtools_client_(false), |
82 paused_in_mouse_move_(false), | 72 paused_in_mouse_move_(false), |
83 main_render_frame_(main_render_frame) { | 73 frame_(frame) { |
84 g_agent_for_routing_id.Get()[routing_id()] = this; | 74 g_agent_for_routing_id.Get()[routing_id()] = this; |
85 | 75 frame_->GetWebFrame()->setDevToolsAgentClient(this); |
86 main_render_frame_->GetRenderView()->GetWebView()->setDevToolsAgentClient( | |
87 this); | |
88 } | 76 } |
89 | 77 |
90 DevToolsAgent::~DevToolsAgent() { | 78 DevToolsAgent::~DevToolsAgent() { |
91 g_agent_for_routing_id.Get().erase(routing_id()); | 79 g_agent_for_routing_id.Get().erase(routing_id()); |
92 resetTraceEventCallback(); | |
93 } | 80 } |
94 | 81 |
95 // Called on the Renderer thread. | 82 // Called on the Renderer thread. |
96 bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { | 83 bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { |
97 bool handled = true; | 84 bool handled = true; |
98 IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message) | 85 IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message) |
99 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnAttach) | 86 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnAttach) |
100 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnReattach) | 87 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnReattach) |
101 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach) | 88 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach) |
102 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, | 89 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend, |
(...skipping 13 matching lines...) Expand all Loading... |
116 } | 103 } |
117 | 104 |
118 void DevToolsAgent::sendProtocolMessage( | 105 void DevToolsAgent::sendProtocolMessage( |
119 int call_id, | 106 int call_id, |
120 const blink::WebString& message, | 107 const blink::WebString& message, |
121 const blink::WebString& state_cookie) { | 108 const blink::WebString& state_cookie) { |
122 SendChunkedProtocolMessage( | 109 SendChunkedProtocolMessage( |
123 this, routing_id(), call_id, message.utf8(), state_cookie.utf8()); | 110 this, routing_id(), call_id, message.utf8(), state_cookie.utf8()); |
124 } | 111 } |
125 | 112 |
126 long DevToolsAgent::processId() { | |
127 return base::GetCurrentProcId(); | |
128 } | |
129 | |
130 int DevToolsAgent::debuggerId() { | |
131 return routing_id(); | |
132 } | |
133 | |
134 blink::WebDevToolsAgentClient::WebKitClientMessageLoop* | 113 blink::WebDevToolsAgentClient::WebKitClientMessageLoop* |
135 DevToolsAgent::createClientMessageLoop() { | 114 DevToolsAgent::createClientMessageLoop() { |
136 return new WebKitClientMessageLoopImpl(); | 115 return new WebKitClientMessageLoopImpl(); |
137 } | 116 } |
138 | 117 |
139 void DevToolsAgent::willEnterDebugLoop() { | 118 void DevToolsAgent::willEnterDebugLoop() { |
140 paused_in_mouse_move_ = | 119 if (RenderWidget* widget = frame_->GetRenderWidget()) |
141 GetRenderViewImpl()->SendAckForMouseMoveFromDebugger(); | 120 paused_in_mouse_move_ = widget->SendAckForMouseMoveFromDebugger(); |
142 } | 121 } |
143 | 122 |
144 void DevToolsAgent::didExitDebugLoop() { | 123 void DevToolsAgent::didExitDebugLoop() { |
145 if (paused_in_mouse_move_) { | 124 if (!paused_in_mouse_move_) |
146 GetRenderViewImpl()->IgnoreAckForMouseMoveFromDebugger(); | 125 return; |
| 126 if (RenderWidget* widget = frame_->GetRenderWidget()) { |
| 127 widget->IgnoreAckForMouseMoveFromDebugger(); |
147 paused_in_mouse_move_ = false; | 128 paused_in_mouse_move_ = false; |
148 } | 129 } |
149 } | 130 } |
150 | 131 |
151 void DevToolsAgent::resetTraceEventCallback() | |
152 { | |
153 TraceLog::GetInstance()->SetEventCallbackDisabled(); | |
154 base::subtle::NoBarrier_Store(&event_callback_, 0); | |
155 } | |
156 | |
157 void DevToolsAgent::setTraceEventCallback(const WebString& category_filter, | |
158 TraceEventCallback cb) { | |
159 TraceLog* trace_log = TraceLog::GetInstance(); | |
160 base::subtle::NoBarrier_Store(&event_callback_, | |
161 reinterpret_cast<base::subtle::AtomicWord>(cb)); | |
162 if (!!cb) { | |
163 trace_log->SetEventCallbackEnabled( | |
164 base::trace_event::CategoryFilter(category_filter.utf8()), | |
165 TraceEventCallbackWrapper); | |
166 } else { | |
167 trace_log->SetEventCallbackDisabled(); | |
168 } | |
169 } | |
170 | |
171 void DevToolsAgent::enableTracing(const WebString& category_filter) { | 132 void DevToolsAgent::enableTracing(const WebString& category_filter) { |
172 TraceLog* trace_log = TraceLog::GetInstance(); | 133 TraceLog* trace_log = TraceLog::GetInstance(); |
173 trace_log->SetEnabled( | 134 trace_log->SetEnabled( |
174 base::trace_event::CategoryFilter(category_filter.utf8()), | 135 base::trace_event::CategoryFilter(category_filter.utf8()), |
175 TraceLog::RECORDING_MODE, TraceOptions()); | 136 TraceLog::RECORDING_MODE, TraceOptions()); |
176 } | 137 } |
177 | 138 |
178 void DevToolsAgent::disableTracing() { | 139 void DevToolsAgent::disableTracing() { |
179 TraceLog::GetInstance()->SetDisabled(); | 140 TraceLog::GetInstance()->SetDisabled(); |
180 } | 141 } |
181 | 142 |
182 // static | 143 // static |
183 void DevToolsAgent::TraceEventCallbackWrapper( | |
184 base::TimeTicks timestamp, | |
185 char phase, | |
186 const unsigned char* category_group_enabled, | |
187 const char* name, | |
188 unsigned long long id, | |
189 int num_args, | |
190 const char* const arg_names[], | |
191 const unsigned char arg_types[], | |
192 const unsigned long long arg_values[], | |
193 unsigned char flags) { | |
194 TraceEventCallback callback = | |
195 reinterpret_cast<TraceEventCallback>( | |
196 base::subtle::NoBarrier_Load(&event_callback_)); | |
197 if (callback) { | |
198 double timestamp_seconds = (timestamp - base::TimeTicks()).InSecondsF(); | |
199 callback(phase, category_group_enabled, name, id, num_args, | |
200 arg_names, arg_types, arg_values, flags, timestamp_seconds); | |
201 } | |
202 } | |
203 | |
204 // static | |
205 DevToolsAgent* DevToolsAgent::FromRoutingId(int routing_id) { | 144 DevToolsAgent* DevToolsAgent::FromRoutingId(int routing_id) { |
206 IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(routing_id); | 145 IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(routing_id); |
207 if (it != g_agent_for_routing_id.Get().end()) { | 146 if (it != g_agent_for_routing_id.Get().end()) { |
208 return it->second; | 147 return it->second; |
209 } | 148 } |
210 return NULL; | 149 return NULL; |
211 } | 150 } |
212 | 151 |
213 // static | 152 // static |
214 void DevToolsAgent::SendChunkedProtocolMessage( | 153 void DevToolsAgent::SendChunkedProtocolMessage( |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 WebDevToolsAgent* web_agent = GetWebAgent(); | 220 WebDevToolsAgent* web_agent = GetWebAgent(); |
282 if (web_agent) { | 221 if (web_agent) { |
283 web_agent->attach(WebString::fromUTF8(host_id)); | 222 web_agent->attach(WebString::fromUTF8(host_id)); |
284 web_agent->inspectElementAt(WebPoint(x, y)); | 223 web_agent->inspectElementAt(WebPoint(x, y)); |
285 is_attached_ = true; | 224 is_attached_ = true; |
286 } | 225 } |
287 } | 226 } |
288 | 227 |
289 void DevToolsAgent::OnAddMessageToConsole(ConsoleMessageLevel level, | 228 void DevToolsAgent::OnAddMessageToConsole(ConsoleMessageLevel level, |
290 const std::string& message) { | 229 const std::string& message) { |
291 WebView* web_view = main_render_frame_->GetRenderView()->GetWebView(); | 230 WebLocalFrame* web_frame = frame_->GetWebFrame(); |
292 if (!web_view) | 231 if (!web_frame) |
293 return; | |
294 | |
295 WebFrame* main_frame = web_view->mainFrame(); | |
296 if (!main_frame) | |
297 return; | 232 return; |
298 | 233 |
299 WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog; | 234 WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog; |
300 switch (level) { | 235 switch (level) { |
301 case CONSOLE_MESSAGE_LEVEL_DEBUG: | 236 case CONSOLE_MESSAGE_LEVEL_DEBUG: |
302 target_level = WebConsoleMessage::LevelDebug; | 237 target_level = WebConsoleMessage::LevelDebug; |
303 break; | 238 break; |
304 case CONSOLE_MESSAGE_LEVEL_LOG: | 239 case CONSOLE_MESSAGE_LEVEL_LOG: |
305 target_level = WebConsoleMessage::LevelLog; | 240 target_level = WebConsoleMessage::LevelLog; |
306 break; | 241 break; |
307 case CONSOLE_MESSAGE_LEVEL_WARNING: | 242 case CONSOLE_MESSAGE_LEVEL_WARNING: |
308 target_level = WebConsoleMessage::LevelWarning; | 243 target_level = WebConsoleMessage::LevelWarning; |
309 break; | 244 break; |
310 case CONSOLE_MESSAGE_LEVEL_ERROR: | 245 case CONSOLE_MESSAGE_LEVEL_ERROR: |
311 target_level = WebConsoleMessage::LevelError; | 246 target_level = WebConsoleMessage::LevelError; |
312 break; | 247 break; |
313 } | 248 } |
314 main_frame->addMessageToConsole( | 249 web_frame->addMessageToConsole( |
315 WebConsoleMessage(target_level, WebString::fromUTF8(message))); | 250 WebConsoleMessage(target_level, WebString::fromUTF8(message))); |
316 } | 251 } |
317 | 252 |
318 void DevToolsAgent::ContinueProgram() { | 253 void DevToolsAgent::ContinueProgram() { |
319 WebDevToolsAgent* web_agent = GetWebAgent(); | 254 WebDevToolsAgent* web_agent = GetWebAgent(); |
320 if (web_agent) | 255 if (web_agent) |
321 web_agent->continueProgram(); | 256 web_agent->continueProgram(); |
322 } | 257 } |
323 | 258 |
324 void DevToolsAgent::OnSetupDevToolsClient() { | 259 void DevToolsAgent::OnSetupDevToolsClient() { |
325 // We only want to register once per render view. | 260 // We only want to register once; and only in main frame. |
| 261 DCHECK(!frame_->GetWebFrame() || !frame_->GetWebFrame()->parent()); |
326 if (is_devtools_client_) | 262 if (is_devtools_client_) |
327 return; | 263 return; |
328 is_devtools_client_ = true; | 264 is_devtools_client_ = true; |
329 new DevToolsClient(main_render_frame_); | 265 new DevToolsClient(frame_); |
330 } | 266 } |
331 | 267 |
332 WebDevToolsAgent* DevToolsAgent::GetWebAgent() { | 268 WebDevToolsAgent* DevToolsAgent::GetWebAgent() { |
333 WebView* web_view = main_render_frame_->GetRenderView()->GetWebView(); | 269 WebLocalFrame* web_frame = frame_->GetWebFrame(); |
334 if (!web_view) | 270 return web_frame ? web_frame->devToolsAgent() : nullptr; |
335 return NULL; | |
336 return web_view->devToolsAgent(); | |
337 } | |
338 | |
339 RenderViewImpl* DevToolsAgent::GetRenderViewImpl() { | |
340 return static_cast<RenderViewImpl*>(main_render_frame_->GetRenderView()); | |
341 } | 271 } |
342 | 272 |
343 bool DevToolsAgent::IsAttached() { | 273 bool DevToolsAgent::IsAttached() { |
344 return is_attached_; | 274 return is_attached_; |
345 } | 275 } |
346 | 276 |
347 } // namespace content | 277 } // namespace content |
OLD | NEW |