devtools_target_impl.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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 24using content::BrowserThread; 25using content::DevToolsAgentHost; 26using content::RenderViewHost; 27using content::WebContents; 28using content::WorkerService; 29 30namespace { 31 32const char kTargetTypeApp[] = "app"; 33const char kTargetTypeBackgroundPage[] = "background_page"; 34const char kTargetTypePage[] = "page"; 35const char kTargetTypeWorker[] = "worker"; 36const char kTargetTypeOther[] = "other"; 37 38std::string GetExtensionName(WebContents* web_contents) { 39 Profile* profile = 40 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 41 if (!profile) 42 return std::string(); 43 44 extensions::ExtensionHost* extension_host = 45 extensions::ExtensionSystem::Get(profile)->process_manager()-> 46 GetBackgroundHostForExtension(web_contents->GetURL().host()); 47 48 if (!extension_host || extension_host->host_contents() != web_contents) 49 return std::string(); 50 51 return extension_host->extension()->name(); 52} 53 54class RenderViewHostTarget : public DevToolsTargetImpl { 55 public: 56 explicit RenderViewHostTarget(RenderViewHost* rvh, bool is_tab); 57 58 // content::DevToolsTarget overrides: 59 virtual bool Activate() const OVERRIDE; 60 virtual bool Close() const OVERRIDE; 61 62 // DevToolsTargetImpl overrides: 63 virtual RenderViewHost* GetRenderViewHost() const OVERRIDE; 64 virtual int GetTabId() const OVERRIDE; 65 virtual std::string GetExtensionId() const OVERRIDE; 66 virtual void Inspect(Profile* profile) const OVERRIDE; 67 68 private: 69 int tab_id_; 70 std::string extension_id_; 71}; 72 73RenderViewHostTarget::RenderViewHostTarget(RenderViewHost* rvh, bool is_tab) { 74 agent_host_ = DevToolsAgentHost::GetOrCreateFor(rvh); 75 id_ = agent_host_->GetId(); 76 type_ = kTargetTypeOther; 77 tab_id_ = -1; 78 79 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); 80 if (!web_contents) 81 return; // Orphan RVH will show up with no title/url/icon in clients. 82 83 title_ = UTF16ToUTF8(web_contents->GetTitle()); 84 url_ = web_contents->GetURL(); 85 content::NavigationController& controller = web_contents->GetController(); 86 content::NavigationEntry* entry = controller.GetActiveEntry(); 87 if (entry != NULL && entry->GetURL().is_valid()) 88 favicon_url_ = entry->GetFavicon().url; 89 last_activity_time_ = web_contents->GetLastSelectedTime(); 90 91 if (is_tab) { 92 type_ = kTargetTypePage; 93 tab_id_ = ExtensionTabUtil::GetTabId(web_contents); 94 } else { 95 Profile* profile = 96 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 97 if (profile) { 98 ExtensionService* extension_service = profile->GetExtensionService(); 99 const extensions::Extension* extension = extension_service-> 100 extensions()->GetByID(url_.host()); 101 if (extension) { 102 title_ = extension->name(); 103 if (extension->is_hosted_app() 104 || extension->is_legacy_packaged_app() 105 || extension->is_platform_app()) { 106 type_ = kTargetTypeApp; 107 } else { 108 extensions::ExtensionHost* extension_host = 109 extensions::ExtensionSystem::Get(profile)->process_manager()-> 110 GetBackgroundHostForExtension(extension->id()); 111 if (extension_host && 112 extension_host->host_contents() == web_contents) { 113 type_ = kTargetTypeBackgroundPage; 114 extension_id_ = extension->id(); 115 } 116 } 117 favicon_url_ = extensions::ExtensionIconSource::GetIconURL( 118 extension, extension_misc::EXTENSION_ICON_SMALLISH, 119 ExtensionIconSet::MATCH_BIGGER, false, NULL); 120 } 121 } 122 123 std::string extension_name = GetExtensionName(web_contents); 124 if (!extension_name.empty()) { 125 type_ = kTargetTypeBackgroundPage; 126 title_ = extension_name; 127 } 128 } 129} 130 131bool 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 142bool RenderViewHostTarget::Close() const { 143 RenderViewHost* rvh = GetRenderViewHost(); 144 if (!rvh) 145 return false; 146 rvh->ClosePage(); 147 return true; 148} 149 150RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const { 151 return agent_host_->GetRenderViewHost(); 152} 153 154int RenderViewHostTarget::GetTabId() const { 155 return tab_id_; 156} 157 158std::string RenderViewHostTarget::GetExtensionId() const { 159 return extension_id_; 160} 161 162void RenderViewHostTarget::Inspect(Profile* profile) const { 163 RenderViewHost* rvh = GetRenderViewHost(); 164 if (!rvh) 165 return; 166 DevToolsWindow::OpenDevToolsWindow(rvh); 167} 168 169/////////////////////////////////////////////////////////////////////////////// 170 171class 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 186WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker) { 187 agent_host_ = 188 DevToolsAgentHost::GetForWorker(worker.process_id, worker.route_id); 189 id_ = agent_host_->GetId(); 190 type_ = kTargetTypeWorker; 191 title_ = UTF16ToUTF8(worker.name); 192 description_ = 193 base::StringPrintf("Worker pid:%d", base::GetProcId(worker.handle)); 194 url_ = worker.url; 195 196 process_id_ = worker.process_id; 197 route_id_ = worker.route_id; 198} 199 200static void TerminateWorker(int process_id, int route_id) { 201 WorkerService::GetInstance()->TerminateWorker(process_id, route_id); 202} 203 204bool WorkerTarget::Close() const { 205 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, 206 base::Bind(&TerminateWorker, process_id_, route_id_)); 207 return true; 208} 209 210void WorkerTarget::Inspect(Profile* profile) const { 211 DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host_.get()); 212} 213 214} // namespace 215 216DevToolsTargetImpl::~DevToolsTargetImpl() { 217} 218 219DevToolsTargetImpl::DevToolsTargetImpl() { 220} 221 222std::string DevToolsTargetImpl::GetId() const { 223 return id_; 224} 225 226std::string DevToolsTargetImpl::GetType() const { 227 return type_; 228} 229 230std::string DevToolsTargetImpl::GetTitle() const { 231 return title_; 232} 233 234std::string DevToolsTargetImpl::GetDescription() const { 235 return description_; 236} 237 238GURL DevToolsTargetImpl::GetUrl() const { 239 return url_; 240} 241 242GURL DevToolsTargetImpl::GetFaviconUrl() const { 243 return favicon_url_; 244} 245 246base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const { 247 return last_activity_time_; 248} 249 250scoped_refptr<content::DevToolsAgentHost> 251DevToolsTargetImpl::GetAgentHost() const { 252 return agent_host_; 253} 254 255bool DevToolsTargetImpl::IsAttached() const { 256 return agent_host_->IsAttached(); 257} 258 259bool DevToolsTargetImpl::Activate() const { 260 return false; 261} 262 263bool DevToolsTargetImpl::Close() const { 264 return false; 265} 266 267int DevToolsTargetImpl::GetTabId() const { 268 return -1; 269} 270 271RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const { 272 return NULL; 273} 274 275std::string DevToolsTargetImpl::GetExtensionId() const { 276 return std::string(); 277} 278 279void DevToolsTargetImpl::Inspect(Profile*) const { 280} 281 282void DevToolsTargetImpl::Reload() const { 283} 284 285// static 286scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost( 287 content::RenderViewHost* rvh, bool is_tab) { 288 return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab)); 289} 290 291// static 292scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForWorker( 293 const WorkerService::WorkerInfo& worker_info) { 294 return scoped_ptr<DevToolsTargetImpl>(new WorkerTarget(worker_info)); 295} 296 297// static 298DevToolsTargetImpl::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 315static 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 327void 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 337static 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 348void 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} 356