1 // Copyright 2013 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 "chrome/browser/devtools/devtools_target_impl.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/devtools/devtools_window.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_tab_util.h"
12 #include "chrome/browser/guest_view/guest_view_base.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
15 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
16 #include "chrome/common/extensions/extension_constants.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/favicon_status.h"
19 #include "content/public/browser/navigation_entry.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
23 #include "extensions/browser/extension_host.h"
24 #include "extensions/browser/extension_system.h"
25 #include "extensions/common/constants.h"
27 using content::BrowserThread
;
28 using content::DevToolsAgentHost
;
29 using content::RenderViewHost
;
30 using content::WebContents
;
31 using content::WorkerService
;
35 const char kTargetTypeApp
[] = "app";
36 const char kTargetTypeBackgroundPage
[] = "background_page";
37 const char kTargetTypePage
[] = "page";
38 const char kTargetTypeWorker
[] = "worker";
39 const char kTargetTypeWebView
[] = "webview";
40 const char kTargetTypeIFrame
[] = "iframe";
41 const char kTargetTypeOther
[] = "other";
43 // RenderViewHostTarget --------------------------------------------------------
45 class RenderViewHostTarget
: public DevToolsTargetImpl
{
47 explicit RenderViewHostTarget(RenderViewHost
* rvh
, bool is_tab
);
49 // DevToolsTargetImpl overrides:
50 virtual bool Activate() const OVERRIDE
;
51 virtual bool Close() const OVERRIDE
;
52 virtual RenderViewHost
* GetRenderViewHost() const OVERRIDE
;
53 virtual int GetTabId() const OVERRIDE
;
54 virtual std::string
GetExtensionId() const OVERRIDE
;
55 virtual void Inspect(Profile
* profile
) const OVERRIDE
;
59 std::string extension_id_
;
62 RenderViewHostTarget::RenderViewHostTarget(RenderViewHost
* rvh
, bool is_tab
)
63 : DevToolsTargetImpl(DevToolsAgentHost::GetOrCreateFor(rvh
)),
65 set_type(kTargetTypeOther
);
66 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
68 return; // Orphan RVH will show up with no title/url/icon in clients.
70 content::RenderFrameHost
* rfh
= rvh
->GetMainFrame();
71 if (rfh
->IsCrossProcessSubframe()) {
72 set_url(rfh
->GetLastCommittedURL());
73 set_type(kTargetTypeIFrame
);
74 // TODO(kaznacheev) Try setting the title when the frame navigation
75 // refactoring is done.
76 RenderViewHost
* parent_rvh
= rfh
->GetParent()->GetRenderViewHost();
77 set_parent_id(DevToolsAgentHost::GetOrCreateFor(parent_rvh
)->GetId());
81 set_title(base::UTF16ToUTF8(web_contents
->GetTitle()));
82 set_url(web_contents
->GetURL());
83 content::NavigationController
& controller
= web_contents
->GetController();
84 content::NavigationEntry
* entry
= controller
.GetActiveEntry();
85 if (entry
!= NULL
&& entry
->GetURL().is_valid())
86 set_favicon_url(entry
->GetFavicon().url
);
87 set_last_activity_time(web_contents
->GetLastActiveTime());
89 GuestViewBase
* guest
= GuestViewBase::FromWebContents(web_contents
);
91 set_type(kTargetTypeWebView
);
92 RenderViewHost
* parent_rvh
=
93 guest
->embedder_web_contents()->GetRenderViewHost();
94 set_parent_id(DevToolsAgentHost::GetOrCreateFor(parent_rvh
)->GetId());
99 set_type(kTargetTypePage
);
100 tab_id_
= extensions::ExtensionTabUtil::GetTabId(web_contents
);
103 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
105 ExtensionService
* extension_service
= profile
->GetExtensionService();
106 const extensions::Extension
* extension
= extension_service
->
107 extensions()->GetByID(GetURL().host());
109 set_title(extension
->name());
110 extensions::ExtensionHost
* extension_host
=
111 extensions::ExtensionSystem::Get(profile
)->process_manager()->
112 GetBackgroundHostForExtension(extension
->id());
113 if (extension_host
&&
114 extension_host
->host_contents() == web_contents
) {
115 set_type(kTargetTypeBackgroundPage
);
116 extension_id_
= extension
->id();
117 } else if (extension
->is_hosted_app()
118 || extension
->is_legacy_packaged_app()
119 || extension
->is_platform_app()) {
120 set_type(kTargetTypeApp
);
122 set_favicon_url(extensions::ExtensionIconSource::GetIconURL(
123 extension
, extension_misc::EXTENSION_ICON_SMALLISH
,
124 ExtensionIconSet::MATCH_BIGGER
, false, NULL
));
130 bool RenderViewHostTarget::Activate() const {
131 RenderViewHost
* rvh
= GetRenderViewHost();
134 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
137 web_contents
->GetDelegate()->ActivateContents(web_contents
);
141 bool RenderViewHostTarget::Close() const {
142 RenderViewHost
* rvh
= GetRenderViewHost();
149 RenderViewHost
* RenderViewHostTarget::GetRenderViewHost() const {
150 return GetAgentHost()->GetRenderViewHost();
153 int RenderViewHostTarget::GetTabId() const {
157 std::string
RenderViewHostTarget::GetExtensionId() const {
158 return extension_id_
;
161 void RenderViewHostTarget::Inspect(Profile
* profile
) const {
162 RenderViewHost
* rvh
= GetRenderViewHost();
165 DevToolsWindow::OpenDevToolsWindow(rvh
);
168 // WorkerTarget ----------------------------------------------------------------
170 class WorkerTarget
: public DevToolsTargetImpl
{
172 explicit WorkerTarget(const WorkerService::WorkerInfo
& worker_info
);
174 // content::DevToolsTarget overrides:
175 virtual bool Close() const OVERRIDE
;
177 // DevToolsTargetImpl overrides:
178 virtual void Inspect(Profile
* profile
) const OVERRIDE
;
185 WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo
& worker
)
186 : DevToolsTargetImpl(DevToolsAgentHost::GetForWorker(worker
.process_id
,
188 set_type(kTargetTypeWorker
);
189 set_title(base::UTF16ToUTF8(worker
.name
));
190 set_description(base::StringPrintf("Worker pid:%d",
191 base::GetProcId(worker
.handle
)));
194 process_id_
= worker
.process_id
;
195 route_id_
= worker
.route_id
;
198 static void TerminateWorker(int process_id
, int route_id
) {
199 WorkerService::GetInstance()->TerminateWorker(process_id
, route_id
);
202 bool WorkerTarget::Close() const {
203 content::BrowserThread::PostTask(content::BrowserThread::IO
, FROM_HERE
,
204 base::Bind(&TerminateWorker
, process_id_
, route_id_
));
208 void WorkerTarget::Inspect(Profile
* profile
) const {
209 DevToolsWindow::OpenDevToolsWindowForWorker(profile
, GetAgentHost());
214 // DevToolsTargetImpl ----------------------------------------------------------
216 DevToolsTargetImpl::~DevToolsTargetImpl() {
219 DevToolsTargetImpl::DevToolsTargetImpl(
220 scoped_refptr
<DevToolsAgentHost
> agent_host
)
221 : agent_host_(agent_host
) {
224 std::string
DevToolsTargetImpl::GetParentId() const {
228 std::string
DevToolsTargetImpl::GetId() const {
229 return agent_host_
->GetId();
232 std::string
DevToolsTargetImpl::GetType() const {
236 std::string
DevToolsTargetImpl::GetTitle() const {
240 std::string
DevToolsTargetImpl::GetDescription() const {
244 GURL
DevToolsTargetImpl::GetURL() const {
248 GURL
DevToolsTargetImpl::GetFaviconURL() const {
252 base::TimeTicks
DevToolsTargetImpl::GetLastActivityTime() const {
253 return last_activity_time_
;
256 scoped_refptr
<content::DevToolsAgentHost
>
257 DevToolsTargetImpl::GetAgentHost() const {
261 bool DevToolsTargetImpl::IsAttached() const {
262 return agent_host_
->IsAttached();
265 bool DevToolsTargetImpl::Activate() const {
269 bool DevToolsTargetImpl::Close() const {
273 int DevToolsTargetImpl::GetTabId() const {
277 RenderViewHost
* DevToolsTargetImpl::GetRenderViewHost() const {
281 std::string
DevToolsTargetImpl::GetExtensionId() const {
282 return std::string();
285 void DevToolsTargetImpl::Inspect(Profile
*) const {
288 void DevToolsTargetImpl::Reload() const {
292 scoped_ptr
<DevToolsTargetImpl
> DevToolsTargetImpl::CreateForRenderViewHost(
293 content::RenderViewHost
* rvh
, bool is_tab
) {
294 return scoped_ptr
<DevToolsTargetImpl
>(new RenderViewHostTarget(rvh
, is_tab
));
298 DevToolsTargetImpl::List
DevToolsTargetImpl::EnumerateRenderViewHostTargets() {
299 std::set
<RenderViewHost
*> tab_rvhs
;
300 for (TabContentsIterator it
; !it
.done(); it
.Next())
301 tab_rvhs
.insert(it
->GetRenderViewHost());
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
304 DevToolsTargetImpl::List result
;
305 std::vector
<RenderViewHost
*> rvh_list
=
306 content::DevToolsAgentHost::GetValidRenderViewHosts();
307 for (std::vector
<RenderViewHost
*>::iterator it
= rvh_list
.begin();
308 it
!= rvh_list
.end(); ++it
) {
309 bool is_tab
= tab_rvhs
.find(*it
) != tab_rvhs
.end();
310 result
.push_back(new RenderViewHostTarget(*it
, is_tab
));
315 static void CreateWorkerTargets(
316 const std::vector
<WorkerService::WorkerInfo
>& worker_info
,
317 DevToolsTargetImpl::Callback callback
) {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
319 DevToolsTargetImpl::List result
;
320 for (size_t i
= 0; i
< worker_info
.size(); ++i
) {
321 result
.push_back(new WorkerTarget(worker_info
[i
]));
323 callback
.Run(result
);
327 void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback
) {
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
329 content::BrowserThread::PostTask(
330 content::BrowserThread::UI
,
332 base::Bind(&CreateWorkerTargets
,
333 WorkerService::GetInstance()->GetWorkers(),
337 static void CollectAllTargets(
338 DevToolsTargetImpl::Callback callback
,
339 const DevToolsTargetImpl::List
& worker_targets
) {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
341 DevToolsTargetImpl::List result
=
342 DevToolsTargetImpl::EnumerateRenderViewHostTargets();
343 result
.insert(result
.begin(), worker_targets
.begin(), worker_targets
.end());
344 callback
.Run(result
);
348 void DevToolsTargetImpl::EnumerateAllTargets(Callback callback
) {
349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
350 content::BrowserThread::PostTask(
351 content::BrowserThread::IO
,
353 base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets
,
354 base::Bind(&CollectAllTargets
, callback
)));