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/profiles/profile.h"
13 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
14 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
15 #include "chrome/common/extensions/extension_constants.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/favicon_status.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "extensions/browser/extension_host.h"
23 #include "extensions/browser/extension_system.h"
25 using content::BrowserThread
;
26 using content::DevToolsAgentHost
;
27 using content::RenderViewHost
;
28 using content::WebContents
;
29 using content::WorkerService
;
33 const char kTargetTypeApp
[] = "app";
34 const char kTargetTypeBackgroundPage
[] = "background_page";
35 const char kTargetTypePage
[] = "page";
36 const char kTargetTypeWorker
[] = "worker";
37 const char kTargetTypeOther
[] = "other";
39 class RenderViewHostTarget
: public DevToolsTargetImpl
{
41 explicit RenderViewHostTarget(RenderViewHost
* rvh
, bool is_tab
);
43 // content::DevToolsTarget overrides:
44 virtual bool Activate() const OVERRIDE
;
45 virtual bool Close() const OVERRIDE
;
47 // DevToolsTargetImpl overrides:
48 virtual RenderViewHost
* GetRenderViewHost() const OVERRIDE
;
49 virtual int GetTabId() const OVERRIDE
;
50 virtual std::string
GetExtensionId() const OVERRIDE
;
51 virtual void Inspect(Profile
* profile
) const OVERRIDE
;
55 std::string extension_id_
;
58 RenderViewHostTarget::RenderViewHostTarget(RenderViewHost
* rvh
, bool is_tab
) {
59 agent_host_
= DevToolsAgentHost::GetOrCreateFor(rvh
);
60 id_
= agent_host_
->GetId();
61 type_
= kTargetTypeOther
;
64 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
66 return; // Orphan RVH will show up with no title/url/icon in clients.
68 content::RenderFrameHost
* rfh
= rvh
->GetMainFrame();
69 if (rfh
->IsCrossProcessSubframe()) {
70 url_
= rfh
->GetLastCommittedURL();
71 type_
= kTargetTypeOther
;
72 // TODO(kaznacheev) Try setting the title when the frame navigation
73 // refactoring is done.
77 title_
= base::UTF16ToUTF8(web_contents
->GetTitle());
78 url_
= web_contents
->GetURL();
79 content::NavigationController
& controller
= web_contents
->GetController();
80 content::NavigationEntry
* entry
= controller
.GetActiveEntry();
81 if (entry
!= NULL
&& entry
->GetURL().is_valid())
82 favicon_url_
= entry
->GetFavicon().url
;
83 last_activity_time_
= web_contents
->GetLastActiveTime();
86 type_
= kTargetTypePage
;
87 tab_id_
= extensions::ExtensionTabUtil::GetTabId(web_contents
);
90 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
92 ExtensionService
* extension_service
= profile
->GetExtensionService();
93 const extensions::Extension
* extension
= extension_service
->
94 extensions()->GetByID(url_
.host());
96 title_
= extension
->name();
97 extensions::ExtensionHost
* extension_host
=
98 extensions::ExtensionSystem::Get(profile
)->process_manager()->
99 GetBackgroundHostForExtension(extension
->id());
100 if (extension_host
&&
101 extension_host
->host_contents() == web_contents
) {
102 type_
= kTargetTypeBackgroundPage
;
103 extension_id_
= extension
->id();
104 } else if (extension
->is_hosted_app()
105 || extension
->is_legacy_packaged_app()
106 || extension
->is_platform_app()) {
107 type_
= kTargetTypeApp
;
109 favicon_url_
= extensions::ExtensionIconSource::GetIconURL(
110 extension
, extension_misc::EXTENSION_ICON_SMALLISH
,
111 ExtensionIconSet::MATCH_BIGGER
, false, NULL
);
117 bool RenderViewHostTarget::Activate() const {
118 RenderViewHost
* rvh
= GetRenderViewHost();
121 WebContents
* web_contents
= WebContents::FromRenderViewHost(rvh
);
124 web_contents
->GetDelegate()->ActivateContents(web_contents
);
128 bool RenderViewHostTarget::Close() const {
129 RenderViewHost
* rvh
= GetRenderViewHost();
136 RenderViewHost
* RenderViewHostTarget::GetRenderViewHost() const {
137 return agent_host_
->GetRenderViewHost();
140 int RenderViewHostTarget::GetTabId() const {
144 std::string
RenderViewHostTarget::GetExtensionId() const {
145 return extension_id_
;
148 void RenderViewHostTarget::Inspect(Profile
* profile
) const {
149 RenderViewHost
* rvh
= GetRenderViewHost();
152 DevToolsWindow::OpenDevToolsWindow(rvh
);
155 ///////////////////////////////////////////////////////////////////////////////
157 class WorkerTarget
: public DevToolsTargetImpl
{
159 explicit WorkerTarget(const WorkerService::WorkerInfo
& worker_info
);
161 // content::DevToolsTarget overrides:
162 virtual bool Close() const OVERRIDE
;
164 // DevToolsTargetImpl overrides:
165 virtual void Inspect(Profile
* profile
) const OVERRIDE
;
172 WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo
& worker
) {
174 DevToolsAgentHost::GetForWorker(worker
.process_id
, worker
.route_id
);
175 id_
= agent_host_
->GetId();
176 type_
= kTargetTypeWorker
;
177 title_
= base::UTF16ToUTF8(worker
.name
);
179 base::StringPrintf("Worker pid:%d", base::GetProcId(worker
.handle
));
182 process_id_
= worker
.process_id
;
183 route_id_
= worker
.route_id
;
186 static void TerminateWorker(int process_id
, int route_id
) {
187 WorkerService::GetInstance()->TerminateWorker(process_id
, route_id
);
190 bool WorkerTarget::Close() const {
191 content::BrowserThread::PostTask(content::BrowserThread::IO
, FROM_HERE
,
192 base::Bind(&TerminateWorker
, process_id_
, route_id_
));
196 void WorkerTarget::Inspect(Profile
* profile
) const {
197 DevToolsWindow::OpenDevToolsWindowForWorker(profile
, agent_host_
.get());
202 DevToolsTargetImpl::~DevToolsTargetImpl() {
205 DevToolsTargetImpl::DevToolsTargetImpl() {
208 std::string
DevToolsTargetImpl::GetId() const {
212 std::string
DevToolsTargetImpl::GetType() const {
216 std::string
DevToolsTargetImpl::GetTitle() const {
220 std::string
DevToolsTargetImpl::GetDescription() const {
224 GURL
DevToolsTargetImpl::GetUrl() const {
228 GURL
DevToolsTargetImpl::GetFaviconUrl() const {
232 base::TimeTicks
DevToolsTargetImpl::GetLastActivityTime() const {
233 return last_activity_time_
;
236 scoped_refptr
<content::DevToolsAgentHost
>
237 DevToolsTargetImpl::GetAgentHost() const {
241 bool DevToolsTargetImpl::IsAttached() const {
242 return agent_host_
->IsAttached();
245 bool DevToolsTargetImpl::Activate() const {
249 bool DevToolsTargetImpl::Close() const {
253 int DevToolsTargetImpl::GetTabId() const {
257 RenderViewHost
* DevToolsTargetImpl::GetRenderViewHost() const {
261 std::string
DevToolsTargetImpl::GetExtensionId() const {
262 return std::string();
265 void DevToolsTargetImpl::Inspect(Profile
*) const {
268 void DevToolsTargetImpl::Reload() const {
272 scoped_ptr
<DevToolsTargetImpl
> DevToolsTargetImpl::CreateForRenderViewHost(
273 content::RenderViewHost
* rvh
, bool is_tab
) {
274 return scoped_ptr
<DevToolsTargetImpl
>(new RenderViewHostTarget(rvh
, is_tab
));
278 DevToolsTargetImpl::List
DevToolsTargetImpl::EnumerateRenderViewHostTargets() {
279 std::set
<RenderViewHost
*> tab_rvhs
;
280 for (TabContentsIterator it
; !it
.done(); it
.Next())
281 tab_rvhs
.insert(it
->GetRenderViewHost());
283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
284 DevToolsTargetImpl::List result
;
285 std::vector
<RenderViewHost
*> rvh_list
=
286 content::DevToolsAgentHost::GetValidRenderViewHosts();
287 for (std::vector
<RenderViewHost
*>::iterator it
= rvh_list
.begin();
288 it
!= rvh_list
.end(); ++it
) {
289 bool is_tab
= tab_rvhs
.find(*it
) != tab_rvhs
.end();
290 result
.push_back(new RenderViewHostTarget(*it
, is_tab
));
295 static void CreateWorkerTargets(
296 const std::vector
<WorkerService::WorkerInfo
>& worker_info
,
297 DevToolsTargetImpl::Callback callback
) {
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
299 DevToolsTargetImpl::List result
;
300 for (size_t i
= 0; i
< worker_info
.size(); ++i
) {
301 result
.push_back(new WorkerTarget(worker_info
[i
]));
303 callback
.Run(result
);
307 void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback
) {
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
309 content::BrowserThread::PostTask(
310 content::BrowserThread::UI
,
312 base::Bind(&CreateWorkerTargets
,
313 WorkerService::GetInstance()->GetWorkers(),
317 static void CollectAllTargets(
318 DevToolsTargetImpl::Callback callback
,
319 const DevToolsTargetImpl::List
& worker_targets
) {
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
321 DevToolsTargetImpl::List result
=
322 DevToolsTargetImpl::EnumerateRenderViewHostTargets();
323 result
.insert(result
.begin(), worker_targets
.begin(), worker_targets
.end());
324 callback
.Run(result
);
328 void DevToolsTargetImpl::EnumerateAllTargets(Callback callback
) {
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
330 content::BrowserThread::PostTask(
331 content::BrowserThread::IO
,
333 base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets
,
334 base::Bind(&CollectAllTargets
, callback
)));