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_host.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
16 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
17 #include "chrome/common/extensions/extension_constants.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/favicon_status.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
24 using content::BrowserThread
;
25 using content::DevToolsAgentHost
;
26 using content::RenderViewHost
;
27 using content::WebContents
;
28 using content::WorkerService
;
32 const char kTargetTypeApp
[] = "app";
33 const char kTargetTypeBackgroundPage
[] = "background_page";
34 const char kTargetTypePage
[] = "page";
35 const char kTargetTypeWorker
[] = "worker";
36 const char kTargetTypeOther
[] = "other";
38 class RenderViewHostTarget
: public DevToolsTargetImpl
{
40 explicit RenderViewHostTarget(RenderViewHost
* rvh
, bool is_tab
);
42 // content::DevToolsTarget overrides:
43 virtual bool Activate() const OVERRIDE
;
44 virtual bool Close() const OVERRIDE
;
46 // DevToolsTargetImpl overrides:
47 virtual RenderViewHost
* GetRenderViewHost() const OVERRIDE
;
48 virtual int GetTabId() const OVERRIDE
;
49 virtual std::string
GetExtensionId() const OVERRIDE
;
50 virtual void Inspect(Profile
* profile
) const OVERRIDE
;
54 std::string extension_id_
;
57 RenderViewHostTarget::RenderViewHostTarget(RenderViewHost
* rvh
, bool is_tab
) {
58 agent_host_
= DevToolsAgentHost::GetOrCreateFor(rvh
);
59 id_
= agent_host_
->GetId();
60 type_
= kTargetTypeOther
;
63 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
65 return; // Orphan RVH will show up with no title/url/icon in clients.
67 title_
= base::UTF16ToUTF8(web_contents
->GetTitle());
68 url_
= web_contents
->GetURL();
69 content::NavigationController
& controller
= web_contents
->GetController();
70 content::NavigationEntry
* entry
= controller
.GetActiveEntry();
71 if (entry
!= NULL
&& entry
->GetURL().is_valid())
72 favicon_url_
= entry
->GetFavicon().url
;
73 last_activity_time_
= web_contents
->GetLastSelectedTime();
76 type_
= kTargetTypePage
;
77 tab_id_
= extensions::ExtensionTabUtil::GetTabId(web_contents
);
80 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
82 ExtensionService
* extension_service
= profile
->GetExtensionService();
83 const extensions::Extension
* extension
= extension_service
->
84 extensions()->GetByID(url_
.host());
86 title_
= extension
->name();
87 extensions::ExtensionHost
* extension_host
=
88 extensions::ExtensionSystem::Get(profile
)->process_manager()->
89 GetBackgroundHostForExtension(extension
->id());
91 extension_host
->host_contents() == web_contents
) {
92 type_
= kTargetTypeBackgroundPage
;
93 extension_id_
= extension
->id();
94 } else if (extension
->is_hosted_app()
95 || extension
->is_legacy_packaged_app()
96 || extension
->is_platform_app()) {
97 type_
= kTargetTypeApp
;
99 favicon_url_
= extensions::ExtensionIconSource::GetIconURL(
100 extension
, extension_misc::EXTENSION_ICON_SMALLISH
,
101 ExtensionIconSet::MATCH_BIGGER
, false, NULL
);
107 bool RenderViewHostTarget::Activate() const {
108 RenderViewHost
* rvh
= GetRenderViewHost();
111 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
114 web_contents
->GetDelegate()->ActivateContents(web_contents
);
118 bool RenderViewHostTarget::Close() const {
119 RenderViewHost
* rvh
= GetRenderViewHost();
126 RenderViewHost
* RenderViewHostTarget::GetRenderViewHost() const {
127 return agent_host_
->GetRenderViewHost();
130 int RenderViewHostTarget::GetTabId() const {
134 std::string
RenderViewHostTarget::GetExtensionId() const {
135 return extension_id_
;
138 void RenderViewHostTarget::Inspect(Profile
* profile
) const {
139 RenderViewHost
* rvh
= GetRenderViewHost();
142 DevToolsWindow::OpenDevToolsWindow(rvh
);
145 ///////////////////////////////////////////////////////////////////////////////
147 class WorkerTarget
: public DevToolsTargetImpl
{
149 explicit WorkerTarget(const WorkerService::WorkerInfo
& worker_info
);
151 // content::DevToolsTarget overrides:
152 virtual bool Close() const OVERRIDE
;
154 // DevToolsTargetImpl overrides:
155 virtual void Inspect(Profile
* profile
) const OVERRIDE
;
162 WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo
& worker
) {
164 DevToolsAgentHost::GetForWorker(worker
.process_id
, worker
.route_id
);
165 id_
= agent_host_
->GetId();
166 type_
= kTargetTypeWorker
;
167 title_
= base::UTF16ToUTF8(worker
.name
);
169 base::StringPrintf("Worker pid:%d", base::GetProcId(worker
.handle
));
172 process_id_
= worker
.process_id
;
173 route_id_
= worker
.route_id
;
176 static void TerminateWorker(int process_id
, int route_id
) {
177 WorkerService::GetInstance()->TerminateWorker(process_id
, route_id
);
180 bool WorkerTarget::Close() const {
181 content::BrowserThread::PostTask(content::BrowserThread::IO
, FROM_HERE
,
182 base::Bind(&TerminateWorker
, process_id_
, route_id_
));
186 void WorkerTarget::Inspect(Profile
* profile
) const {
187 DevToolsWindow::OpenDevToolsWindowForWorker(profile
, agent_host_
.get());
192 DevToolsTargetImpl::~DevToolsTargetImpl() {
195 DevToolsTargetImpl::DevToolsTargetImpl() {
198 std::string
DevToolsTargetImpl::GetId() const {
202 std::string
DevToolsTargetImpl::GetType() const {
206 std::string
DevToolsTargetImpl::GetTitle() const {
210 std::string
DevToolsTargetImpl::GetDescription() const {
214 GURL
DevToolsTargetImpl::GetUrl() const {
218 GURL
DevToolsTargetImpl::GetFaviconUrl() const {
222 base::TimeTicks
DevToolsTargetImpl::GetLastActivityTime() const {
223 return last_activity_time_
;
226 scoped_refptr
<content::DevToolsAgentHost
>
227 DevToolsTargetImpl::GetAgentHost() const {
231 bool DevToolsTargetImpl::IsAttached() const {
232 return agent_host_
->IsAttached();
235 bool DevToolsTargetImpl::Activate() const {
239 bool DevToolsTargetImpl::Close() const {
243 int DevToolsTargetImpl::GetTabId() const {
247 RenderViewHost
* DevToolsTargetImpl::GetRenderViewHost() const {
251 std::string
DevToolsTargetImpl::GetExtensionId() const {
252 return std::string();
255 void DevToolsTargetImpl::Inspect(Profile
*) const {
258 void DevToolsTargetImpl::Reload() const {
262 scoped_ptr
<DevToolsTargetImpl
> DevToolsTargetImpl::CreateForRenderViewHost(
263 content::RenderViewHost
* rvh
, bool is_tab
) {
264 return scoped_ptr
<DevToolsTargetImpl
>(new RenderViewHostTarget(rvh
, is_tab
));
268 scoped_ptr
<DevToolsTargetImpl
> DevToolsTargetImpl::CreateForWorker(
269 const WorkerService::WorkerInfo
& worker_info
) {
270 return scoped_ptr
<DevToolsTargetImpl
>(new WorkerTarget(worker_info
));
274 DevToolsTargetImpl::List
DevToolsTargetImpl::EnumerateRenderViewHostTargets() {
275 std::set
<RenderViewHost
*> tab_rvhs
;
276 for (TabContentsIterator it
; !it
.done(); it
.Next())
277 tab_rvhs
.insert(it
->GetRenderViewHost());
279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
280 DevToolsTargetImpl::List result
;
281 std::vector
<RenderViewHost
*> rvh_list
=
282 content::DevToolsAgentHost::GetValidRenderViewHosts();
283 for (std::vector
<RenderViewHost
*>::iterator it
= rvh_list
.begin();
284 it
!= rvh_list
.end(); ++it
) {
285 bool is_tab
= tab_rvhs
.find(*it
) != tab_rvhs
.end();
286 result
.push_back(new RenderViewHostTarget(*it
, is_tab
));
291 static void CreateWorkerTargets(
292 const std::vector
<WorkerService::WorkerInfo
>& worker_info
,
293 DevToolsTargetImpl::Callback callback
) {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
295 DevToolsTargetImpl::List result
;
296 for (size_t i
= 0; i
< worker_info
.size(); ++i
) {
297 result
.push_back(new WorkerTarget(worker_info
[i
]));
299 callback
.Run(result
);
303 void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback
) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
305 content::BrowserThread::PostTask(
306 content::BrowserThread::UI
,
308 base::Bind(&CreateWorkerTargets
,
309 WorkerService::GetInstance()->GetWorkers(),
313 static void CollectAllTargets(
314 DevToolsTargetImpl::Callback callback
,
315 const DevToolsTargetImpl::List
& worker_targets
) {
316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
317 DevToolsTargetImpl::List result
=
318 DevToolsTargetImpl::EnumerateRenderViewHostTargets();
319 result
.insert(result
.begin(), worker_targets
.begin(), worker_targets
.end());
320 callback
.Run(result
);
324 void DevToolsTargetImpl::EnumerateAllTargets(Callback callback
) {
325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
326 content::BrowserThread::PostTask(
327 content::BrowserThread::IO
,
329 base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets
,
330 base::Bind(&CollectAllTargets
, callback
)));