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/io_handler.h"
18 #include "content/browser/devtools/protocol/network_handler.h"
19 #include "content/browser/devtools/protocol/page_handler.h"
20 #include "content/browser/devtools/protocol/power_handler.h"
21 #include "content/browser/devtools/protocol/security_handler.h"
22 #include "content/browser/devtools/protocol/service_worker_handler.h"
23 #include "content/browser/devtools/protocol/tracing_handler.h"
24 #include "content/browser/frame_host/render_frame_host_impl.h"
25 #include "content/browser/renderer_host/render_process_host_impl.h"
26 #include "content/browser/renderer_host/render_view_host_impl.h"
27 #include "content/browser/site_instance_impl.h"
28 #include "content/browser/web_contents/web_contents_impl.h"
29 #include "content/common/view_messages.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/content_browser_client.h"
32 #include "content/public/browser/render_widget_host_iterator.h"
33 #include "content/public/browser/web_contents_delegate.h"
35 #if defined(OS_ANDROID)
36 #include "content/browser/power_save_blocker_impl.h"
37 #include "content/public/browser/render_widget_host_view.h"
42 typedef std::vector
<RenderFrameDevToolsAgentHost
*> Instances
;
45 base::LazyInstance
<Instances
>::Leaky g_instances
= LAZY_INSTANCE_INITIALIZER
;
47 static RenderFrameDevToolsAgentHost
* FindAgentHost(RenderFrameHost
* host
) {
48 if (g_instances
== NULL
)
50 for (Instances::iterator it
= g_instances
.Get().begin();
51 it
!= g_instances
.Get().end(); ++it
) {
52 if ((*it
)->HasRenderFrameHost(host
))
58 // Returns RenderFrameDevToolsAgentHost attached to any of RenderFrameHost
59 // instances associated with |web_contents|
60 static RenderFrameDevToolsAgentHost
* FindAgentHost(WebContents
* web_contents
) {
61 if (g_instances
== NULL
)
63 for (Instances::iterator it
= g_instances
.Get().begin();
64 it
!= g_instances
.Get().end(); ++it
) {
65 if ((*it
)->GetWebContents() == web_contents
)
71 bool ShouldCreateDevToolsFor(RenderFrameHost
* rfh
) {
72 return rfh
->IsCrossProcessSubframe() || !rfh
->GetParent();
77 // RenderFrameDevToolsAgentHost::FrameHostHolder -------------------------------
79 class RenderFrameDevToolsAgentHost::FrameHostHolder
{
82 RenderFrameDevToolsAgentHost
* agent
, RenderFrameHostImpl
* host
);
85 RenderFrameHostImpl
* host() const { return host_
; }
88 void Reattach(FrameHostHolder
* old
);
90 void DispatchProtocolMessage(int call_id
, const std::string
& message
);
91 void InspectElement(int x
, int y
);
92 void ProcessChunkedMessageFromAgent(const DevToolsMessageChunk
& chunk
);
99 void SendMessageToClient(const std::string
& message
);
101 RenderFrameDevToolsAgentHost
* agent_
;
102 RenderFrameHostImpl
* host_
;
105 DevToolsMessageChunkProcessor chunk_processor_
;
106 std::vector
<std::string
> pending_messages_
;
107 std::map
<int, std::string
> sent_messages_
;
110 RenderFrameDevToolsAgentHost::FrameHostHolder::FrameHostHolder(
111 RenderFrameDevToolsAgentHost
* agent
, RenderFrameHostImpl
* host
)
116 chunk_processor_(base::Bind(
117 &RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient
,
118 base::Unretained(this))) {
123 RenderFrameDevToolsAgentHost::FrameHostHolder::~FrameHostHolder() {
128 void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach() {
129 host_
->Send(new DevToolsAgentMsg_Attach(
130 host_
->GetRoutingID(), agent_
->GetId()));
135 void RenderFrameDevToolsAgentHost::FrameHostHolder::Reattach(
136 FrameHostHolder
* old
) {
138 chunk_processor_
.set_state_cookie(old
->chunk_processor_
.state_cookie());
139 host_
->Send(new DevToolsAgentMsg_Reattach(
140 host_
->GetRoutingID(), agent_
->GetId(), chunk_processor_
.state_cookie()));
142 for (const auto& pair
: old
->sent_messages_
)
143 DispatchProtocolMessage(pair
.first
, pair
.second
);
149 void RenderFrameDevToolsAgentHost::FrameHostHolder::Detach() {
150 host_
->Send(new DevToolsAgentMsg_Detach(host_
->GetRoutingID()));
155 void RenderFrameDevToolsAgentHost::FrameHostHolder::GrantPolicy() {
156 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies(
157 host_
->GetProcess()->GetID());
160 void RenderFrameDevToolsAgentHost::FrameHostHolder::RevokePolicy() {
161 bool process_has_agents
= false;
162 RenderProcessHost
* process_host
= host_
->GetProcess();
163 for (RenderFrameDevToolsAgentHost
* agent
: g_instances
.Get()) {
164 if (!agent
->IsAttached())
166 if (agent
->current_
&& agent
->current_
->host() != host_
&&
167 agent
->current_
->host()->GetProcess() == process_host
) {
168 process_has_agents
= true;
170 if (agent
->pending_
&& agent
->pending_
->host() != host_
&&
171 agent
->pending_
->host()->GetProcess() == process_host
) {
172 process_has_agents
= true;
176 // We are the last to disconnect from the renderer -> revoke permissions.
177 if (!process_has_agents
) {
178 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeReadRawCookies(
179 process_host
->GetID());
182 void RenderFrameDevToolsAgentHost::FrameHostHolder::DispatchProtocolMessage(
183 int call_id
, const std::string
& message
) {
184 host_
->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
185 host_
->GetRoutingID(), message
));
186 sent_messages_
[call_id
] = message
;
189 void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement(
191 host_
->Send(new DevToolsAgentMsg_InspectElement(
192 host_
->GetRoutingID(), agent_
->GetId(), x
, y
));
196 RenderFrameDevToolsAgentHost::FrameHostHolder::ProcessChunkedMessageFromAgent(
197 const DevToolsMessageChunk
& chunk
) {
198 chunk_processor_
.ProcessChunkedMessageFromAgent(chunk
);
201 void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient(
202 const std::string
& message
) {
203 sent_messages_
.erase(chunk_processor_
.last_call_id());
205 pending_messages_
.push_back(message
);
207 agent_
->SendMessageToClient(message
);
210 void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
214 void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() {
216 for (const std::string
& message
: pending_messages_
)
217 agent_
->SendMessageToClient(message
);
218 std::vector
<std::string
> empty
;
219 pending_messages_
.swap(empty
);
222 // RenderFrameDevToolsAgentHost ------------------------------------------------
224 scoped_refptr
<DevToolsAgentHost
>
225 DevToolsAgentHost::GetOrCreateFor(WebContents
* web_contents
) {
226 RenderFrameDevToolsAgentHost
* result
= FindAgentHost(web_contents
);
228 // TODO(dgozman): this check should not be necessary. See
229 // http://crbug.com/489664.
230 if (!web_contents
->GetMainFrame())
232 result
= new RenderFrameDevToolsAgentHost(
233 static_cast<RenderFrameHostImpl
*>(web_contents
->GetMainFrame()));
239 scoped_refptr
<DevToolsAgentHost
> RenderFrameDevToolsAgentHost::GetOrCreateFor(
240 RenderFrameHostImpl
* host
) {
241 RenderFrameDevToolsAgentHost
* result
= FindAgentHost(host
);
243 result
= new RenderFrameDevToolsAgentHost(host
);
248 void RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable(
249 DevToolsAgentHost::List
* result
,
250 RenderFrameHost
* host
) {
251 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(host
);
252 if (!rfh
->IsRenderFrameLive())
254 if (ShouldCreateDevToolsFor(rfh
))
255 result
->push_back(RenderFrameDevToolsAgentHost::GetOrCreateFor(rfh
));
259 bool DevToolsAgentHost::HasFor(WebContents
* web_contents
) {
260 return FindAgentHost(web_contents
) != NULL
;
264 bool DevToolsAgentHost::IsDebuggerAttached(WebContents
* web_contents
) {
265 RenderFrameDevToolsAgentHost
* agent_host
= FindAgentHost(web_contents
);
266 return agent_host
&& agent_host
->IsAttached();
270 void RenderFrameDevToolsAgentHost::AddAllAgentHosts(
271 DevToolsAgentHost::List
* result
) {
272 base::Callback
<void(RenderFrameHost
*)> callback
= base::Bind(
273 RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable
,
274 base::Unretained(result
));
275 for (const auto& wc
: WebContentsImpl::GetAllWebContents())
276 wc
->ForEachFrame(callback
);
280 void RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
281 RenderFrameHost
* pending
,
282 RenderFrameHost
* current
) {
283 RenderFrameDevToolsAgentHost
* agent_host
= FindAgentHost(pending
);
286 if (agent_host
->pending_
&& agent_host
->pending_
->host() == pending
) {
287 DCHECK(agent_host
->current_
&& agent_host
->current_
->host() == current
);
288 agent_host
->DiscardPending();
292 RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
293 RenderFrameHostImpl
* host
)
294 : dom_handler_(new devtools::dom::DOMHandler()),
295 input_handler_(new devtools::input::InputHandler()),
296 inspector_handler_(new devtools::inspector::InspectorHandler()),
297 io_handler_(new devtools::io::IOHandler(GetIOContext())),
298 network_handler_(new devtools::network::NetworkHandler()),
299 page_handler_(nullptr),
300 power_handler_(new devtools::power::PowerHandler()),
301 security_handler_(nullptr),
302 service_worker_handler_(
303 new devtools::service_worker::ServiceWorkerHandler()),
304 tracing_handler_(new devtools::tracing::TracingHandler(
305 devtools::tracing::TracingHandler::Renderer
,
307 emulation_handler_(nullptr),
308 frame_trace_recorder_(nullptr),
309 protocol_handler_(new DevToolsProtocolHandler(
311 base::Bind(&RenderFrameDevToolsAgentHost::SendMessageToClient
,
312 base::Unretained(this)))),
313 current_frame_crashed_(false) {
314 DevToolsProtocolDispatcher
* dispatcher
= protocol_handler_
->dispatcher();
315 dispatcher
->SetDOMHandler(dom_handler_
.get());
316 dispatcher
->SetInputHandler(input_handler_
.get());
317 dispatcher
->SetInspectorHandler(inspector_handler_
.get());
318 dispatcher
->SetIOHandler(io_handler_
.get());
319 dispatcher
->SetNetworkHandler(network_handler_
.get());
320 dispatcher
->SetPowerHandler(power_handler_
.get());
321 dispatcher
->SetServiceWorkerHandler(service_worker_handler_
.get());
322 dispatcher
->SetTracingHandler(tracing_handler_
.get());
324 if (!host
->GetParent()) {
325 security_handler_
.reset(new devtools::security::SecurityHandler());
326 page_handler_
.reset(new devtools::page::PageHandler());
327 emulation_handler_
.reset(
328 new devtools::emulation::EmulationHandler(page_handler_
.get()));
329 dispatcher
->SetSecurityHandler(security_handler_
.get());
330 dispatcher
->SetPageHandler(page_handler_
.get());
331 dispatcher
->SetEmulationHandler(emulation_handler_
.get());
336 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host
));
338 g_instances
.Get().push_back(this);
339 AddRef(); // Balanced in RenderFrameHostDestroyed.
342 void RenderFrameDevToolsAgentHost::SetPending(RenderFrameHostImpl
* host
) {
344 current_frame_crashed_
= false;
345 pending_
.reset(new FrameHostHolder(this, host
));
347 pending_
->Reattach(current_
.get());
349 // Can only be null in constructor.
354 UpdateProtocolHandlers(host
);
357 void RenderFrameDevToolsAgentHost::CommitPending() {
359 current_frame_crashed_
= false;
361 if (!ShouldCreateDevToolsFor(pending_
->host())) {
362 DestroyOnRenderFrameGone();
363 // |this| may be deleted at this point.
367 current_
= pending_
.Pass();
368 UpdateProtocolHandlers(current_
->host());
372 void RenderFrameDevToolsAgentHost::DiscardPending() {
376 UpdateProtocolHandlers(current_
->host());
380 BrowserContext
* RenderFrameDevToolsAgentHost::GetBrowserContext() {
381 WebContents
* contents
= web_contents();
382 return contents
? contents
->GetBrowserContext() : nullptr;
385 WebContents
* RenderFrameDevToolsAgentHost::GetWebContents() {
386 return web_contents();
389 void RenderFrameDevToolsAgentHost::Attach() {
397 void RenderFrameDevToolsAgentHost::Detach() {
405 bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
406 const std::string
& message
) {
408 if (protocol_handler_
->HandleOptionalMessage(message
, &call_id
))
412 current_
->DispatchProtocolMessage(call_id
, message
);
414 pending_
->DispatchProtocolMessage(call_id
, message
);
418 void RenderFrameDevToolsAgentHost::InspectElement(int x
, int y
) {
420 current_
->InspectElement(x
, y
);
422 pending_
->InspectElement(x
, y
);
425 void RenderFrameDevToolsAgentHost::OnClientAttached() {
429 frame_trace_recorder_
.reset(new DevToolsFrameTraceRecorder());
431 #if defined(OS_ANDROID)
432 power_save_blocker_
.reset(static_cast<PowerSaveBlockerImpl
*>(
433 PowerSaveBlocker::Create(
434 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep
,
435 PowerSaveBlocker::kReasonOther
, "DevTools").release()));
436 power_save_blocker_
->InitDisplaySleepBlocker(web_contents());
439 // TODO(kaznacheev): Move this call back to DevToolsManager when
440 // extensions::ProcessManager no longer relies on this notification.
441 DevToolsAgentHostImpl::NotifyCallbacks(this, true);
444 void RenderFrameDevToolsAgentHost::OnClientDetached() {
445 #if defined(OS_ANDROID)
446 power_save_blocker_
.reset();
448 if (emulation_handler_
)
449 emulation_handler_
->Detached();
451 page_handler_
->Detached();
452 power_handler_
->Detached();
453 service_worker_handler_
->Detached();
454 tracing_handler_
->Detached();
455 frame_trace_recorder_
.reset();
457 // TODO(kaznacheev): Move this call back to DevToolsManager when
458 // extensions::ProcessManager no longer relies on this notification.
459 DevToolsAgentHostImpl::NotifyCallbacks(this, false);
462 RenderFrameDevToolsAgentHost::~RenderFrameDevToolsAgentHost() {
463 Instances::iterator it
= std::find(g_instances
.Get().begin(),
464 g_instances
.Get().end(),
466 if (it
!= g_instances
.Get().end())
467 g_instances
.Get().erase(it
);
470 // TODO(creis): Consider removing this in favor of RenderFrameHostChanged.
471 void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
472 RenderFrameHost
* old_host
,
473 RenderFrameHost
* new_host
) {
474 DCHECK(!pending_
|| pending_
->host() != old_host
);
475 if (!current_
|| current_
->host() != old_host
)
477 if (old_host
== new_host
&& !current_frame_crashed_
)
480 SetPending(static_cast<RenderFrameHostImpl
*>(new_host
));
483 void RenderFrameDevToolsAgentHost::RenderFrameHostChanged(
484 RenderFrameHost
* old_host
,
485 RenderFrameHost
* new_host
) {
486 DCHECK(!pending_
|| pending_
->host() != old_host
);
487 if (!current_
|| current_
->host() != old_host
)
490 // AboutToNavigateRenderFrame was not called for renderer-initiated
493 SetPending(static_cast<RenderFrameHostImpl
*>(new_host
));
498 void RenderFrameDevToolsAgentHost::FrameDeleted(RenderFrameHost
* rfh
) {
499 if (pending_
&& pending_
->host() == rfh
) {
504 if (current_
&& current_
->host() == rfh
)
505 DestroyOnRenderFrameGone(); // |this| may be deleted at this point.
508 void RenderFrameDevToolsAgentHost::RenderFrameDeleted(RenderFrameHost
* rfh
) {
509 if (!current_frame_crashed_
)
513 void RenderFrameDevToolsAgentHost::DestroyOnRenderFrameGone() {
515 scoped_refptr
<RenderFrameDevToolsAgentHost
> protect(this);
516 UpdateProtocolHandlers(nullptr);
525 void RenderFrameDevToolsAgentHost::RenderProcessGone(
526 base::TerminationStatus status
) {
528 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
529 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
530 #if defined(OS_CHROMEOS)
531 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM
:
533 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
534 #if defined(OS_ANDROID)
535 case base::TERMINATION_STATUS_OOM_PROTECTED
:
537 case base::TERMINATION_STATUS_LAUNCH_FAILED
:
538 inspector_handler_
->TargetCrashed();
539 current_frame_crashed_
= true;
542 inspector_handler_
->TargetDetached("Render process gone.");
547 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
548 const IPC::Message
& message
) {
551 if (message
.type() == ViewHostMsg_SwapCompositorFrame::ID
)
552 OnSwapCompositorFrame(message
);
556 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
557 const IPC::Message
& message
,
558 RenderFrameHost
* render_frame_host
) {
559 if (message
.type() != DevToolsClientMsg_DispatchOnInspectorFrontend::ID
)
564 FrameHostHolder
* holder
= nullptr;
565 if (current_
&& current_
->host() == render_frame_host
)
566 holder
= current_
.get();
567 if (pending_
&& pending_
->host() == render_frame_host
)
568 holder
= pending_
.get();
572 DevToolsClientMsg_DispatchOnInspectorFrontend::Param param
;
573 if (!DevToolsClientMsg_DispatchOnInspectorFrontend::Read(&message
, ¶m
))
575 holder
->ProcessChunkedMessageFromAgent(base::get
<0>(param
));
579 void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() {
581 page_handler_
->DidAttachInterstitialPage();
583 // TODO(dgozman): this may break for cross-process subframes.
586 // Pending set in AboutToNavigateRenderFrame turned out to be interstitial.
587 // Connect back to the real one.
591 void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() {
593 page_handler_
->DidDetachInterstitialPage();
596 void RenderFrameDevToolsAgentHost::DidCommitProvisionalLoadForFrame(
597 RenderFrameHost
* render_frame_host
,
599 ui::PageTransition transition_type
) {
600 if (pending_
&& pending_
->host() == render_frame_host
)
602 service_worker_handler_
->UpdateHosts();
605 void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
606 RenderFrameHost
* render_frame_host
,
607 const GURL
& validated_url
,
609 const base::string16
& error_description
,
610 bool was_ignored_by_handler
) {
611 if (pending_
&& pending_
->host() == render_frame_host
)
615 void RenderFrameDevToolsAgentHost::UpdateProtocolHandlers(
616 RenderFrameHostImpl
* host
) {
617 dom_handler_
->SetRenderFrameHost(host
);
618 if (emulation_handler_
)
619 emulation_handler_
->SetRenderFrameHost(host
);
620 input_handler_
->SetRenderWidgetHost(
621 host
? host
->GetRenderWidgetHost() : nullptr);
622 inspector_handler_
->SetRenderFrameHost(host
);
623 network_handler_
->SetRenderFrameHost(host
);
625 page_handler_
->SetRenderFrameHost(host
);
626 service_worker_handler_
->SetRenderFrameHost(host
);
627 if (security_handler_
)
628 security_handler_
->SetRenderFrameHost(host
);
631 void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
634 UpdateProtocolHandlers(nullptr);
635 disconnected_
= current_
.Pass();
636 WebContentsObserver::Observe(nullptr);
639 void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents
* wc
) {
642 RenderFrameHostImpl
* host
=
643 static_cast<RenderFrameHostImpl
*>(wc
->GetMainFrame());
645 current_
= disconnected_
.Pass();
648 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host
));
651 DevToolsAgentHost::Type
RenderFrameDevToolsAgentHost::GetType() {
652 return IsChildFrame() ? TYPE_FRAME
: TYPE_WEB_CONTENTS
;
655 std::string
RenderFrameDevToolsAgentHost::GetTitle() {
657 return GetURL().spec();
658 if (WebContents
* web_contents
= GetWebContents())
659 return base::UTF16ToUTF8(web_contents
->GetTitle());
663 GURL
RenderFrameDevToolsAgentHost::GetURL() {
664 // Order is important here.
665 WebContents
* web_contents
= GetWebContents();
666 if (web_contents
&& !IsChildFrame())
667 return web_contents
->GetVisibleURL();
669 return pending_
->host()->GetLastCommittedURL();
671 return current_
->host()->GetLastCommittedURL();
675 bool RenderFrameDevToolsAgentHost::Activate() {
676 WebContentsImpl
* wc
= static_cast<WebContentsImpl
*>(web_contents());
684 bool RenderFrameDevToolsAgentHost::Close() {
685 if (web_contents()) {
686 web_contents()->ClosePage();
692 void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame(
693 const IPC::Message
& message
) {
694 ViewHostMsg_SwapCompositorFrame::Param param
;
695 if (!ViewHostMsg_SwapCompositorFrame::Read(&message
, ¶m
))
698 page_handler_
->OnSwapCompositorFrame(base::get
<1>(param
).metadata
);
700 input_handler_
->OnSwapCompositorFrame(base::get
<1>(param
).metadata
);
701 if (frame_trace_recorder_
&& tracing_handler_
->did_initiate_recording()) {
702 frame_trace_recorder_
->OnSwapCompositorFrame(
703 current_
? current_
->host() : nullptr,
704 base::get
<1>(param
).metadata
);
708 void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
709 const cc::CompositorFrameMetadata
& frame_metadata
) {
711 page_handler_
->OnSynchronousSwapCompositorFrame(frame_metadata
);
713 input_handler_
->OnSwapCompositorFrame(frame_metadata
);
714 if (frame_trace_recorder_
&& tracing_handler_
->did_initiate_recording()) {
715 frame_trace_recorder_
->OnSynchronousSwapCompositorFrame(
716 current_
? current_
->host() : nullptr,
721 bool RenderFrameDevToolsAgentHost::HasRenderFrameHost(
722 RenderFrameHost
* host
) {
723 return (current_
&& current_
->host() == host
) ||
724 (pending_
&& pending_
->host() == host
);
727 bool RenderFrameDevToolsAgentHost::IsChildFrame() {
728 return current_
&& current_
->host()->GetParent();
731 } // namespace content