devtools_target_impl.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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_tab_util.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_view_host.h" 21#include "content/public/browser/web_contents.h" 22#include "extensions/browser/extension_system.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 38class 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 57RenderViewHostTarget::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_ = base::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->GetLastActiveTime(); 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 extensions::ExtensionHost* extension_host = 88 extensions::ExtensionSystem::Get(profile)->process_manager()-> 89 GetBackgroundHostForExtension(extension->id()); 90 if (extension_host && 91 extension_host->host_contents() == web_contents) { 92 type_ = kTargetTypeBackgroundPage; 93 extension_id_ = extension->id(); 94 } else if (extension->is_hosted_app() 95 || extension->is_legacy_packaged_app() 96 || extension->is_platform_app()) { 97 type_ = kTargetTypeApp; 98 } 99 favicon_url_ = extensions::ExtensionIconSource::GetIconURL( 100 extension, extension_misc::EXTENSION_ICON_SMALLISH, 101 ExtensionIconSet::MATCH_BIGGER, false, NULL); 102 } 103 } 104 } 105} 106 107bool RenderViewHostTarget::Activate() const { 108 RenderViewHost* rvh = GetRenderViewHost(); 109 if (!rvh) 110 return false; 111 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); 112 if (!web_contents) 113 return false; 114 web_contents->GetDelegate()->ActivateContents(web_contents); 115 return true; 116} 117 118bool RenderViewHostTarget::Close() const { 119 RenderViewHost* rvh = GetRenderViewHost(); 120 if (!rvh) 121 return false; 122 rvh->ClosePage(); 123 return true; 124} 125 126RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const { 127 return agent_host_->GetRenderViewHost(); 128} 129 130int RenderViewHostTarget::GetTabId() const { 131 return tab_id_; 132} 133 134std::string RenderViewHostTarget::GetExtensionId() const { 135 return extension_id_; 136} 137 138void RenderViewHostTarget::Inspect(Profile* profile) const { 139 RenderViewHost* rvh = GetRenderViewHost(); 140 if (!rvh) 141 return; 142 DevToolsWindow::OpenDevToolsWindow(rvh); 143} 144 145/////////////////////////////////////////////////////////////////////////////// 146 147class WorkerTarget : public DevToolsTargetImpl { 148 public: 149 explicit WorkerTarget(const WorkerService::WorkerInfo& worker_info); 150 151 // content::DevToolsTarget overrides: 152 virtual bool Close() const OVERRIDE; 153 154 // DevToolsTargetImpl overrides: 155 virtual void Inspect(Profile* profile) const OVERRIDE; 156 157 private: 158 int process_id_; 159 int route_id_; 160}; 161 162WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker) { 163 agent_host_ = 164 DevToolsAgentHost::GetForWorker(worker.process_id, worker.route_id); 165 id_ = agent_host_->GetId(); 166 type_ = kTargetTypeWorker; 167 title_ = base::UTF16ToUTF8(worker.name); 168 description_ = 169 base::StringPrintf("Worker pid:%d", base::GetProcId(worker.handle)); 170 url_ = worker.url; 171 172 process_id_ = worker.process_id; 173 route_id_ = worker.route_id; 174} 175 176static void TerminateWorker(int process_id, int route_id) { 177 WorkerService::GetInstance()->TerminateWorker(process_id, route_id); 178} 179 180bool WorkerTarget::Close() const { 181 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, 182 base::Bind(&TerminateWorker, process_id_, route_id_)); 183 return true; 184} 185 186void WorkerTarget::Inspect(Profile* profile) const { 187 DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host_.get()); 188} 189 190} // namespace 191 192DevToolsTargetImpl::~DevToolsTargetImpl() { 193} 194 195DevToolsTargetImpl::DevToolsTargetImpl() { 196} 197 198std::string DevToolsTargetImpl::GetId() const { 199 return id_; 200} 201 202std::string DevToolsTargetImpl::GetType() const { 203 return type_; 204} 205 206std::string DevToolsTargetImpl::GetTitle() const { 207 return title_; 208} 209 210std::string DevToolsTargetImpl::GetDescription() const { 211 return description_; 212} 213 214GURL DevToolsTargetImpl::GetUrl() const { 215 return url_; 216} 217 218GURL DevToolsTargetImpl::GetFaviconUrl() const { 219 return favicon_url_; 220} 221 222base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const { 223 return last_activity_time_; 224} 225 226scoped_refptr<content::DevToolsAgentHost> 227DevToolsTargetImpl::GetAgentHost() const { 228 return agent_host_; 229} 230 231bool DevToolsTargetImpl::IsAttached() const { 232 return agent_host_->IsAttached(); 233} 234 235bool DevToolsTargetImpl::Activate() const { 236 return false; 237} 238 239bool DevToolsTargetImpl::Close() const { 240 return false; 241} 242 243int DevToolsTargetImpl::GetTabId() const { 244 return -1; 245} 246 247RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const { 248 return NULL; 249} 250 251std::string DevToolsTargetImpl::GetExtensionId() const { 252 return std::string(); 253} 254 255void DevToolsTargetImpl::Inspect(Profile*) const { 256} 257 258void DevToolsTargetImpl::Reload() const { 259} 260 261// static 262scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost( 263 content::RenderViewHost* rvh, bool is_tab) { 264 return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab)); 265} 266 267// static 268scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForWorker( 269 const WorkerService::WorkerInfo& worker_info) { 270 return scoped_ptr<DevToolsTargetImpl>(new WorkerTarget(worker_info)); 271} 272 273// static 274DevToolsTargetImpl::List DevToolsTargetImpl::EnumerateRenderViewHostTargets() { 275 std::set<RenderViewHost*> tab_rvhs; 276 for (TabContentsIterator it; !it.done(); it.Next()) 277 tab_rvhs.insert(it->GetRenderViewHost()); 278 279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 280 DevToolsTargetImpl::List result; 281 std::vector<RenderViewHost*> rvh_list = 282 content::DevToolsAgentHost::GetValidRenderViewHosts(); 283 for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin(); 284 it != rvh_list.end(); ++it) { 285 bool is_tab = tab_rvhs.find(*it) != tab_rvhs.end(); 286 result.push_back(new RenderViewHostTarget(*it, is_tab)); 287 } 288 return result; 289} 290 291static void CreateWorkerTargets( 292 const std::vector<WorkerService::WorkerInfo>& worker_info, 293 DevToolsTargetImpl::Callback callback) { 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 295 DevToolsTargetImpl::List result; 296 for (size_t i = 0; i < worker_info.size(); ++i) { 297 result.push_back(new WorkerTarget(worker_info[i])); 298 } 299 callback.Run(result); 300} 301 302// static 303void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) { 304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 305 content::BrowserThread::PostTask( 306 content::BrowserThread::UI, 307 FROM_HERE, 308 base::Bind(&CreateWorkerTargets, 309 WorkerService::GetInstance()->GetWorkers(), 310 callback)); 311} 312 313static void CollectAllTargets( 314 DevToolsTargetImpl::Callback callback, 315 const DevToolsTargetImpl::List& worker_targets) { 316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 317 DevToolsTargetImpl::List result = 318 DevToolsTargetImpl::EnumerateRenderViewHostTargets(); 319 result.insert(result.begin(), worker_targets.begin(), worker_targets.end()); 320 callback.Run(result); 321} 322 323// static 324void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) { 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 326 content::BrowserThread::PostTask( 327 content::BrowserThread::IO, 328 FROM_HERE, 329 base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets, 330 base::Bind(&CollectAllTargets, callback))); 331} 332