Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / content / renderer / devtools / devtools_agent.cc
blob0777af1c66a6cc1e82d1fb045aa02dd059e3c42e
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
3 // found in the LICENSE file.
5 #include "content/renderer/devtools/devtools_agent.h"
7 #include <map>
9 #include "base/lazy_instance.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/trace_event/trace_event.h"
13 #include "content/common/devtools_messages.h"
14 #include "content/common/frame_messages.h"
15 #include "content/renderer/devtools/devtools_client.h"
16 #include "content/renderer/render_frame_impl.h"
17 #include "content/renderer/render_widget.h"
18 #include "ipc/ipc_channel.h"
19 #include "third_party/WebKit/public/platform/WebPoint.h"
20 #include "third_party/WebKit/public/platform/WebString.h"
21 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
22 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
23 #include "third_party/WebKit/public/web/WebLocalFrame.h"
25 #if defined(USE_TCMALLOC)
26 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
27 #endif
29 using blink::WebConsoleMessage;
30 using blink::WebDevToolsAgent;
31 using blink::WebDevToolsAgentClient;
32 using blink::WebLocalFrame;
33 using blink::WebPoint;
34 using blink::WebString;
36 using base::trace_event::TraceLog;
38 namespace content {
40 namespace {
42 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
44 class WebKitClientMessageLoopImpl
45 : public WebDevToolsAgentClient::WebKitClientMessageLoop {
46 public:
47 WebKitClientMessageLoopImpl() : message_loop_(base::MessageLoop::current()) {}
48 virtual ~WebKitClientMessageLoopImpl() { message_loop_ = NULL; }
49 virtual void run() {
50 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_);
51 message_loop_->Run();
53 virtual void quitNow() {
54 message_loop_->QuitNow();
56 private:
57 base::MessageLoop* message_loop_;
60 typedef std::map<int, DevToolsAgent*> IdToAgentMap;
61 base::LazyInstance<IdToAgentMap>::Leaky
62 g_agent_for_routing_id = LAZY_INSTANCE_INITIALIZER;
64 } // namespace
66 DevToolsAgent::DevToolsAgent(RenderFrameImpl* frame)
67 : RenderFrameObserver(frame),
68 is_attached_(false),
69 is_devtools_client_(false),
70 paused_in_mouse_move_(false),
71 paused_(false),
72 frame_(frame) {
73 g_agent_for_routing_id.Get()[routing_id()] = this;
74 frame_->GetWebFrame()->setDevToolsAgentClient(this);
77 DevToolsAgent::~DevToolsAgent() {
78 g_agent_for_routing_id.Get().erase(routing_id());
81 // Called on the Renderer thread.
82 bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) {
83 bool handled = true;
84 IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message)
85 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnAttach)
86 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnReattach)
87 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach)
88 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
89 OnDispatchOnInspectorBackend)
90 IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement)
91 IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient)
92 IPC_MESSAGE_UNHANDLED(handled = false)
93 IPC_END_MESSAGE_MAP()
95 if (message.type() == FrameMsg_Navigate::ID)
96 ContinueProgram(); // Don't want to swallow the message.
98 return handled;
101 void DevToolsAgent::WidgetWillClose() {
102 ContinueProgram();
105 void DevToolsAgent::sendProtocolMessage(
106 int call_id,
107 const blink::WebString& message,
108 const blink::WebString& state_cookie) {
109 SendChunkedProtocolMessage(
110 this, routing_id(), call_id, message.utf8(), state_cookie.utf8());
113 blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
114 DevToolsAgent::createClientMessageLoop() {
115 return new WebKitClientMessageLoopImpl();
118 void DevToolsAgent::willEnterDebugLoop() {
119 paused_ = true;
120 if (RenderWidget* widget = frame_->GetRenderWidget())
121 paused_in_mouse_move_ = widget->SendAckForMouseMoveFromDebugger();
124 void DevToolsAgent::didExitDebugLoop() {
125 paused_ = false;
126 if (!paused_in_mouse_move_)
127 return;
128 if (RenderWidget* widget = frame_->GetRenderWidget()) {
129 widget->IgnoreAckForMouseMoveFromDebugger();
130 paused_in_mouse_move_ = false;
134 void DevToolsAgent::enableTracing(const WebString& category_filter) {
135 TraceLog* trace_log = TraceLog::GetInstance();
136 trace_log->SetEnabled(
137 base::trace_event::TraceConfig(category_filter.utf8(), ""),
138 TraceLog::RECORDING_MODE);
141 void DevToolsAgent::disableTracing() {
142 TraceLog::GetInstance()->SetDisabled();
145 // static
146 DevToolsAgent* DevToolsAgent::FromRoutingId(int routing_id) {
147 IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(routing_id);
148 if (it != g_agent_for_routing_id.Get().end()) {
149 return it->second;
151 return NULL;
154 // static
155 void DevToolsAgent::SendChunkedProtocolMessage(
156 IPC::Sender* sender,
157 int routing_id,
158 int call_id,
159 const std::string& message,
160 const std::string& post_state) {
161 DevToolsMessageChunk chunk;
162 chunk.message_size = message.size();
163 chunk.is_first = true;
165 if (message.length() < kMaxMessageChunkSize) {
166 chunk.data = message;
167 chunk.call_id = call_id;
168 chunk.post_state = post_state;
169 chunk.is_last = true;
170 sender->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
171 routing_id, chunk));
172 return;
175 for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) {
176 chunk.is_last = pos + kMaxMessageChunkSize >= message.length();
177 chunk.call_id = chunk.is_last ? call_id : 0;
178 chunk.post_state = chunk.is_last ? post_state : std::string();
179 chunk.data = message.substr(pos, kMaxMessageChunkSize);
180 sender->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
181 routing_id, chunk));
182 chunk.is_first = false;
183 chunk.message_size = 0;
187 void DevToolsAgent::OnAttach(const std::string& host_id) {
188 WebDevToolsAgent* web_agent = GetWebAgent();
189 if (web_agent) {
190 web_agent->attach(WebString::fromUTF8(host_id));
191 is_attached_ = true;
195 void DevToolsAgent::OnReattach(const std::string& host_id,
196 const std::string& agent_state) {
197 WebDevToolsAgent* web_agent = GetWebAgent();
198 if (web_agent) {
199 web_agent->reattach(WebString::fromUTF8(host_id),
200 WebString::fromUTF8(agent_state));
201 is_attached_ = true;
205 void DevToolsAgent::OnDetach() {
206 WebDevToolsAgent* web_agent = GetWebAgent();
207 if (web_agent) {
208 web_agent->detach();
209 is_attached_ = false;
213 void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) {
214 TRACE_EVENT0("devtools", "DevToolsAgent::OnDispatchOnInspectorBackend");
215 WebDevToolsAgent* web_agent = GetWebAgent();
216 if (web_agent)
217 web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message));
220 void DevToolsAgent::OnInspectElement(
221 const std::string& host_id, int x, int y) {
222 WebDevToolsAgent* web_agent = GetWebAgent();
223 if (web_agent) {
224 web_agent->attach(WebString::fromUTF8(host_id));
225 web_agent->inspectElementAt(WebPoint(x, y));
226 is_attached_ = true;
230 void DevToolsAgent::AddMessageToConsole(ConsoleMessageLevel level,
231 const std::string& message) {
232 WebLocalFrame* web_frame = frame_->GetWebFrame();
233 if (!web_frame)
234 return;
236 WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog;
237 switch (level) {
238 case CONSOLE_MESSAGE_LEVEL_DEBUG:
239 target_level = WebConsoleMessage::LevelDebug;
240 break;
241 case CONSOLE_MESSAGE_LEVEL_LOG:
242 target_level = WebConsoleMessage::LevelLog;
243 break;
244 case CONSOLE_MESSAGE_LEVEL_WARNING:
245 target_level = WebConsoleMessage::LevelWarning;
246 break;
247 case CONSOLE_MESSAGE_LEVEL_ERROR:
248 target_level = WebConsoleMessage::LevelError;
249 break;
251 web_frame->addMessageToConsole(
252 WebConsoleMessage(target_level, WebString::fromUTF8(message)));
255 void DevToolsAgent::ContinueProgram() {
256 WebDevToolsAgent* web_agent = GetWebAgent();
257 if (web_agent)
258 web_agent->continueProgram();
261 void DevToolsAgent::OnSetupDevToolsClient(
262 const std::string& compatibility_script) {
263 // We only want to register once; and only in main frame.
264 DCHECK(!frame_->GetWebFrame() || !frame_->GetWebFrame()->parent());
265 if (is_devtools_client_)
266 return;
267 is_devtools_client_ = true;
268 new DevToolsClient(frame_, compatibility_script);
271 WebDevToolsAgent* DevToolsAgent::GetWebAgent() {
272 WebLocalFrame* web_frame = frame_->GetWebFrame();
273 return web_frame ? web_frame->devToolsAgent() : nullptr;
276 bool DevToolsAgent::IsAttached() {
277 return is_attached_;
280 } // namespace content