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)));