devtools_target_impl.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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.
4
5#include "chrome/browser/devtools/devtools_target_impl.h"
6
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_tab_util.h"
11#include "chrome/browser/guest_view/guest_view_base.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_registry.h"
24#include "extensions/browser/extension_system.h"
25#include "extensions/browser/process_manager.h"
26#include "extensions/common/constants.h"
27
28using content::BrowserThread;
29using content::DevToolsAgentHost;
30using content::RenderViewHost;
31using content::WebContents;
32using content::WorkerService;
33
34namespace {
35
36const char kTargetTypeApp[] = "app";
37const char kTargetTypeBackgroundPage[] = "background_page";
38const char kTargetTypePage[] = "page";
39const char kTargetTypeWorker[] = "worker";
40const char kTargetTypeWebView[] = "webview";
41const char kTargetTypeIFrame[] = "iframe";
42const char kTargetTypeOther[] = "other";
43
44// RenderViewHostTarget --------------------------------------------------------
45
46class RenderViewHostTarget : public DevToolsTargetImpl {
47 public:
48  explicit RenderViewHostTarget(RenderViewHost* rvh, bool is_tab);
49
50  // DevToolsTargetImpl overrides:
51  virtual bool Activate() const OVERRIDE;
52  virtual bool Close() const OVERRIDE;
53  virtual RenderViewHost* GetRenderViewHost() const OVERRIDE;
54  virtual int GetTabId() const OVERRIDE;
55  virtual std::string GetExtensionId() const OVERRIDE;
56  virtual void Inspect(Profile* profile) const OVERRIDE;
57
58 private:
59  int tab_id_;
60  std::string extension_id_;
61};
62
63RenderViewHostTarget::RenderViewHostTarget(RenderViewHost* rvh, bool is_tab)
64    : DevToolsTargetImpl(DevToolsAgentHost::GetOrCreateFor(rvh)),
65      tab_id_(-1) {
66  set_type(kTargetTypeOther);
67  WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
68  if (!web_contents)
69    return;  // Orphan RVH will show up with no title/url/icon in clients.
70
71  content::RenderFrameHost* rfh = rvh->GetMainFrame();
72  if (rfh->IsCrossProcessSubframe()) {
73    set_url(rfh->GetLastCommittedURL());
74    set_type(kTargetTypeIFrame);
75    // TODO(kaznacheev) Try setting the title when the frame navigation
76    // refactoring is done.
77    RenderViewHost* parent_rvh = rfh->GetParent()->GetRenderViewHost();
78    set_parent_id(DevToolsAgentHost::GetOrCreateFor(parent_rvh)->GetId());
79    return;
80  }
81
82  set_title(base::UTF16ToUTF8(web_contents->GetTitle()));
83  set_url(web_contents->GetURL());
84  content::NavigationController& controller = web_contents->GetController();
85  content::NavigationEntry* entry = controller.GetActiveEntry();
86  if (entry != NULL && entry->GetURL().is_valid())
87    set_favicon_url(entry->GetFavicon().url);
88  set_last_activity_time(web_contents->GetLastActiveTime());
89
90  GuestViewBase* guest = GuestViewBase::FromWebContents(web_contents);
91  WebContents* guest_contents = guest ? guest->embedder_web_contents() : NULL;
92  RenderViewHost* guest_parent_rvh =
93      guest_contents ? guest_contents->GetRenderViewHost() : NULL;
94  if (guest_parent_rvh) {
95    set_type(kTargetTypeWebView);
96    set_parent_id(DevToolsAgentHost::GetOrCreateFor(guest_parent_rvh)->GetId());
97    return;
98  }
99
100  if (is_tab) {
101    set_type(kTargetTypePage);
102    tab_id_ = extensions::ExtensionTabUtil::GetTabId(web_contents);
103    return;
104  }
105
106  const extensions::Extension* extension = extensions::ExtensionRegistry::Get(
107      web_contents->GetBrowserContext())->enabled_extensions().GetByID(
108          GetURL().host());
109  if (!extension)
110    return;
111
112  Profile* profile =
113      Profile::FromBrowserContext(web_contents->GetBrowserContext());
114  if (!profile)
115    return;
116  extensions::ExtensionSystem* extension_system =
117      extensions::ExtensionSystem::Get(profile);
118  set_title(extension->name());
119  extensions::ExtensionHost* extension_host =
120      extension_system->process_manager()->GetBackgroundHostForExtension(
121          extension->id());
122  if (extension_host &&
123      extension_host->host_contents() == web_contents) {
124    set_type(kTargetTypeBackgroundPage);
125    extension_id_ = extension->id();
126  } else if (extension->is_hosted_app()
127             || extension->is_legacy_packaged_app()
128             || extension->is_platform_app()) {
129    set_type(kTargetTypeApp);
130  }
131  set_favicon_url(extensions::ExtensionIconSource::GetIconURL(
132      extension, extension_misc::EXTENSION_ICON_SMALLISH,
133      ExtensionIconSet::MATCH_BIGGER, false, NULL));
134}
135
136bool RenderViewHostTarget::Activate() const {
137  RenderViewHost* rvh = GetRenderViewHost();
138  if (!rvh)
139    return false;
140  WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
141  if (!web_contents)
142    return false;
143  web_contents->GetDelegate()->ActivateContents(web_contents);
144  return true;
145}
146
147bool RenderViewHostTarget::Close() const {
148  RenderViewHost* rvh = GetRenderViewHost();
149  if (!rvh)
150    return false;
151  rvh->ClosePage();
152  return true;
153}
154
155RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const {
156  return GetAgentHost()->GetRenderViewHost();
157}
158
159int RenderViewHostTarget::GetTabId() const {
160  return tab_id_;
161}
162
163std::string RenderViewHostTarget::GetExtensionId() const {
164  return extension_id_;
165}
166
167void RenderViewHostTarget::Inspect(Profile* profile) const {
168  RenderViewHost* rvh = GetRenderViewHost();
169  if (!rvh)
170    return;
171  DevToolsWindow::OpenDevToolsWindow(rvh);
172}
173
174// WorkerTarget ----------------------------------------------------------------
175
176class WorkerTarget : public DevToolsTargetImpl {
177 public:
178  explicit WorkerTarget(const WorkerService::WorkerInfo& worker_info);
179
180  // content::DevToolsTarget overrides:
181  virtual bool Close() const OVERRIDE;
182
183  // DevToolsTargetImpl overrides:
184  virtual void Inspect(Profile* profile) const OVERRIDE;
185
186 private:
187  int process_id_;
188  int route_id_;
189};
190
191WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker)
192    : DevToolsTargetImpl(DevToolsAgentHost::GetForWorker(worker.process_id,
193                                                         worker.route_id)) {
194  set_type(kTargetTypeWorker);
195  set_title(base::UTF16ToUTF8(worker.name));
196  set_description(base::StringPrintf("Worker pid:%d",
197                      base::GetProcId(worker.handle)));
198  set_url(worker.url);
199
200  process_id_ = worker.process_id;
201  route_id_ = worker.route_id;
202}
203
204static void TerminateWorker(int process_id, int route_id) {
205  WorkerService::GetInstance()->TerminateWorker(process_id, route_id);
206}
207
208bool WorkerTarget::Close() const {
209  content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
210      base::Bind(&TerminateWorker, process_id_, route_id_));
211  return true;
212}
213
214void WorkerTarget::Inspect(Profile* profile) const {
215  DevToolsWindow::OpenDevToolsWindowForWorker(profile, GetAgentHost());
216}
217
218}  // namespace
219
220// DevToolsTargetImpl ----------------------------------------------------------
221
222DevToolsTargetImpl::~DevToolsTargetImpl() {
223}
224
225DevToolsTargetImpl::DevToolsTargetImpl(
226    scoped_refptr<DevToolsAgentHost> agent_host)
227    : agent_host_(agent_host) {
228}
229
230std::string DevToolsTargetImpl::GetParentId() const {
231  return parent_id_;
232}
233
234std::string DevToolsTargetImpl::GetId() const {
235  return agent_host_->GetId();
236}
237
238std::string DevToolsTargetImpl::GetType() const {
239  return type_;
240}
241
242std::string DevToolsTargetImpl::GetTitle() const {
243  return title_;
244}
245
246std::string DevToolsTargetImpl::GetDescription() const {
247  return description_;
248}
249
250GURL DevToolsTargetImpl::GetURL() const {
251  return url_;
252}
253
254GURL DevToolsTargetImpl::GetFaviconURL() const {
255  return favicon_url_;
256}
257
258base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const {
259  return last_activity_time_;
260}
261
262scoped_refptr<content::DevToolsAgentHost>
263DevToolsTargetImpl::GetAgentHost() const {
264  return agent_host_;
265}
266
267bool DevToolsTargetImpl::IsAttached() const {
268  return agent_host_->IsAttached();
269}
270
271bool DevToolsTargetImpl::Activate() const {
272  return false;
273}
274
275bool DevToolsTargetImpl::Close() const {
276  return false;
277}
278
279int DevToolsTargetImpl::GetTabId() const {
280  return -1;
281}
282
283RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const {
284  return NULL;
285}
286
287std::string DevToolsTargetImpl::GetExtensionId() const {
288  return std::string();
289}
290
291void DevToolsTargetImpl::Inspect(Profile* /*profile*/) const {
292}
293
294void DevToolsTargetImpl::Reload() const {
295}
296
297// static
298scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost(
299    content::RenderViewHost* rvh, bool is_tab) {
300  return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab));
301}
302
303// static
304DevToolsTargetImpl::List DevToolsTargetImpl::EnumerateRenderViewHostTargets() {
305  std::set<RenderViewHost*> tab_rvhs;
306  for (TabContentsIterator it; !it.done(); it.Next())
307    tab_rvhs.insert(it->GetRenderViewHost());
308
309  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
310  DevToolsTargetImpl::List result;
311  std::vector<RenderViewHost*> rvh_list =
312      content::DevToolsAgentHost::GetValidRenderViewHosts();
313  for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
314       it != rvh_list.end(); ++it) {
315    bool is_tab = tab_rvhs.find(*it) != tab_rvhs.end();
316    result.push_back(new RenderViewHostTarget(*it, is_tab));
317  }
318  return result;
319}
320
321static void CreateWorkerTargets(
322    const std::vector<WorkerService::WorkerInfo>& worker_info,
323    DevToolsTargetImpl::Callback callback) {
324  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
325  DevToolsTargetImpl::List result;
326  for (size_t i = 0; i < worker_info.size(); ++i) {
327    result.push_back(new WorkerTarget(worker_info[i]));
328  }
329  callback.Run(result);
330}
331
332// static
333void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) {
334  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
335  content::BrowserThread::PostTask(
336      content::BrowserThread::UI,
337      FROM_HERE,
338      base::Bind(&CreateWorkerTargets,
339                 WorkerService::GetInstance()->GetWorkers(),
340                 callback));
341}
342
343static void CollectAllTargets(
344    DevToolsTargetImpl::Callback callback,
345    const DevToolsTargetImpl::List& worker_targets) {
346  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
347  DevToolsTargetImpl::List result =
348      DevToolsTargetImpl::EnumerateRenderViewHostTargets();
349  result.insert(result.begin(), worker_targets.begin(), worker_targets.end());
350  callback.Run(result);
351}
352
353// static
354void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) {
355  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
356  content::BrowserThread::PostTask(
357      content::BrowserThread::IO,
358      FROM_HERE,
359      base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets,
360                 base::Bind(&CollectAllTargets, callback)));
361}
362