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