[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / devtools / render_frame_devtools_agent_host.cc
blobb763dc7668fcc983821d35c95bfdee1b7665f89c
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"
38 #endif
40 namespace content {
42 typedef std::vector<RenderFrameDevToolsAgentHost*> Instances;
44 namespace {
45 base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
47 static RenderFrameDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) {
48 if (g_instances == NULL)
49 return NULL;
50 for (Instances::iterator it = g_instances.Get().begin();
51 it != g_instances.Get().end(); ++it) {
52 if ((*it)->HasRenderFrameHost(host))
53 return *it;
55 return NULL;
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)
62 return NULL;
63 for (Instances::iterator it = g_instances.Get().begin();
64 it != g_instances.Get().end(); ++it) {
65 if ((*it)->GetWebContents() == web_contents)
66 return *it;
68 return NULL;
71 bool ShouldCreateDevToolsFor(RenderFrameHost* rfh) {
72 return rfh->IsCrossProcessSubframe() || !rfh->GetParent();
75 } // namespace
77 // RenderFrameDevToolsAgentHost::FrameHostHolder -------------------------------
79 class RenderFrameDevToolsAgentHost::FrameHostHolder {
80 public:
81 FrameHostHolder(
82 RenderFrameDevToolsAgentHost* agent, RenderFrameHostImpl* host);
83 ~FrameHostHolder();
85 RenderFrameHostImpl* host() const { return host_; }
87 void Attach();
88 void Reattach(FrameHostHolder* old);
89 void Detach();
90 void DispatchProtocolMessage(int call_id, const std::string& message);
91 void InspectElement(int x, int y);
92 void ProcessChunkedMessageFromAgent(const DevToolsMessageChunk& chunk);
93 void Suspend();
94 void Resume();
96 private:
97 void GrantPolicy();
98 void RevokePolicy();
99 void SendMessageToClient(const std::string& message);
101 RenderFrameDevToolsAgentHost* agent_;
102 RenderFrameHostImpl* host_;
103 bool attached_;
104 bool suspended_;
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)
112 : agent_(agent),
113 host_(host),
114 attached_(false),
115 suspended_(false),
116 chunk_processor_(base::Bind(
117 &RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient,
118 base::Unretained(this))) {
119 DCHECK(agent_);
120 DCHECK(host_);
123 RenderFrameDevToolsAgentHost::FrameHostHolder::~FrameHostHolder() {
124 if (attached_)
125 RevokePolicy();
128 void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach() {
129 host_->Send(new DevToolsAgentMsg_Attach(
130 host_->GetRoutingID(), agent_->GetId()));
131 GrantPolicy();
132 attached_ = true;
135 void RenderFrameDevToolsAgentHost::FrameHostHolder::Reattach(
136 FrameHostHolder* old) {
137 if (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()));
141 if (old) {
142 for (const auto& pair : old->sent_messages_)
143 DispatchProtocolMessage(pair.first, pair.second);
145 GrantPolicy();
146 attached_ = true;
149 void RenderFrameDevToolsAgentHost::FrameHostHolder::Detach() {
150 host_->Send(new DevToolsAgentMsg_Detach(host_->GetRoutingID()));
151 RevokePolicy();
152 attached_ = false;
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())
165 continue;
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(
190 int x, int y) {
191 host_->Send(new DevToolsAgentMsg_InspectElement(
192 host_->GetRoutingID(), agent_->GetId(), x, y));
195 void
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());
204 if (suspended_)
205 pending_messages_.push_back(message);
206 else
207 agent_->SendMessageToClient(message);
210 void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
211 suspended_ = true;
214 void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() {
215 suspended_ = false;
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);
227 if (!result) {
228 // TODO(dgozman): this check should not be necessary. See
229 // http://crbug.com/489664.
230 if (!web_contents->GetMainFrame())
231 return nullptr;
232 result = new RenderFrameDevToolsAgentHost(
233 static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame()));
235 return result;
238 // static
239 scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::GetOrCreateFor(
240 RenderFrameHostImpl* host) {
241 RenderFrameDevToolsAgentHost* result = FindAgentHost(host);
242 if (!result)
243 result = new RenderFrameDevToolsAgentHost(host);
244 return result;
247 // static
248 void RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable(
249 DevToolsAgentHost::List* result,
250 RenderFrameHost* host) {
251 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(host);
252 if (!rfh->IsRenderFrameLive())
253 return;
254 if (ShouldCreateDevToolsFor(rfh))
255 result->push_back(RenderFrameDevToolsAgentHost::GetOrCreateFor(rfh));
258 // static
259 bool DevToolsAgentHost::HasFor(WebContents* web_contents) {
260 return FindAgentHost(web_contents) != NULL;
263 // static
264 bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) {
265 RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(web_contents);
266 return agent_host && agent_host->IsAttached();
269 // static
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);
279 // static
280 void RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
281 RenderFrameHost* pending,
282 RenderFrameHost* current) {
283 RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(pending);
284 if (!agent_host)
285 return;
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,
306 GetIOContext())),
307 emulation_handler_(nullptr),
308 frame_trace_recorder_(nullptr),
309 protocol_handler_(new DevToolsProtocolHandler(
310 this,
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());
334 SetPending(host);
335 CommitPending();
336 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host));
338 g_instances.Get().push_back(this);
339 AddRef(); // Balanced in RenderFrameHostDestroyed.
342 void RenderFrameDevToolsAgentHost::SetPending(RenderFrameHostImpl* host) {
343 DCHECK(!pending_);
344 current_frame_crashed_ = false;
345 pending_.reset(new FrameHostHolder(this, host));
346 if (IsAttached())
347 pending_->Reattach(current_.get());
349 // Can only be null in constructor.
350 if (current_)
351 current_->Suspend();
352 pending_->Suspend();
354 UpdateProtocolHandlers(host);
357 void RenderFrameDevToolsAgentHost::CommitPending() {
358 DCHECK(pending_);
359 current_frame_crashed_ = false;
361 if (!ShouldCreateDevToolsFor(pending_->host())) {
362 DestroyOnRenderFrameGone();
363 // |this| may be deleted at this point.
364 return;
367 current_ = pending_.Pass();
368 UpdateProtocolHandlers(current_->host());
369 current_->Resume();
372 void RenderFrameDevToolsAgentHost::DiscardPending() {
373 DCHECK(pending_);
374 DCHECK(current_);
375 pending_.reset();
376 UpdateProtocolHandlers(current_->host());
377 current_->Resume();
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() {
390 if (current_)
391 current_->Attach();
392 if (pending_)
393 pending_->Attach();
394 OnClientAttached();
397 void RenderFrameDevToolsAgentHost::Detach() {
398 if (current_)
399 current_->Detach();
400 if (pending_)
401 pending_->Detach();
402 OnClientDetached();
405 bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
406 const std::string& message) {
407 int call_id = 0;
408 if (protocol_handler_->HandleOptionalMessage(message, &call_id))
409 return true;
411 if (current_)
412 current_->DispatchProtocolMessage(call_id, message);
413 if (pending_)
414 pending_->DispatchProtocolMessage(call_id, message);
415 return true;
418 void RenderFrameDevToolsAgentHost::InspectElement(int x, int y) {
419 if (current_)
420 current_->InspectElement(x, y);
421 if (pending_)
422 pending_->InspectElement(x, y);
425 void RenderFrameDevToolsAgentHost::OnClientAttached() {
426 if (!web_contents())
427 return;
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());
437 #endif
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();
447 #endif
448 if (emulation_handler_)
449 emulation_handler_->Detached();
450 if (page_handler_)
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(),
465 this);
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)
476 return;
477 if (old_host == new_host && !current_frame_crashed_)
478 return;
479 DCHECK(!pending_);
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)
488 return;
490 // AboutToNavigateRenderFrame was not called for renderer-initiated
491 // navigation.
492 if (!pending_)
493 SetPending(static_cast<RenderFrameHostImpl*>(new_host));
495 CommitPending();
498 void RenderFrameDevToolsAgentHost::FrameDeleted(RenderFrameHost* rfh) {
499 if (pending_ && pending_->host() == rfh) {
500 DiscardPending();
501 return;
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_)
510 FrameDeleted(rfh);
513 void RenderFrameDevToolsAgentHost::DestroyOnRenderFrameGone() {
514 DCHECK(current_);
515 scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
516 UpdateProtocolHandlers(nullptr);
517 if (IsAttached())
518 OnClientDetached();
519 HostClosed();
520 pending_.reset();
521 current_.reset();
522 Release();
525 void RenderFrameDevToolsAgentHost::RenderProcessGone(
526 base::TerminationStatus status) {
527 switch(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:
532 #endif
533 case base::TERMINATION_STATUS_PROCESS_CRASHED:
534 #if defined(OS_ANDROID)
535 case base::TERMINATION_STATUS_OOM_PROTECTED:
536 #endif
537 case base::TERMINATION_STATUS_LAUNCH_FAILED:
538 inspector_handler_->TargetCrashed();
539 current_frame_crashed_ = true;
540 break;
541 default:
542 inspector_handler_->TargetDetached("Render process gone.");
543 break;
547 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
548 const IPC::Message& message) {
549 if (!current_)
550 return false;
551 if (message.type() == ViewHostMsg_SwapCompositorFrame::ID)
552 OnSwapCompositorFrame(message);
553 return false;
556 bool RenderFrameDevToolsAgentHost::OnMessageReceived(
557 const IPC::Message& message,
558 RenderFrameHost* render_frame_host) {
559 if (message.type() != DevToolsClientMsg_DispatchOnInspectorFrontend::ID)
560 return false;
561 if (!IsAttached())
562 return false;
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();
569 if (!holder)
570 return false;
572 DevToolsClientMsg_DispatchOnInspectorFrontend::Param param;
573 if (!DevToolsClientMsg_DispatchOnInspectorFrontend::Read(&message, &param))
574 return false;
575 holder->ProcessChunkedMessageFromAgent(base::get<0>(param));
576 return true;
579 void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() {
580 if (page_handler_)
581 page_handler_->DidAttachInterstitialPage();
583 // TODO(dgozman): this may break for cross-process subframes.
584 if (!pending_)
585 return;
586 // Pending set in AboutToNavigateRenderFrame turned out to be interstitial.
587 // Connect back to the real one.
588 DiscardPending();
591 void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() {
592 if (page_handler_)
593 page_handler_->DidDetachInterstitialPage();
596 void RenderFrameDevToolsAgentHost::DidCommitProvisionalLoadForFrame(
597 RenderFrameHost* render_frame_host,
598 const GURL& url,
599 ui::PageTransition transition_type) {
600 if (pending_ && pending_->host() == render_frame_host)
601 CommitPending();
602 service_worker_handler_->UpdateHosts();
605 void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
606 RenderFrameHost* render_frame_host,
607 const GURL& validated_url,
608 int error_code,
609 const base::string16& error_description,
610 bool was_ignored_by_handler) {
611 if (pending_ && pending_->host() == render_frame_host)
612 DiscardPending();
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);
624 if (page_handler_)
625 page_handler_->SetRenderFrameHost(host);
626 service_worker_handler_->SetRenderFrameHost(host);
627 if (security_handler_)
628 security_handler_->SetRenderFrameHost(host);
631 void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
632 if (pending_)
633 DiscardPending();
634 UpdateProtocolHandlers(nullptr);
635 disconnected_ = current_.Pass();
636 WebContentsObserver::Observe(nullptr);
639 void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
640 DCHECK(!current_);
641 DCHECK(!pending_);
642 RenderFrameHostImpl* host =
643 static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
644 DCHECK(host);
645 current_ = disconnected_.Pass();
646 SetPending(host);
647 CommitPending();
648 WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host));
651 DevToolsAgentHost::Type RenderFrameDevToolsAgentHost::GetType() {
652 return IsChildFrame() ? TYPE_FRAME : TYPE_WEB_CONTENTS;
655 std::string RenderFrameDevToolsAgentHost::GetTitle() {
656 if (IsChildFrame())
657 return GetURL().spec();
658 if (WebContents* web_contents = GetWebContents())
659 return base::UTF16ToUTF8(web_contents->GetTitle());
660 return "";
663 GURL RenderFrameDevToolsAgentHost::GetURL() {
664 // Order is important here.
665 WebContents* web_contents = GetWebContents();
666 if (web_contents && !IsChildFrame())
667 return web_contents->GetVisibleURL();
668 if (pending_)
669 return pending_->host()->GetLastCommittedURL();
670 if (current_)
671 return current_->host()->GetLastCommittedURL();
672 return GURL();
675 bool RenderFrameDevToolsAgentHost::Activate() {
676 WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents());
677 if (wc) {
678 wc->Activate();
679 return true;
681 return false;
684 bool RenderFrameDevToolsAgentHost::Close() {
685 if (web_contents()) {
686 web_contents()->ClosePage();
687 return true;
689 return false;
692 void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame(
693 const IPC::Message& message) {
694 ViewHostMsg_SwapCompositorFrame::Param param;
695 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
696 return;
697 if (page_handler_)
698 page_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
699 if (input_handler_)
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) {
710 if (page_handler_)
711 page_handler_->OnSynchronousSwapCompositorFrame(frame_metadata);
712 if (input_handler_)
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,
717 frame_metadata);
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