devtools_target_impl.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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/profiles/profile.h" 12#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 13#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 14#include "chrome/common/extensions/extension_constants.h" 15#include "content/public/browser/browser_thread.h" 16#include "content/public/browser/favicon_status.h" 17#include "content/public/browser/navigation_entry.h" 18#include "content/public/browser/render_frame_host.h" 19#include "content/public/browser/render_view_host.h" 20#include "content/public/browser/web_contents.h" 21#include "extensions/browser/extension_host.h" 22#include "extensions/browser/extension_registry.h" 23#include "extensions/browser/extension_system.h" 24#include "extensions/browser/guest_view/guest_view_base.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// WebContentsTarget -------------------------------------------------------- 45 46class WebContentsTarget : public DevToolsTargetImpl { 47 public: 48 WebContentsTarget(WebContents* web_contents, bool is_tab); 49 50 // DevToolsTargetImpl overrides: 51 virtual bool Activate() const OVERRIDE; 52 virtual bool Close() const OVERRIDE; 53 virtual WebContents* GetWebContents() 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 63WebContentsTarget::WebContentsTarget(WebContents* web_contents, bool is_tab) 64 : DevToolsTargetImpl(DevToolsAgentHost::GetOrCreateFor(web_contents)), 65 tab_id_(-1) { 66 set_type(kTargetTypeOther); 67 68 content::RenderFrameHost* rfh = 69 web_contents->GetRenderViewHost()->GetMainFrame(); 70 if (rfh->IsCrossProcessSubframe()) { 71 set_url(rfh->GetLastCommittedURL()); 72 set_type(kTargetTypeIFrame); 73 // TODO(pfeldman) Update for out of process iframes. 74 RenderViewHost* parent_rvh = rfh->GetParent()->GetRenderViewHost(); 75 set_parent_id(DevToolsAgentHost::GetOrCreateFor( 76 WebContents::FromRenderViewHost(parent_rvh))->GetId()); 77 return; 78 } 79 80 set_title(base::UTF16ToUTF8(web_contents->GetTitle())); 81 set_url(web_contents->GetURL()); 82 content::NavigationController& controller = web_contents->GetController(); 83 content::NavigationEntry* entry = controller.GetActiveEntry(); 84 if (entry != NULL && entry->GetURL().is_valid()) 85 set_favicon_url(entry->GetFavicon().url); 86 set_last_activity_time(web_contents->GetLastActiveTime()); 87 88 extensions::GuestViewBase* guest = 89 extensions::GuestViewBase::FromWebContents(web_contents); 90 WebContents* guest_contents = guest ? guest->embedder_web_contents() : NULL; 91 if (guest_contents) { 92 set_type(kTargetTypeWebView); 93 set_parent_id(DevToolsAgentHost::GetOrCreateFor(guest_contents)->GetId()); 94 return; 95 } 96 97 if (is_tab) { 98 set_type(kTargetTypePage); 99 tab_id_ = extensions::ExtensionTabUtil::GetTabId(web_contents); 100 return; 101 } 102 103 const extensions::Extension* extension = extensions::ExtensionRegistry::Get( 104 web_contents->GetBrowserContext())->enabled_extensions().GetByID( 105 GetURL().host()); 106 if (!extension) 107 return; 108 109 Profile* profile = 110 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 111 if (!profile) 112 return; 113 extensions::ExtensionSystem* extension_system = 114 extensions::ExtensionSystem::Get(profile); 115 set_title(extension->name()); 116 extensions::ExtensionHost* extension_host = 117 extension_system->process_manager()->GetBackgroundHostForExtension( 118 extension->id()); 119 if (extension_host && 120 extension_host->host_contents() == web_contents) { 121 set_type(kTargetTypeBackgroundPage); 122 extension_id_ = extension->id(); 123 } else if (extension->is_hosted_app() 124 || extension->is_legacy_packaged_app() 125 || extension->is_platform_app()) { 126 set_type(kTargetTypeApp); 127 } 128 set_favicon_url(extensions::ExtensionIconSource::GetIconURL( 129 extension, extension_misc::EXTENSION_ICON_SMALLISH, 130 ExtensionIconSet::MATCH_BIGGER, false, NULL)); 131} 132 133bool WebContentsTarget::Activate() const { 134 WebContents* web_contents = GetWebContents(); 135 if (!web_contents) 136 return false; 137 web_contents->GetDelegate()->ActivateContents(web_contents); 138 return true; 139} 140 141bool WebContentsTarget::Close() const { 142 WebContents* web_contents = GetWebContents(); 143 if (!web_contents) 144 return false; 145 web_contents->GetRenderViewHost()->ClosePage(); 146 return true; 147} 148 149WebContents* WebContentsTarget::GetWebContents() const { 150 return GetAgentHost()->GetWebContents(); 151} 152 153int WebContentsTarget::GetTabId() const { 154 return tab_id_; 155} 156 157std::string WebContentsTarget::GetExtensionId() const { 158 return extension_id_; 159} 160 161void WebContentsTarget::Inspect(Profile* profile) const { 162 WebContents* web_contents = GetWebContents(); 163 if (!web_contents) 164 return; 165 DevToolsWindow::OpenDevToolsWindow(web_contents); 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 277WebContents* DevToolsTargetImpl::GetWebContents() const { 278 return NULL; 279} 280 281std::string DevToolsTargetImpl::GetExtensionId() const { 282 return std::string(); 283} 284 285void DevToolsTargetImpl::Inspect(Profile* /*profile*/) const { 286} 287 288void DevToolsTargetImpl::Reload() const { 289} 290 291// static 292scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForWebContents( 293 content::WebContents* web_contents, 294 bool is_tab) { 295 return scoped_ptr<DevToolsTargetImpl>( 296 new WebContentsTarget(web_contents, is_tab)); 297} 298 299// static 300DevToolsTargetImpl::List DevToolsTargetImpl::EnumerateWebContentsTargets() { 301 std::set<WebContents*> tab_web_contents; 302 for (TabContentsIterator it; !it.done(); it.Next()) 303 tab_web_contents.insert(*it); 304 305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 306 DevToolsTargetImpl::List result; 307 std::vector<WebContents*> wc_list = 308 content::DevToolsAgentHost::GetInspectableWebContents(); 309 for (std::vector<WebContents*>::iterator it = wc_list.begin(); 310 it != wc_list.end(); 311 ++it) { 312 bool is_tab = tab_web_contents.find(*it) != tab_web_contents.end(); 313 result.push_back(new WebContentsTarget(*it, is_tab)); 314 } 315 return result; 316} 317 318static void CreateWorkerTargets( 319 const std::vector<WorkerService::WorkerInfo>& worker_info, 320 DevToolsTargetImpl::Callback callback) { 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 322 DevToolsTargetImpl::List result; 323 for (size_t i = 0; i < worker_info.size(); ++i) { 324 result.push_back(new WorkerTarget(worker_info[i])); 325 } 326 callback.Run(result); 327} 328 329// static 330void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) { 331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 332 content::BrowserThread::PostTask( 333 content::BrowserThread::UI, 334 FROM_HERE, 335 base::Bind(&CreateWorkerTargets, 336 WorkerService::GetInstance()->GetWorkers(), 337 callback)); 338} 339 340static void CollectAllTargets( 341 DevToolsTargetImpl::Callback callback, 342 const DevToolsTargetImpl::List& worker_targets) { 343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 344 DevToolsTargetImpl::List result = 345 DevToolsTargetImpl::EnumerateWebContentsTargets(); 346 result.insert(result.begin(), worker_targets.begin(), worker_targets.end()); 347 callback.Run(result); 348} 349 350// static 351void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) { 352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 353 content::BrowserThread::PostTask( 354 content::BrowserThread::IO, 355 FROM_HERE, 356 base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets, 357 base::Bind(&CollectAllTargets, callback))); 358} 359