DevTools: cut host and port from webSocketDebuggerUrl in addition to ws:// prefix
[chromium-blink-merge.git] / content / browser / devtools / render_frame_devtools_agent_host.cc
blob167668627a6370608d8dcf2d1f296fafb00cabd5
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 if (IsAttached())
513 OnClientDetached();
514 HostClosed();
515 pending_.reset();
516 current_.reset();
517 Release();
520 void RenderFrameDevToolsAgentHost::RenderProcessGone(
521 base::TerminationStatus status) {
522 switch(status) {
523 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
524 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
525 #if defined(OS_CHROMEOS)
526 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
527 #endif
528 case base::TERMINATION_STATUS_PROCESS_CRASHED:
529 #if defined(OS_ANDROID)
530 case base::TERMINATION_STATUS_OOM_PROTECTED:
531 #endif
532 inspector_handler_->TargetCrashed();
533 current_frame_crashed_ = true;
534 break;
535 default:
536 break;
540 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
541 const IPC::Message& message) {
542 if (!current_)
543 return false;
544 if (message.type() == ViewHostMsg_SwapCompositorFrame::ID)
545 OnSwapCompositorFrame(message);
546 return false;
549 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
550 const IPC::Message& message,
551 RenderFrameHost* render_frame_host) {
552 if (message.type() != DevToolsClientMsg_DispatchOnInspectorFrontend::ID)
553 return false;
554 if (!IsAttached())
555 return false;
557 FrameHostHolder* holder = nullptr;
558 if (current_ && current_->host() == render_frame_host)
559 holder = current_.get();
560 if (pending_ && pending_->host() == render_frame_host)
561 holder = pending_.get();
562 if (!holder)
563 return false;
565 DevToolsClientMsg_DispatchOnInspectorFrontend::Param param;
566 if (!DevToolsClientMsg_DispatchOnInspectorFrontend::Read(&message, &param))
567 return false;
568 holder->ProcessChunkedMessageFromAgent(base::get<0>(param));
569 return true;
572 void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() {
573 if (page_handler_)
574 page_handler_->DidAttachInterstitialPage();
576 // TODO(dgozman): this may break for cross-process subframes.
577 if (!pending_)
578 return;
579 // Pending set in AboutToNavigateRenderFrame turned out to be interstitial.
580 // Connect back to the real one.
581 DiscardPending();
584 void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() {
585 if (page_handler_)
586 page_handler_->DidDetachInterstitialPage();
589 void RenderFrameDevToolsAgentHost::DidCommitProvisionalLoadForFrame(
590 RenderFrameHost* render_frame_host,
591 const GURL& url,
592 ui::PageTransition transition_type) {
593 if (pending_ && pending_->host() == render_frame_host)
594 CommitPending();
595 service_worker_handler_->UpdateHosts();
598 void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
599 RenderFrameHost* render_frame_host,
600 const GURL& validated_url,
601 int error_code,
602 const base::string16& error_description,
603 bool was_ignored_by_handler) {
604 if (pending_ && pending_->host() == render_frame_host)
605 DiscardPending();
608 void RenderFrameDevToolsAgentHost::UpdateProtocolHandlers(
609 RenderFrameHostImpl* host) {
610 dom_handler_->SetRenderFrameHost(host);
611 if (emulation_handler_)
612 emulation_handler_->SetRenderFrameHost(host);
613 input_handler_->SetRenderWidgetHost(
614 host ? host->GetRenderWidgetHost() : nullptr);
615 inspector_handler_->SetRenderFrameHost(host);
616 network_handler_->SetRenderFrameHost(host);
617 if (page_handler_)
618 page_handler_->SetRenderFrameHost(host);
619 service_worker_handler_->SetRenderFrameHost(host);
620 if (security_handler_)
621 security_handler_->SetRenderFrameHost(host);
624 void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
625 if (pending_)
626 DiscardPending();
627 UpdateProtocolHandlers(nullptr);
628 current_.reset();
629 WebContentsObserver::Observe(nullptr);
632 void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
633 DCHECK(!current_);
634 DCHECK(!pending_);
635 RenderFrameHostImpl* host =
636 static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
637 DCHECK(host);
638 SetPending(host);
639 CommitPending();
640 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host));
643 DevToolsAgentHost::Type RenderFrameDevToolsAgentHost::GetType() {
644 return IsChildFrame() ? TYPE_FRAME : TYPE_WEB_CONTENTS;
647 std::string RenderFrameDevToolsAgentHost::GetTitle() {
648 if (IsChildFrame())
649 return GetURL().spec();
650 if (WebContents* web_contents = GetWebContents())
651 return base::UTF16ToUTF8(web_contents->GetTitle());
652 return "";
655 GURL RenderFrameDevToolsAgentHost::GetURL() {
656 // Order is important here.
657 WebContents* web_contents = GetWebContents();
658 if (web_contents && !IsChildFrame())
659 return web_contents->GetVisibleURL();
660 if (pending_)
661 return pending_->host()->GetLastCommittedURL();
662 if (current_)
663 return current_->host()->GetLastCommittedURL();
664 return GURL();
667 bool RenderFrameDevToolsAgentHost::Activate() {
668 WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents());
669 if (wc) {
670 wc->Activate();
671 return true;
673 return false;
676 bool RenderFrameDevToolsAgentHost::Close() {
677 if (web_contents()) {
678 web_contents()->ClosePage();
679 return true;
681 return false;
684 void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame(
685 const IPC::Message& message) {
686 ViewHostMsg_SwapCompositorFrame::Param param;
687 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
688 return;
689 if (page_handler_)
690 page_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
691 if (input_handler_)
692 input_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
693 if (frame_trace_recorder_) {
694 frame_trace_recorder_->OnSwapCompositorFrame(
695 current_ ? current_->host() : nullptr,
696 base::get<1>(param).metadata,
697 tracing_handler_->did_initiate_recording());
701 void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
702 const cc::CompositorFrameMetadata& frame_metadata) {
703 if (page_handler_)
704 page_handler_->OnSwapCompositorFrame(frame_metadata);
705 if (input_handler_)
706 input_handler_->OnSwapCompositorFrame(frame_metadata);
707 if (frame_trace_recorder_) {
708 frame_trace_recorder_->OnSwapCompositorFrame(
709 current_ ? current_->host() : nullptr,
710 frame_metadata,
711 tracing_handler_->did_initiate_recording());
715 bool RenderFrameDevToolsAgentHost::HasRenderFrameHost(
716 RenderFrameHost* host) {
717 return (current_ && current_->host() == host) ||
718 (pending_ && pending_->host() == host);
721 bool RenderFrameDevToolsAgentHost::IsChildFrame() {
722 return current_ && current_->host()->GetParent();
725 } // namespace content