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