| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/devtools/devtools_target_impl.h" |
| |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/devtools/devtools_window.h" |
| #include "chrome/browser/extensions/extension_host.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/extensions/extension_tab_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
| #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/favicon_status.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| |
| using content::BrowserThread; |
| using content::DevToolsAgentHost; |
| using content::RenderViewHost; |
| using content::WebContents; |
| using content::WorkerService; |
| |
| namespace { |
| |
| const char kTargetTypeApp[] = "app"; |
| const char kTargetTypeBackgroundPage[] = "background_page"; |
| const char kTargetTypePage[] = "page"; |
| const char kTargetTypeWorker[] = "worker"; |
| const char kTargetTypeOther[] = "other"; |
| |
| class RenderViewHostTarget : public DevToolsTargetImpl { |
| public: |
| explicit RenderViewHostTarget(RenderViewHost* rvh, bool is_tab); |
| |
| // content::DevToolsTarget overrides: |
| virtual bool Activate() const OVERRIDE; |
| virtual bool Close() const OVERRIDE; |
| |
| // DevToolsTargetImpl overrides: |
| virtual RenderViewHost* GetRenderViewHost() const OVERRIDE; |
| virtual int GetTabId() const OVERRIDE; |
| virtual std::string GetExtensionId() const OVERRIDE; |
| virtual void Inspect(Profile* profile) const OVERRIDE; |
| |
| private: |
| int tab_id_; |
| std::string extension_id_; |
| }; |
| |
| RenderViewHostTarget::RenderViewHostTarget(RenderViewHost* rvh, bool is_tab) { |
| agent_host_ = DevToolsAgentHost::GetOrCreateFor(rvh); |
| id_ = agent_host_->GetId(); |
| type_ = kTargetTypeOther; |
| tab_id_ = -1; |
| |
| WebContents* web_contents = WebContents::FromRenderViewHost(rvh); |
| if (!web_contents) |
| return; // Orphan RVH will show up with no title/url/icon in clients. |
| |
| title_ = UTF16ToUTF8(web_contents->GetTitle()); |
| url_ = web_contents->GetURL(); |
| content::NavigationController& controller = web_contents->GetController(); |
| content::NavigationEntry* entry = controller.GetActiveEntry(); |
| if (entry != NULL && entry->GetURL().is_valid()) |
| favicon_url_ = entry->GetFavicon().url; |
| last_activity_time_ = web_contents->GetLastSelectedTime(); |
| |
| if (is_tab) { |
| type_ = kTargetTypePage; |
| tab_id_ = extensions::ExtensionTabUtil::GetTabId(web_contents); |
| } else { |
| Profile* profile = |
| Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| if (profile) { |
| ExtensionService* extension_service = profile->GetExtensionService(); |
| const extensions::Extension* extension = extension_service-> |
| extensions()->GetByID(url_.host()); |
| if (extension) { |
| title_ = extension->name(); |
| if (extension->is_hosted_app() |
| || extension->is_legacy_packaged_app() |
| || extension->is_platform_app()) { |
| type_ = kTargetTypeApp; |
| } else { |
| extensions::ExtensionHost* extension_host = |
| extensions::ExtensionSystem::Get(profile)->process_manager()-> |
| GetBackgroundHostForExtension(extension->id()); |
| if (extension_host && |
| extension_host->host_contents() == web_contents) { |
| type_ = kTargetTypeBackgroundPage; |
| extension_id_ = extension->id(); |
| } |
| } |
| favicon_url_ = extensions::ExtensionIconSource::GetIconURL( |
| extension, extension_misc::EXTENSION_ICON_SMALLISH, |
| ExtensionIconSet::MATCH_BIGGER, false, NULL); |
| } |
| } |
| } |
| } |
| |
| bool RenderViewHostTarget::Activate() const { |
| RenderViewHost* rvh = GetRenderViewHost(); |
| if (!rvh) |
| return false; |
| WebContents* web_contents = WebContents::FromRenderViewHost(rvh); |
| if (!web_contents) |
| return false; |
| web_contents->GetDelegate()->ActivateContents(web_contents); |
| return true; |
| } |
| |
| bool RenderViewHostTarget::Close() const { |
| RenderViewHost* rvh = GetRenderViewHost(); |
| if (!rvh) |
| return false; |
| rvh->ClosePage(); |
| return true; |
| } |
| |
| RenderViewHost* RenderViewHostTarget::GetRenderViewHost() const { |
| return agent_host_->GetRenderViewHost(); |
| } |
| |
| int RenderViewHostTarget::GetTabId() const { |
| return tab_id_; |
| } |
| |
| std::string RenderViewHostTarget::GetExtensionId() const { |
| return extension_id_; |
| } |
| |
| void RenderViewHostTarget::Inspect(Profile* profile) const { |
| RenderViewHost* rvh = GetRenderViewHost(); |
| if (!rvh) |
| return; |
| DevToolsWindow::OpenDevToolsWindow(rvh); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| class WorkerTarget : public DevToolsTargetImpl { |
| public: |
| explicit WorkerTarget(const WorkerService::WorkerInfo& worker_info); |
| |
| // content::DevToolsTarget overrides: |
| virtual bool Close() const OVERRIDE; |
| |
| // DevToolsTargetImpl overrides: |
| virtual void Inspect(Profile* profile) const OVERRIDE; |
| |
| private: |
| int process_id_; |
| int route_id_; |
| }; |
| |
| WorkerTarget::WorkerTarget(const WorkerService::WorkerInfo& worker) { |
| agent_host_ = |
| DevToolsAgentHost::GetForWorker(worker.process_id, worker.route_id); |
| id_ = agent_host_->GetId(); |
| type_ = kTargetTypeWorker; |
| title_ = UTF16ToUTF8(worker.name); |
| description_ = |
| base::StringPrintf("Worker pid:%d", base::GetProcId(worker.handle)); |
| url_ = worker.url; |
| |
| process_id_ = worker.process_id; |
| route_id_ = worker.route_id; |
| } |
| |
| static void TerminateWorker(int process_id, int route_id) { |
| WorkerService::GetInstance()->TerminateWorker(process_id, route_id); |
| } |
| |
| bool WorkerTarget::Close() const { |
| content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
| base::Bind(&TerminateWorker, process_id_, route_id_)); |
| return true; |
| } |
| |
| void WorkerTarget::Inspect(Profile* profile) const { |
| DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host_.get()); |
| } |
| |
| } // namespace |
| |
| DevToolsTargetImpl::~DevToolsTargetImpl() { |
| } |
| |
| DevToolsTargetImpl::DevToolsTargetImpl() { |
| } |
| |
| std::string DevToolsTargetImpl::GetId() const { |
| return id_; |
| } |
| |
| std::string DevToolsTargetImpl::GetType() const { |
| return type_; |
| } |
| |
| std::string DevToolsTargetImpl::GetTitle() const { |
| return title_; |
| } |
| |
| std::string DevToolsTargetImpl::GetDescription() const { |
| return description_; |
| } |
| |
| GURL DevToolsTargetImpl::GetUrl() const { |
| return url_; |
| } |
| |
| GURL DevToolsTargetImpl::GetFaviconUrl() const { |
| return favicon_url_; |
| } |
| |
| base::TimeTicks DevToolsTargetImpl::GetLastActivityTime() const { |
| return last_activity_time_; |
| } |
| |
| scoped_refptr<content::DevToolsAgentHost> |
| DevToolsTargetImpl::GetAgentHost() const { |
| return agent_host_; |
| } |
| |
| bool DevToolsTargetImpl::IsAttached() const { |
| return agent_host_->IsAttached(); |
| } |
| |
| bool DevToolsTargetImpl::Activate() const { |
| return false; |
| } |
| |
| bool DevToolsTargetImpl::Close() const { |
| return false; |
| } |
| |
| int DevToolsTargetImpl::GetTabId() const { |
| return -1; |
| } |
| |
| RenderViewHost* DevToolsTargetImpl::GetRenderViewHost() const { |
| return NULL; |
| } |
| |
| std::string DevToolsTargetImpl::GetExtensionId() const { |
| return std::string(); |
| } |
| |
| void DevToolsTargetImpl::Inspect(Profile*) const { |
| } |
| |
| void DevToolsTargetImpl::Reload() const { |
| } |
| |
| // static |
| scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForRenderViewHost( |
| content::RenderViewHost* rvh, bool is_tab) { |
| return scoped_ptr<DevToolsTargetImpl>(new RenderViewHostTarget(rvh, is_tab)); |
| } |
| |
| // static |
| scoped_ptr<DevToolsTargetImpl> DevToolsTargetImpl::CreateForWorker( |
| const WorkerService::WorkerInfo& worker_info) { |
| return scoped_ptr<DevToolsTargetImpl>(new WorkerTarget(worker_info)); |
| } |
| |
| // static |
| DevToolsTargetImpl::List DevToolsTargetImpl::EnumerateRenderViewHostTargets() { |
| std::set<RenderViewHost*> tab_rvhs; |
| for (TabContentsIterator it; !it.done(); it.Next()) |
| tab_rvhs.insert(it->GetRenderViewHost()); |
| |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DevToolsTargetImpl::List result; |
| std::vector<RenderViewHost*> rvh_list = |
| content::DevToolsAgentHost::GetValidRenderViewHosts(); |
| for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin(); |
| it != rvh_list.end(); ++it) { |
| bool is_tab = tab_rvhs.find(*it) != tab_rvhs.end(); |
| result.push_back(new RenderViewHostTarget(*it, is_tab)); |
| } |
| return result; |
| } |
| |
| static void CreateWorkerTargets( |
| const std::vector<WorkerService::WorkerInfo>& worker_info, |
| DevToolsTargetImpl::Callback callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DevToolsTargetImpl::List result; |
| for (size_t i = 0; i < worker_info.size(); ++i) { |
| result.push_back(new WorkerTarget(worker_info[i])); |
| } |
| callback.Run(result); |
| } |
| |
| // static |
| void DevToolsTargetImpl::EnumerateWorkerTargets(Callback callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| content::BrowserThread::PostTask( |
| content::BrowserThread::UI, |
| FROM_HERE, |
| base::Bind(&CreateWorkerTargets, |
| WorkerService::GetInstance()->GetWorkers(), |
| callback)); |
| } |
| |
| static void CollectAllTargets( |
| DevToolsTargetImpl::Callback callback, |
| const DevToolsTargetImpl::List& worker_targets) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DevToolsTargetImpl::List result = |
| DevToolsTargetImpl::EnumerateRenderViewHostTargets(); |
| result.insert(result.begin(), worker_targets.begin(), worker_targets.end()); |
| callback.Run(result); |
| } |
| |
| // static |
| void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| content::BrowserThread::PostTask( |
| content::BrowserThread::IO, |
| FROM_HERE, |
| base::Bind(&DevToolsTargetImpl::EnumerateWorkerTargets, |
| base::Bind(&CollectAllTargets, callback))); |
| } |