Add ICU message format support
[chromium-blink-merge.git] / content / browser / devtools / render_frame_devtools_agent_host.cc
blob0fc8ce9e8dae6bb56ee840d144884adb91a66970
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/browser/devtools/render_frame_devtools_agent_host.h"
7 #include "base/basictypes.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/child_process_security_policy_impl.h"
11 #include "content/browser/devtools/devtools_frame_trace_recorder.h"
12 #include "content/browser/devtools/devtools_protocol_handler.h"
13 #include "content/browser/devtools/protocol/dom_handler.h"
14 #include "content/browser/devtools/protocol/emulation_handler.h"
15 #include "content/browser/devtools/protocol/input_handler.h"
16 #include "content/browser/devtools/protocol/inspector_handler.h"
17 #include "content/browser/devtools/protocol/network_handler.h"
18 #include "content/browser/devtools/protocol/page_handler.h"
19 #include "content/browser/devtools/protocol/power_handler.h"
20 #include "content/browser/devtools/protocol/security_handler.h"
21 #include "content/browser/devtools/protocol/service_worker_handler.h"
22 #include "content/browser/devtools/protocol/tracing_handler.h"
23 #include "content/browser/frame_host/render_frame_host_impl.h"
24 #include "content/browser/renderer_host/render_process_host_impl.h"
25 #include "content/browser/renderer_host/render_view_host_impl.h"
26 #include "content/browser/site_instance_impl.h"
27 #include "content/browser/web_contents/web_contents_impl.h"
28 #include "content/common/view_messages.h"
29 #include "content/public/browser/browser_context.h"
30 #include "content/public/browser/content_browser_client.h"
31 #include "content/public/browser/render_widget_host_iterator.h"
32 #include "content/public/browser/web_contents_delegate.h"
34 #if defined(OS_ANDROID)
35 #include "content/browser/power_save_blocker_impl.h"
36 #include "content/public/browser/render_widget_host_view.h"
37 #endif
39 namespace content {
41 typedef std::vector<RenderFrameDevToolsAgentHost*> Instances;
43 namespace {
44 base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
46 static RenderFrameDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) {
47 if (g_instances == NULL)
48 return NULL;
49 for (Instances::iterator it = g_instances.Get().begin();
50 it != g_instances.Get().end(); ++it) {
51 if ((*it)->HasRenderFrameHost(host))
52 return *it;
54 return NULL;
57 // Returns RenderFrameDevToolsAgentHost attached to any of RenderFrameHost
58 // instances associated with |web_contents|
59 static RenderFrameDevToolsAgentHost* FindAgentHost(WebContents* web_contents) {
60 if (g_instances == NULL)
61 return NULL;
62 for (Instances::iterator it = g_instances.Get().begin();
63 it != g_instances.Get().end(); ++it) {
64 if ((*it)->GetWebContents() == web_contents)
65 return *it;
67 return NULL;
70 bool ShouldCreateDevToolsFor(RenderFrameHost* rfh) {
71 return rfh->IsCrossProcessSubframe() || !rfh->GetParent();
74 } // namespace
76 // RenderFrameDevToolsAgentHost::FrameHostHolder -------------------------------
78 class RenderFrameDevToolsAgentHost::FrameHostHolder {
79 public:
80 FrameHostHolder(
81 RenderFrameDevToolsAgentHost* agent, RenderFrameHostImpl* host);
82 ~FrameHostHolder();
84 RenderFrameHostImpl* host() const { return host_; }
86 void Attach();
87 void Reattach(FrameHostHolder* old);
88 void Detach();
89 void DispatchProtocolMessage(int call_id, const std::string& message);
90 void InspectElement(int x, int y);
91 void ProcessChunkedMessageFromAgent(const DevToolsMessageChunk& chunk);
92 void Suspend();
93 void Resume();
95 private:
96 void GrantPolicy();
97 void RevokePolicy();
98 void SendMessageToClient(const std::string& message);
100 RenderFrameDevToolsAgentHost* agent_;
101 RenderFrameHostImpl* host_;
102 bool attached_;
103 bool suspended_;
104 DevToolsMessageChunkProcessor chunk_processor_;
105 std::vector<std::string> pending_messages_;
106 std::map<int, std::string> sent_messages_;
109 RenderFrameDevToolsAgentHost::FrameHostHolder::FrameHostHolder(
110 RenderFrameDevToolsAgentHost* agent, RenderFrameHostImpl* host)
111 : agent_(agent),
112 host_(host),
113 attached_(false),
114 suspended_(false),
115 chunk_processor_(base::Bind(
116 &RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient,
117 base::Unretained(this))) {
118 DCHECK(agent_);
119 DCHECK(host_);
122 RenderFrameDevToolsAgentHost::FrameHostHolder::~FrameHostHolder() {
123 if (attached_)
124 RevokePolicy();
127 void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach() {
128 host_->Send(new DevToolsAgentMsg_Attach(
129 host_->GetRoutingID(), agent_->GetId()));
130 GrantPolicy();
131 attached_ = true;
134 void RenderFrameDevToolsAgentHost::FrameHostHolder::Reattach(
135 FrameHostHolder* old) {
136 if (old)
137 chunk_processor_.set_state_cookie(old->chunk_processor_.state_cookie());
138 host_->Send(new DevToolsAgentMsg_Reattach(
139 host_->GetRoutingID(), agent_->GetId(), chunk_processor_.state_cookie()));
140 if (old) {
141 for (const auto& pair : old->sent_messages_)
142 DispatchProtocolMessage(pair.first, pair.second);
144 GrantPolicy();
145 attached_ = true;
148 void RenderFrameDevToolsAgentHost::FrameHostHolder::Detach() {
149 host_->Send(new DevToolsAgentMsg_Detach(host_->GetRoutingID()));
150 RevokePolicy();
151 attached_ = false;
154 void RenderFrameDevToolsAgentHost::FrameHostHolder::GrantPolicy() {
155 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies(
156 host_->GetProcess()->GetID());
159 void RenderFrameDevToolsAgentHost::FrameHostHolder::RevokePolicy() {
160 bool process_has_agents = false;
161 RenderProcessHost* process_host = host_->GetProcess();
162 for (RenderFrameDevToolsAgentHost* agent : g_instances.Get()) {
163 if (!agent->IsAttached())
164 continue;
165 if (agent->current_ && agent->current_->host() != host_ &&
166 agent->current_->host()->GetProcess() == process_host) {
167 process_has_agents = true;
169 if (agent->pending_ && agent->pending_->host() != host_ &&
170 agent->pending_->host()->GetProcess() == process_host) {
171 process_has_agents = true;
175 // We are the last to disconnect from the renderer -> revoke permissions.
176 if (!process_has_agents) {
177 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeReadRawCookies(
178 process_host->GetID());
181 void RenderFrameDevToolsAgentHost::FrameHostHolder::DispatchProtocolMessage(
182 int call_id, const std::string& message) {
183 host_->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
184 host_->GetRoutingID(), message));
185 sent_messages_[call_id] = message;
188 void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement(
189 int x, int y) {
190 host_->Send(new DevToolsAgentMsg_InspectElement(
191 host_->GetRoutingID(), agent_->GetId(), x, y));
194 void
195 RenderFrameDevToolsAgentHost::FrameHostHolder::ProcessChunkedMessageFromAgent(
196 const DevToolsMessageChunk& chunk) {
197 chunk_processor_.ProcessChunkedMessageFromAgent(chunk);
200 void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient(
201 const std::string& message) {
202 sent_messages_.erase(chunk_processor_.last_call_id());
203 if (suspended_)
204 pending_messages_.push_back(message);
205 else
206 agent_->SendMessageToClient(message);
209 void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
210 suspended_ = true;
213 void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() {
214 suspended_ = false;
215 for (const std::string& message : pending_messages_)
216 agent_->SendMessageToClient(message);
217 std::vector<std::string> empty;
218 pending_messages_.swap(empty);
221 // RenderFrameDevToolsAgentHost ------------------------------------------------
223 scoped_refptr<DevToolsAgentHost>
224 DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
225 RenderFrameDevToolsAgentHost* result = FindAgentHost(web_contents);
226 if (!result) {
227 // TODO(dgozman): this check should not be necessary. See
228 // http://crbug.com/489664.
229 if (!web_contents->GetMainFrame())
230 return nullptr;
231 result = new RenderFrameDevToolsAgentHost(
232 static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame()));
234 return result;
237 // static
238 scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::GetOrCreateFor(
239 RenderFrameHostImpl* host) {
240 RenderFrameDevToolsAgentHost* result = FindAgentHost(host);
241 if (!result)
242 result = new RenderFrameDevToolsAgentHost(host);
243 return result;
246 // static
247 void RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable(
248 DevToolsAgentHost::List* result,
249 RenderFrameHost* host) {
250 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(host);
251 if (!rfh->IsRenderFrameLive())
252 return;
253 if (ShouldCreateDevToolsFor(rfh))
254 result->push_back(RenderFrameDevToolsAgentHost::GetOrCreateFor(rfh));
257 // static
258 bool DevToolsAgentHost::HasFor(WebContents* web_contents) {
259 return FindAgentHost(web_contents) != NULL;
262 // static
263 bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) {
264 RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(web_contents);
265 return agent_host && agent_host->IsAttached();
268 // static
269 void RenderFrameDevToolsAgentHost::AddAllAgentHosts(
270 DevToolsAgentHost::List* result) {
271 base::Callback<void(RenderFrameHost*)> callback = base::Bind(
272 RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable,
273 base::Unretained(result));
274 for (const auto& wc : WebContentsImpl::GetAllWebContents())
275 wc->ForEachFrame(callback);
278 // static
279 void RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
280 RenderFrameHost* pending,
281 RenderFrameHost* current) {
282 RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(pending);
283 if (!agent_host)
284 return;
285 if (agent_host->pending_ && agent_host->pending_->host() == pending) {
286 DCHECK(agent_host->current_ && agent_host->current_->host() == current);
287 agent_host->DiscardPending();
291 RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
292 RenderFrameHostImpl* host)
293 : dom_handler_(new devtools::dom::DOMHandler()),
294 input_handler_(new devtools::input::InputHandler()),
295 inspector_handler_(new devtools::inspector::InspectorHandler()),
296 network_handler_(new devtools::network::NetworkHandler()),
297 page_handler_(nullptr),
298 power_handler_(new devtools::power::PowerHandler()),
299 security_handler_(nullptr),
300 service_worker_handler_(
301 new devtools::service_worker::ServiceWorkerHandler()),
302 tracing_handler_(new devtools::tracing::TracingHandler(
303 devtools::tracing::TracingHandler::Renderer)),
304 emulation_handler_(nullptr),
305 frame_trace_recorder_(nullptr),
306 protocol_handler_(new DevToolsProtocolHandler(
307 this,
308 base::Bind(&RenderFrameDevToolsAgentHost::SendMessageToClient,
309 base::Unretained(this)))),
310 current_frame_crashed_(false) {
311 DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
312 dispatcher->SetDOMHandler(dom_handler_.get());
313 dispatcher->SetInputHandler(input_handler_.get());
314 dispatcher->SetInspectorHandler(inspector_handler_.get());
315 dispatcher->SetNetworkHandler(network_handler_.get());
316 dispatcher->SetPowerHandler(power_handler_.get());
317 dispatcher->SetServiceWorkerHandler(service_worker_handler_.get());
318 dispatcher->SetTracingHandler(tracing_handler_.get());
320 if (!host->GetParent()) {
321 security_handler_.reset(new devtools::security::SecurityHandler());
322 page_handler_.reset(new devtools::page::PageHandler());
323 emulation_handler_.reset(
324 new devtools::emulation::EmulationHandler(page_handler_.get()));
325 dispatcher->SetSecurityHandler(security_handler_.get());
326 dispatcher->SetPageHandler(page_handler_.get());
327 dispatcher->SetEmulationHandler(emulation_handler_.get());
330 SetPending(host);
331 CommitPending();
332 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host));
334 g_instances.Get().push_back(this);
335 AddRef(); // Balanced in RenderFrameHostDestroyed.
338 void RenderFrameDevToolsAgentHost::SetPending(RenderFrameHostImpl* host) {
339 DCHECK(!pending_);
340 current_frame_crashed_ = false;
341 pending_.reset(new FrameHostHolder(this, host));
342 if (IsAttached())
343 pending_->Reattach(current_.get());
345 // Can only be null in constructor.
346 if (current_)
347 current_->Suspend();
348 pending_->Suspend();
350 UpdateProtocolHandlers(host);
353 void RenderFrameDevToolsAgentHost::CommitPending() {
354 DCHECK(pending_);
355 current_frame_crashed_ = false;
357 if (!ShouldCreateDevToolsFor(pending_->host())) {
358 DestroyOnRenderFrameGone();
359 // |this| may be deleted at this point.
360 return;
363 current_ = pending_.Pass();
364 UpdateProtocolHandlers(current_->host());
365 current_->Resume();
368 void RenderFrameDevToolsAgentHost::DiscardPending() {
369 DCHECK(pending_);
370 DCHECK(current_);
371 pending_.reset();
372 UpdateProtocolHandlers(current_->host());
373 current_->Resume();
376 BrowserContext* RenderFrameDevToolsAgentHost::GetBrowserContext() {
377 WebContents* contents = web_contents();
378 return contents ? contents->GetBrowserContext() : nullptr;
381 WebContents* RenderFrameDevToolsAgentHost::GetWebContents() {
382 return web_contents();
385 void RenderFrameDevToolsAgentHost::Attach() {
386 if (current_)
387 current_->Attach();
388 if (pending_)
389 pending_->Attach();
390 OnClientAttached();
393 void RenderFrameDevToolsAgentHost::Detach() {
394 if (current_)
395 current_->Detach();
396 if (pending_)
397 pending_->Detach();
398 OnClientDetached();
401 bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
402 const std::string& message) {
403 int call_id = 0;
404 if (protocol_handler_->HandleOptionalMessage(message, &call_id))
405 return true;
407 if (current_)
408 current_->DispatchProtocolMessage(call_id, message);
409 if (pending_)
410 pending_->DispatchProtocolMessage(call_id, message);
411 return true;
414 void RenderFrameDevToolsAgentHost::InspectElement(int x, int y) {
415 if (current_)
416 current_->InspectElement(x, y);
417 if (pending_)
418 pending_->InspectElement(x, y);
421 void RenderFrameDevToolsAgentHost::OnClientAttached() {
422 if (!web_contents())
423 return;
425 frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder());
427 #if defined(OS_ANDROID)
428 power_save_blocker_.reset(static_cast<PowerSaveBlockerImpl*>(
429 PowerSaveBlocker::Create(
430 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
431 PowerSaveBlocker::kReasonOther, "DevTools").release()));
432 power_save_blocker_->InitDisplaySleepBlocker(web_contents());
433 #endif
435 // TODO(kaznacheev): Move this call back to DevToolsManager when
436 // extensions::ProcessManager no longer relies on this notification.
437 DevToolsAgentHostImpl::NotifyCallbacks(this, true);
440 void RenderFrameDevToolsAgentHost::OnClientDetached() {
441 #if defined(OS_ANDROID)
442 power_save_blocker_.reset();
443 #endif
444 if (emulation_handler_)
445 emulation_handler_->Detached();
446 if (page_handler_)
447 page_handler_->Detached();
448 power_handler_->Detached();
449 service_worker_handler_->Detached();
450 tracing_handler_->Detached();
451 frame_trace_recorder_.reset();
453 // TODO(kaznacheev): Move this call back to DevToolsManager when
454 // extensions::ProcessManager no longer relies on this notification.
455 DevToolsAgentHostImpl::NotifyCallbacks(this, false);
458 RenderFrameDevToolsAgentHost::~RenderFrameDevToolsAgentHost() {
459 Instances::iterator it = std::find(g_instances.Get().begin(),
460 g_instances.Get().end(),
461 this);
462 if (it != g_instances.Get().end())
463 g_instances.Get().erase(it);
466 // TODO(creis): Consider removing this in favor of RenderFrameHostChanged.
467 void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
468 RenderFrameHost* old_host,
469 RenderFrameHost* new_host) {
470 DCHECK(!pending_ || pending_->host() != old_host);
471 if (!current_ || current_->host() != old_host)
472 return;
473 if (old_host == new_host && !current_frame_crashed_)
474 return;
475 DCHECK(!pending_);
476 SetPending(static_cast<RenderFrameHostImpl*>(new_host));
479 void RenderFrameDevToolsAgentHost::RenderFrameHostChanged(
480 RenderFrameHost* old_host,
481 RenderFrameHost* new_host) {
482 DCHECK(!pending_ || pending_->host() != old_host);
483 if (!current_ || current_->host() != old_host)
484 return;
486 // AboutToNavigateRenderFrame was not called for renderer-initiated
487 // navigation.
488 if (!pending_)
489 SetPending(static_cast<RenderFrameHostImpl*>(new_host));
491 CommitPending();
494 void RenderFrameDevToolsAgentHost::FrameDeleted(RenderFrameHost* rfh) {
495 if (pending_ && pending_->host() == rfh) {
496 DiscardPending();
497 return;
500 if (current_ && current_->host() == rfh)
501 DestroyOnRenderFrameGone(); // |this| may be deleted at this point.
504 void RenderFrameDevToolsAgentHost::RenderFrameDeleted(RenderFrameHost* rfh) {
505 if (!current_frame_crashed_)
506 FrameDeleted(rfh);
509 void RenderFrameDevToolsAgentHost::DestroyOnRenderFrameGone() {
510 DCHECK(current_);
511 scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
512 UpdateProtocolHandlers(nullptr);
513 if (IsAttached())
514 OnClientDetached();
515 HostClosed();
516 pending_.reset();
517 current_.reset();
518 Release();
521 void RenderFrameDevToolsAgentHost::RenderProcessGone(
522 base::TerminationStatus status) {
523 switch(status) {
524 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
525 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
526 #if defined(OS_CHROMEOS)
527 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
528 #endif
529 case base::TERMINATION_STATUS_PROCESS_CRASHED:
530 #if defined(OS_ANDROID)
531 case base::TERMINATION_STATUS_OOM_PROTECTED:
532 #endif
533 inspector_handler_->TargetCrashed();
534 current_frame_crashed_ = true;
535 break;
536 default:
537 break;
541 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
542 const IPC::Message& message) {
543 if (!current_)
544 return false;
545 if (message.type() == ViewHostMsg_SwapCompositorFrame::ID)
546 OnSwapCompositorFrame(message);
547 return false;
550 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
551 const IPC::Message& message,
552 RenderFrameHost* render_frame_host) {
553 if (message.type() != DevToolsClientMsg_DispatchOnInspectorFrontend::ID)
554 return false;
555 if (!IsAttached())
556 return false;
558 FrameHostHolder* holder = nullptr;
559 if (current_ && current_->host() == render_frame_host)
560 holder = current_.get();
561 if (pending_ && pending_->host() == render_frame_host)
562 holder = pending_.get();
563 if (!holder)
564 return false;
566 DevToolsClientMsg_DispatchOnInspectorFrontend::Param param;
567 if (!DevToolsClientMsg_DispatchOnInspectorFrontend::Read(&message, &param))
568 return false;
569 holder->ProcessChunkedMessageFromAgent(base::get<0>(param));
570 return true;
573 void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() {
574 if (page_handler_)
575 page_handler_->DidAttachInterstitialPage();
577 // TODO(dgozman): this may break for cross-process subframes.
578 if (!pending_)
579 return;
580 // Pending set in AboutToNavigateRenderFrame turned out to be interstitial.
581 // Connect back to the real one.
582 DiscardPending();
585 void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() {
586 if (page_handler_)
587 page_handler_->DidDetachInterstitialPage();
590 void RenderFrameDevToolsAgentHost::DidCommitProvisionalLoadForFrame(
591 RenderFrameHost* render_frame_host,
592 const GURL& url,
593 ui::PageTransition transition_type) {
594 if (pending_ && pending_->host() == render_frame_host)
595 CommitPending();
596 service_worker_handler_->UpdateHosts();
599 void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
600 RenderFrameHost* render_frame_host,
601 const GURL& validated_url,
602 int error_code,
603 const base::string16& error_description,
604 bool was_ignored_by_handler) {
605 if (pending_ && pending_->host() == render_frame_host)
606 DiscardPending();
609 void RenderFrameDevToolsAgentHost::UpdateProtocolHandlers(
610 RenderFrameHostImpl* host) {
611 dom_handler_->SetRenderFrameHost(host);
612 if (emulation_handler_)
613 emulation_handler_->SetRenderFrameHost(host);
614 input_handler_->SetRenderWidgetHost(
615 host ? host->GetRenderWidgetHost() : nullptr);
616 inspector_handler_->SetRenderFrameHost(host);
617 network_handler_->SetRenderFrameHost(host);
618 if (page_handler_)
619 page_handler_->SetRenderFrameHost(host);
620 service_worker_handler_->SetRenderFrameHost(host);
621 if (security_handler_)
622 security_handler_->SetRenderFrameHost(host);
625 void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
626 if (pending_)
627 DiscardPending();
628 UpdateProtocolHandlers(nullptr);
629 current_.reset();
630 WebContentsObserver::Observe(nullptr);
633 void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
634 DCHECK(!current_);
635 DCHECK(!pending_);
636 RenderFrameHostImpl* host =
637 static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
638 DCHECK(host);
639 SetPending(host);
640 CommitPending();
641 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host));
644 DevToolsAgentHost::Type RenderFrameDevToolsAgentHost::GetType() {
645 return IsChildFrame() ? TYPE_FRAME : TYPE_WEB_CONTENTS;
648 std::string RenderFrameDevToolsAgentHost::GetTitle() {
649 if (IsChildFrame())
650 return GetURL().spec();
651 if (WebContents* web_contents = GetWebContents())
652 return base::UTF16ToUTF8(web_contents->GetTitle());
653 return "";
656 GURL RenderFrameDevToolsAgentHost::GetURL() {
657 // Order is important here.
658 WebContents* web_contents = GetWebContents();
659 if (web_contents && !IsChildFrame())
660 return web_contents->GetVisibleURL();
661 if (pending_)
662 return pending_->host()->GetLastCommittedURL();
663 if (current_)
664 return current_->host()->GetLastCommittedURL();
665 return GURL();
668 bool RenderFrameDevToolsAgentHost::Activate() {
669 WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents());
670 if (wc) {
671 wc->Activate();
672 return true;
674 return false;
677 bool RenderFrameDevToolsAgentHost::Close() {
678 if (web_contents()) {
679 web_contents()->ClosePage();
680 return true;
682 return false;
685 void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame(
686 const IPC::Message& message) {
687 ViewHostMsg_SwapCompositorFrame::Param param;
688 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
689 return;
690 if (page_handler_)
691 page_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
692 if (input_handler_)
693 input_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
694 if (frame_trace_recorder_) {
695 frame_trace_recorder_->OnSwapCompositorFrame(
696 current_ ? current_->host() : nullptr,
697 base::get<1>(param).metadata,
698 tracing_handler_->did_initiate_recording());
702 void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
703 const cc::CompositorFrameMetadata& frame_metadata) {
704 if (page_handler_)
705 page_handler_->OnSwapCompositorFrame(frame_metadata);
706 if (input_handler_)
707 input_handler_->OnSwapCompositorFrame(frame_metadata);
708 if (frame_trace_recorder_) {
709 frame_trace_recorder_->OnSwapCompositorFrame(
710 current_ ? current_->host() : nullptr,
711 frame_metadata,
712 tracing_handler_->did_initiate_recording());
716 bool RenderFrameDevToolsAgentHost::HasRenderFrameHost(
717 RenderFrameHost* host) {
718 return (current_ && current_->host() == host) ||
719 (pending_ && pending_->host() == host);
722 bool RenderFrameDevToolsAgentHost::IsChildFrame() {
723 return current_ && current_->host()->GetParent();
726 } // namespace content