Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / devtools / devtools_target_impl.cc
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_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"
26
27 using content::BrowserThread;
28 using content::DevToolsAgentHost;
29 using content::RenderViewHost;
30 using content::WebContents;
31 using content::WorkerService;
32
33 namespace {
34
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";
42
43 // RenderViewHostTarget --------------------------------------------------------
44
45 class RenderViewHostTarget : public DevToolsTargetImpl {
46  public:
47   explicit RenderViewHostTarget(RenderViewHost* rvh, bool is_tab);
48
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;
56
57  private:
58   int tab_id_;
59   std::string extension_id_;
60 };
61
62 RenderViewHostTarget::RenderViewHostTarget(RenderViewHost* rvh, bool is_tab)
63     : DevToolsTargetImpl(DevToolsAgentHost::GetOrCreateFor(rvh)),
64       tab_id_(-1) {
65   set_type(kTargetTypeOther);
66   WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
67   if (!web_contents)
68     return;  // Orphan RVH will show up with no title/url/icon in clients.
69
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());
78     return;
79   }
80
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());
88
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());
96     return;
97   }
98
99   if (is_tab) {
100     set_type(kTargetTypePage);
101     tab_id_ = extensions::ExtensionTabUtil::GetTabId(web_contents);
102   } else {
103     Profile* profile =
104         Profile::FromBrowserContext(web_contents->GetBrowserContext());
105     if (profile) {
106       ExtensionService* extension_service = profile->GetExtensionService();
107       const extensions::Extension* extension = extension_service->
108           extensions()->GetByID(GetURL().host());
109       if (extension) {
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);
122         }
123         set_favicon_url(extensions::ExtensionIconSource::GetIconURL(
124             extension, extension_misc::EXTENSION_ICON_SMALLISH,
125             ExtensionIconSet::MATCH_BIGGER, false, NULL));
126       }
127     }
128   }
129 }
130
131 bool RenderViewHostTarget::Activate() const {
132   RenderViewHost* rvh = GetRenderViewHost();
133   if (!rvh)
134     return false;
135   WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
136   if (!web_contents)
137     return false;
138   web_contents->GetDelegate()->ActivateContents(web_contents);
139   return true;
140 }
141
142 bool RenderViewHostTarget::Close() const {
143   RenderViewHost* rvh = GetRenderViewHost();
144   if (!rvh)
145     return false;
146   rvh->ClosePage();
147   return true;
148 }
149
150 RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const {
151   return GetAgentHost()->GetRenderViewHost();
152 }
153
154 int RenderViewHostTarget::GetTabId() const {
155   return tab_id_;
156 }
157
158 std::string RenderViewHostTarget::GetExtensionId() const {
159   return extension_id_;
160 }
161
162 void RenderViewHostTarget::Inspect(Profile* profile) const {
163   RenderViewHost* rvh = GetRenderViewHost();
164   if (!rvh)
165     return;
166   DevToolsWindow::OpenDevToolsWindow(rvh);
167 }
168
169 // WorkerTarget ----------------------------------------------------------------
170
171 class WorkerTarget : public DevToolsTargetImpl {
172  public:
173   explicit WorkerTarget(const WorkerService::WorkerInfo& worker_info);
174
175   // content::DevToolsTarget overrides:
176   virtual bool Close() const OVERRIDE;
177
178   // DevToolsTargetImpl overrides:
179   virtual void Inspect(Profile* profile) const OVERRIDE;
180
181  private:
182   int process_id_;
183   int route_id_;
184 };
185
186 WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker)
187     : DevToolsTargetImpl(DevToolsAgentHost::GetForWorker(worker.process_id,
188                                                          worker.route_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)));
193   set_url(worker.url);
194
195   process_id_ = worker.process_id;
196   route_id_ = worker.route_id;
197 }
198
199 static void TerminateWorker(int process_id, int route_id) {
200   WorkerService::GetInstance()->TerminateWorker(process_id, route_id);
201 }
202
203 bool WorkerTarget::Close() const {
204   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
205       base::Bind(&TerminateWorker, process_id_, route_id_));
206   return true;
207 }
208
209 void WorkerTarget::Inspect(Profile* profile) const {
210   DevToolsWindow::OpenDevToolsWindowForWorker(profile, GetAgentHost());
211 }
212
213 }  // namespace
214
215 // DevToolsTargetImpl ----------------------------------------------------------
216
217 DevToolsTargetImpl::~DevToolsTargetImpl() {
218 }
219
220 DevToolsTargetImpl::DevToolsTargetImpl(
221     scoped_refptr<DevToolsAgentHost> agent_host)
222     : agent_host_(agent_host) {
223 }
224
225 std::string DevToolsTargetImpl::GetParentId() const {
226   return parent_id_;
227 }
228
229 std::string DevToolsTargetImpl::GetId() const {
230   return agent_host_->GetId();
231 }
232
233 std::string DevToolsTargetImpl::GetType() const {
234   return type_;
235 }
236
237 std::string DevToolsTargetImpl::GetTitle() const {
238   return title_;
239 }
240
241 std::string DevToolsTargetImpl::GetDescription() const {
242   return description_;
243 }
244
245 GURL DevToolsTargetImpl::GetURL() const {
246   return url_;
247 }
248
249 GURL DevToolsTargetImpl::GetFaviconURL() const {
250   return favicon_url_;
251 }
252
253 base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const {
254   return last_activity_time_;
255 }
256
257 scoped_refptr<content::DevToolsAgentHost>
258 DevToolsTargetImpl::GetAgentHost() const {
259   return agent_host_;
260 }
261
262 bool DevToolsTargetImpl::IsAttached() const {
263   return agent_host_->IsAttached();
264 }
265
266 bool DevToolsTargetImpl::Activate() const {
267   return false;
268 }
269
270 bool DevToolsTargetImpl::Close() const {
271   return false;
272 }
273
274 int DevToolsTargetImpl::GetTabId() const {
275   return -1;
276 }
277
278 RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const {
279   return NULL;
280 }
281
282 std::string DevToolsTargetImpl::GetExtensionId() const {
283   return std::string();
284 }
285
286 void DevToolsTargetImpl::Inspect(Profile*) const {
287 }
288
289 void DevToolsTargetImpl::Reload() const {
290 }
291
292 // static
293 scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost(
294     content::RenderViewHost* rvh, bool is_tab) {
295   return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab));
296 }
297
298 // static
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());
303
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));
312   }
313   return result;
314 }
315
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]));
323   }
324   callback.Run(result);
325 }
326
327 // static
328 void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) {
329   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330   content::BrowserThread::PostTask(
331       content::BrowserThread::UI,
332       FROM_HERE,
333       base::Bind(&CreateWorkerTargets,
334                  WorkerService::GetInstance()->GetWorkers(),
335                  callback));
336 }
337
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);
346 }
347
348 // static
349 void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) {
350   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
351   content::BrowserThread::PostTask(
352       content::BrowserThread::IO,
353       FROM_HERE,
354       base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets,
355                  base::Bind(&CollectAllTargets, callback)));
356 }