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