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