• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_host.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
16 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
17 #include "chrome/common/extensions/extension_constants.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/favicon_status.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
23 
24 using content::BrowserThread;
25 using content::DevToolsAgentHost;
26 using content::RenderViewHost;
27 using content::WebContents;
28 using content::WorkerService;
29 
30 namespace {
31 
32 const char kTargetTypeApp[] = "app";
33 const char kTargetTypeBackgroundPage[] = "background_page";
34 const char kTargetTypePage[] = "page";
35 const char kTargetTypeWorker[] = "worker";
36 const char kTargetTypeOther[] = "other";
37 
38 class RenderViewHostTarget : public DevToolsTargetImpl {
39  public:
40   explicit RenderViewHostTarget(RenderViewHost* rvh, bool is_tab);
41 
42   // content::DevToolsTarget overrides:
43   virtual bool Activate() const OVERRIDE;
44   virtual bool Close() const OVERRIDE;
45 
46   // DevToolsTargetImpl overrides:
47   virtual RenderViewHost* GetRenderViewHost() const OVERRIDE;
48   virtual int GetTabId() const OVERRIDE;
49   virtual std::string GetExtensionId() const OVERRIDE;
50   virtual void Inspect(Profile* profile) const OVERRIDE;
51 
52  private:
53   int tab_id_;
54   std::string extension_id_;
55 };
56 
RenderViewHostTarget(RenderViewHost * rvh,bool is_tab)57 RenderViewHostTarget::RenderViewHostTarget(RenderViewHost* rvh, bool is_tab) {
58   agent_host_ = DevToolsAgentHost::GetOrCreateFor(rvh);
59   id_ = agent_host_->GetId();
60   type_ = kTargetTypeOther;
61   tab_id_ = -1;
62 
63   WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
64   if (!web_contents)
65     return;  // Orphan RVH will show up with no title/url/icon in clients.
66 
67   title_ = UTF16ToUTF8(web_contents->GetTitle());
68   url_ = web_contents->GetURL();
69   content::NavigationController& controller = web_contents->GetController();
70   content::NavigationEntry* entry = controller.GetActiveEntry();
71   if (entry != NULL && entry->GetURL().is_valid())
72     favicon_url_ = entry->GetFavicon().url;
73   last_activity_time_ = web_contents->GetLastSelectedTime();
74 
75   if (is_tab) {
76     type_ = kTargetTypePage;
77     tab_id_ = extensions::ExtensionTabUtil::GetTabId(web_contents);
78   } else {
79     Profile* profile =
80         Profile::FromBrowserContext(web_contents->GetBrowserContext());
81     if (profile) {
82       ExtensionService* extension_service = profile->GetExtensionService();
83       const extensions::Extension* extension = extension_service->
84           extensions()->GetByID(url_.host());
85       if (extension) {
86         title_ = extension->name();
87         if (extension->is_hosted_app()
88             || extension->is_legacy_packaged_app()
89             || extension->is_platform_app()) {
90           type_ = kTargetTypeApp;
91         } else {
92           extensions::ExtensionHost* extension_host =
93               extensions::ExtensionSystem::Get(profile)->process_manager()->
94                   GetBackgroundHostForExtension(extension->id());
95           if (extension_host &&
96               extension_host->host_contents() == web_contents) {
97             type_ = kTargetTypeBackgroundPage;
98             extension_id_ = extension->id();
99           }
100         }
101         favicon_url_ = extensions::ExtensionIconSource::GetIconURL(
102             extension, extension_misc::EXTENSION_ICON_SMALLISH,
103             ExtensionIconSet::MATCH_BIGGER, false, NULL);
104       }
105     }
106   }
107 }
108 
Activate() const109 bool RenderViewHostTarget::Activate() const {
110   RenderViewHost* rvh = GetRenderViewHost();
111   if (!rvh)
112     return false;
113   WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
114   if (!web_contents)
115     return false;
116   web_contents->GetDelegate()->ActivateContents(web_contents);
117   return true;
118 }
119 
Close() const120 bool RenderViewHostTarget::Close() const {
121   RenderViewHost* rvh = GetRenderViewHost();
122   if (!rvh)
123     return false;
124   rvh->ClosePage();
125   return true;
126 }
127 
GetRenderViewHost() const128 RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const {
129   return agent_host_->GetRenderViewHost();
130 }
131 
GetTabId() const132 int RenderViewHostTarget::GetTabId() const {
133   return tab_id_;
134 }
135 
GetExtensionId() const136 std::string RenderViewHostTarget::GetExtensionId() const {
137   return extension_id_;
138 }
139 
Inspect(Profile * profile) const140 void RenderViewHostTarget::Inspect(Profile* profile) const {
141   RenderViewHost* rvh = GetRenderViewHost();
142   if (!rvh)
143     return;
144   DevToolsWindow::OpenDevToolsWindow(rvh);
145 }
146 
147 ///////////////////////////////////////////////////////////////////////////////
148 
149 class WorkerTarget : public DevToolsTargetImpl {
150  public:
151   explicit WorkerTarget(const WorkerService::WorkerInfo& worker_info);
152 
153   // content::DevToolsTarget overrides:
154   virtual bool Close() const OVERRIDE;
155 
156   // DevToolsTargetImpl overrides:
157   virtual void Inspect(Profile* profile) const OVERRIDE;
158 
159  private:
160   int process_id_;
161   int route_id_;
162 };
163 
WorkerTarget(const WorkerService::WorkerInfo & worker)164 WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker) {
165   agent_host_ =
166       DevToolsAgentHost::GetForWorker(worker.process_id, worker.route_id);
167   id_ = agent_host_->GetId();
168   type_ = kTargetTypeWorker;
169   title_ = UTF16ToUTF8(worker.name);
170   description_ =
171       base::StringPrintf("Worker pid:%d", base::GetProcId(worker.handle));
172   url_ = worker.url;
173 
174   process_id_ = worker.process_id;
175   route_id_ = worker.route_id;
176 }
177 
TerminateWorker(int process_id,int route_id)178 static void TerminateWorker(int process_id, int route_id) {
179   WorkerService::GetInstance()->TerminateWorker(process_id, route_id);
180 }
181 
Close() const182 bool WorkerTarget::Close() const {
183   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
184       base::Bind(&TerminateWorker, process_id_, route_id_));
185   return true;
186 }
187 
Inspect(Profile * profile) const188 void WorkerTarget::Inspect(Profile* profile) const {
189   DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host_.get());
190 }
191 
192 }  // namespace
193 
~DevToolsTargetImpl()194 DevToolsTargetImpl::~DevToolsTargetImpl() {
195 }
196 
DevToolsTargetImpl()197 DevToolsTargetImpl::DevToolsTargetImpl() {
198 }
199 
GetId() const200 std::string DevToolsTargetImpl::GetId() const {
201   return id_;
202 }
203 
GetType() const204 std::string DevToolsTargetImpl::GetType() const {
205   return type_;
206 }
207 
GetTitle() const208 std::string DevToolsTargetImpl::GetTitle() const {
209   return title_;
210 }
211 
GetDescription() const212 std::string DevToolsTargetImpl::GetDescription() const {
213   return description_;
214 }
215 
GetUrl() const216 GURL DevToolsTargetImpl::GetUrl() const {
217   return url_;
218 }
219 
GetFaviconUrl() const220 GURL DevToolsTargetImpl::GetFaviconUrl() const {
221   return favicon_url_;
222 }
223 
GetLastActivityTime() const224 base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const {
225   return last_activity_time_;
226 }
227 
228 scoped_refptr<content::DevToolsAgentHost>
GetAgentHost() const229 DevToolsTargetImpl::GetAgentHost() const {
230   return agent_host_;
231 }
232 
IsAttached() const233 bool DevToolsTargetImpl::IsAttached() const {
234   return agent_host_->IsAttached();
235 }
236 
Activate() const237 bool DevToolsTargetImpl::Activate() const {
238   return false;
239 }
240 
Close() const241 bool DevToolsTargetImpl::Close() const {
242   return false;
243 }
244 
GetTabId() const245 int DevToolsTargetImpl::GetTabId() const {
246   return -1;
247 }
248 
GetRenderViewHost() const249 RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const {
250   return NULL;
251 }
252 
GetExtensionId() const253 std::string DevToolsTargetImpl::GetExtensionId() const {
254   return std::string();
255 }
256 
Inspect(Profile *) const257 void DevToolsTargetImpl::Inspect(Profile*) const {
258 }
259 
Reload() const260 void DevToolsTargetImpl::Reload() const {
261 }
262 
263 // static
CreateForRenderViewHost(content::RenderViewHost * rvh,bool is_tab)264 scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost(
265     content::RenderViewHost* rvh, bool is_tab) {
266   return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab));
267 }
268 
269 // static
CreateForWorker(const WorkerService::WorkerInfo & worker_info)270 scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForWorker(
271     const WorkerService::WorkerInfo& worker_info) {
272   return scoped_ptr<DevToolsTargetImpl>(new WorkerTarget(worker_info));
273 }
274 
275 // static
EnumerateRenderViewHostTargets()276 DevToolsTargetImpl::List DevToolsTargetImpl::EnumerateRenderViewHostTargets() {
277   std::set<RenderViewHost*> tab_rvhs;
278   for (TabContentsIterator it; !it.done(); it.Next())
279     tab_rvhs.insert(it->GetRenderViewHost());
280 
281   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
282   DevToolsTargetImpl::List result;
283   std::vector<RenderViewHost*> rvh_list =
284       content::DevToolsAgentHost::GetValidRenderViewHosts();
285   for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
286        it != rvh_list.end(); ++it) {
287     bool is_tab = tab_rvhs.find(*it) != tab_rvhs.end();
288     result.push_back(new RenderViewHostTarget(*it, is_tab));
289   }
290   return result;
291 }
292 
CreateWorkerTargets(const std::vector<WorkerService::WorkerInfo> & worker_info,DevToolsTargetImpl::Callback callback)293 static void CreateWorkerTargets(
294     const std::vector<WorkerService::WorkerInfo>& worker_info,
295     DevToolsTargetImpl::Callback callback) {
296   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
297   DevToolsTargetImpl::List result;
298   for (size_t i = 0; i < worker_info.size(); ++i) {
299     result.push_back(new WorkerTarget(worker_info[i]));
300   }
301   callback.Run(result);
302 }
303 
304 // static
EnumerateWorkerTargets(Callback callback)305 void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) {
306   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
307   content::BrowserThread::PostTask(
308       content::BrowserThread::UI,
309       FROM_HERE,
310       base::Bind(&CreateWorkerTargets,
311                  WorkerService::GetInstance()->GetWorkers(),
312                  callback));
313 }
314 
CollectAllTargets(DevToolsTargetImpl::Callback callback,const DevToolsTargetImpl::List & worker_targets)315 static void CollectAllTargets(
316     DevToolsTargetImpl::Callback callback,
317     const DevToolsTargetImpl::List& worker_targets) {
318   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
319   DevToolsTargetImpl::List result =
320       DevToolsTargetImpl::EnumerateRenderViewHostTargets();
321   result.insert(result.begin(), worker_targets.begin(), worker_targets.end());
322   callback.Run(result);
323 }
324 
325 // static
EnumerateAllTargets(Callback callback)326 void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) {
327   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
328   content::BrowserThread::PostTask(
329       content::BrowserThread::IO,
330       FROM_HERE,
331       base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets,
332                  base::Bind(&CollectAllTargets, callback)));
333 }
334