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