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);
90 WebContents* guest_contents = guest ? guest->embedder_web_contents() : NULL;
91 RenderViewHost* guest_parent_rvh =
92 guest_contents ? guest_contents->GetRenderViewHost() : NULL;
93 if (guest_parent_rvh) {
94 set_type(kTargetTypeWebView);
95 set_parent_id(DevToolsAgentHost::GetOrCreateFor(guest_parent_rvh)->GetId());
100 set_type(kTargetTypePage);
101 tab_id_ = extensions::ExtensionTabUtil::GetTabId(web_contents);
104 Profile::FromBrowserContext(web_contents->GetBrowserContext());
106 ExtensionService* extension_service = profile->GetExtensionService();
107 const extensions::Extension* extension = extension_service->
108 extensions()->GetByID(GetURL().host());
110 set_title(extension->name());
111 extensions::ExtensionHost* extension_host =
112 extensions::ExtensionSystem::Get(profile)->process_manager()->
113 GetBackgroundHostForExtension(extension->id());
114 if (extension_host &&
115 extension_host->host_contents() == web_contents) {
116 set_type(kTargetTypeBackgroundPage);
117 extension_id_ = extension->id();
118 } else if (extension->is_hosted_app()
119 || extension->is_legacy_packaged_app()
120 || extension->is_platform_app()) {
121 set_type(kTargetTypeApp);
123 set_favicon_url(extensions::ExtensionIconSource::GetIconURL(
124 extension, extension_misc::EXTENSION_ICON_SMALLISH,
125 ExtensionIconSet::MATCH_BIGGER, false, NULL));
131 bool RenderViewHostTarget::Activate() const {
132 RenderViewHost* rvh = GetRenderViewHost();
135 WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
138 web_contents->GetDelegate()->ActivateContents(web_contents);
142 bool RenderViewHostTarget::Close() const {
143 RenderViewHost* rvh = GetRenderViewHost();
150 RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const {
151 return GetAgentHost()->GetRenderViewHost();
154 int RenderViewHostTarget::GetTabId() const {
158 std::string RenderViewHostTarget::GetExtensionId() const {
159 return extension_id_;
162 void RenderViewHostTarget::Inspect(Profile* profile) const {
163 RenderViewHost* rvh = GetRenderViewHost();
166 DevToolsWindow::OpenDevToolsWindow(rvh);
169 // WorkerTarget ----------------------------------------------------------------
171 class WorkerTarget : public DevToolsTargetImpl {
173 explicit WorkerTarget(const WorkerService::WorkerInfo& worker_info);
175 // content::DevToolsTarget overrides:
176 virtual bool Close() const OVERRIDE;
178 // DevToolsTargetImpl overrides:
179 virtual void Inspect(Profile* profile) const OVERRIDE;
186 WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker)
187 : DevToolsTargetImpl(DevToolsAgentHost::GetForWorker(worker.process_id,
189 set_type(kTargetTypeWorker);
190 set_title(base::UTF16ToUTF8(worker.name));
191 set_description(base::StringPrintf("Worker pid:%d",
192 base::GetProcId(worker.handle)));
195 process_id_ = worker.process_id;
196 route_id_ = worker.route_id;
199 static void TerminateWorker(int process_id, int route_id) {
200 WorkerService::GetInstance()->TerminateWorker(process_id, route_id);
203 bool WorkerTarget::Close() const {
204 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
205 base::Bind(&TerminateWorker, process_id_, route_id_));
209 void WorkerTarget::Inspect(Profile* profile) const {
210 DevToolsWindow::OpenDevToolsWindowForWorker(profile, GetAgentHost());
215 // DevToolsTargetImpl ----------------------------------------------------------
217 DevToolsTargetImpl::~DevToolsTargetImpl() {
220 DevToolsTargetImpl::DevToolsTargetImpl(
221 scoped_refptr<DevToolsAgentHost> agent_host)
222 : agent_host_(agent_host) {
225 std::string DevToolsTargetImpl::GetParentId() const {
229 std::string DevToolsTargetImpl::GetId() const {
230 return agent_host_->GetId();
233 std::string DevToolsTargetImpl::GetType() const {
237 std::string DevToolsTargetImpl::GetTitle() const {
241 std::string DevToolsTargetImpl::GetDescription() const {
245 GURL DevToolsTargetImpl::GetURL() const {
249 GURL DevToolsTargetImpl::GetFaviconURL() const {
253 base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const {
254 return last_activity_time_;
257 scoped_refptr<content::DevToolsAgentHost>
258 DevToolsTargetImpl::GetAgentHost() const {
262 bool DevToolsTargetImpl::IsAttached() const {
263 return agent_host_->IsAttached();
266 bool DevToolsTargetImpl::Activate() const {
270 bool DevToolsTargetImpl::Close() const {
274 int DevToolsTargetImpl::GetTabId() const {
278 RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const {
282 std::string DevToolsTargetImpl::GetExtensionId() const {
283 return std::string();
286 void DevToolsTargetImpl::Inspect(Profile*) const {
289 void DevToolsTargetImpl::Reload() const {
293 scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost(
294 content::RenderViewHost* rvh, bool is_tab) {
295 return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab));
299 DevToolsTargetImpl::List DevToolsTargetImpl::EnumerateRenderViewHostTargets() {
300 std::set<RenderViewHost*> tab_rvhs;
301 for (TabContentsIterator it; !it.done(); it.Next())
302 tab_rvhs.insert(it->GetRenderViewHost());
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
305 DevToolsTargetImpl::List result;
306 std::vector<RenderViewHost*> rvh_list =
307 content::DevToolsAgentHost::GetValidRenderViewHosts();
308 for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
309 it != rvh_list.end(); ++it) {
310 bool is_tab = tab_rvhs.find(*it) != tab_rvhs.end();
311 result.push_back(new RenderViewHostTarget(*it, is_tab));
316 static void CreateWorkerTargets(
317 const std::vector<WorkerService::WorkerInfo>& worker_info,
318 DevToolsTargetImpl::Callback callback) {
319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
320 DevToolsTargetImpl::List result;
321 for (size_t i = 0; i < worker_info.size(); ++i) {
322 result.push_back(new WorkerTarget(worker_info[i]));
324 callback.Run(result);
328 void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) {
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330 content::BrowserThread::PostTask(
331 content::BrowserThread::UI,
333 base::Bind(&CreateWorkerTargets,
334 WorkerService::GetInstance()->GetWorkers(),
338 static void CollectAllTargets(
339 DevToolsTargetImpl::Callback callback,
340 const DevToolsTargetImpl::List& worker_targets) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 DevToolsTargetImpl::List result =
343 DevToolsTargetImpl::EnumerateRenderViewHostTargets();
344 result.insert(result.begin(), worker_targets.begin(), worker_targets.end());
345 callback.Run(result);
349 void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) {
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
351 content::BrowserThread::PostTask(
352 content::BrowserThread::IO,
354 base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets,
355 base::Bind(&CollectAllTargets, callback)));