Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / task_manager / tab_contents_resource_provider.cc
blob97824dc45eb9ee5c112514e152fee195c620e5f2
1 // Copyright 2012 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.
5 #include "chrome/browser/task_manager/tab_contents_resource_provider.h"
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/devtools/devtools_window.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/favicon/favicon_tab_helper.h"
12 #include "chrome/browser/prerender/prerender_manager.h"
13 #include "chrome/browser/prerender/prerender_manager_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/search/search.h"
17 #include "chrome/browser/tab_contents/tab_util.h"
18 #include "chrome/browser/task_manager/renderer_resource.h"
19 #include "chrome/browser/task_manager/resource_provider.h"
20 #include "chrome/browser/task_manager/task_manager.h"
21 #include "chrome/browser/task_manager/task_manager_util.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/browser_finder.h"
24 #include "chrome/browser/ui/browser_iterator.h"
25 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/render_frame_host.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/web_contents.h"
30 #include "extensions/browser/process_map.h"
31 #include "extensions/common/constants.h"
32 #include "grit/theme_resources.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h"
35 #include "ui/gfx/image/image_skia.h"
37 #if defined(ENABLE_FULL_PRINTING)
38 #include "chrome/browser/printing/background_printing_manager.h"
39 #endif
41 using content::WebContents;
42 using extensions::Extension;
44 namespace {
46 bool IsContentsPrerendering(WebContents* web_contents) {
47 Profile* profile =
48 Profile::FromBrowserContext(web_contents->GetBrowserContext());
49 prerender::PrerenderManager* prerender_manager =
50 prerender::PrerenderManagerFactory::GetForProfile(profile);
51 return prerender_manager &&
52 prerender_manager->IsWebContentsPrerendering(web_contents, NULL);
55 bool IsContentsBackgroundPrinted(WebContents* web_contents) {
56 #if defined(ENABLE_FULL_PRINTING)
57 printing::BackgroundPrintingManager* printing_manager =
58 g_browser_process->background_printing_manager();
59 return printing_manager->HasPrintPreviewDialog(web_contents);
60 #else
61 return false;
62 #endif
65 } // namespace
67 namespace task_manager {
69 // Tracks a single tab contents, prerendered page, Instant page, or background
70 // printing page.
71 class TabContentsResource : public RendererResource {
72 public:
73 explicit TabContentsResource(content::WebContents* web_contents);
74 virtual ~TabContentsResource();
76 // Resource methods:
77 virtual Type GetType() const OVERRIDE;
78 virtual base::string16 GetTitle() const OVERRIDE;
79 virtual base::string16 GetProfileName() const OVERRIDE;
80 virtual gfx::ImageSkia GetIcon() const OVERRIDE;
81 virtual content::WebContents* GetWebContents() const OVERRIDE;
82 virtual const extensions::Extension* GetExtension() const OVERRIDE;
84 private:
85 // Returns true if contains content rendered by an extension.
86 bool HostsExtension() const;
88 static gfx::ImageSkia* prerender_icon_;
89 content::WebContents* web_contents_;
90 Profile* profile_;
92 DISALLOW_COPY_AND_ASSIGN(TabContentsResource);
95 gfx::ImageSkia* TabContentsResource::prerender_icon_ = NULL;
97 TabContentsResource::TabContentsResource(
98 WebContents* web_contents)
99 : RendererResource(web_contents->GetRenderProcessHost()->GetHandle(),
100 web_contents->GetRenderViewHost()),
101 web_contents_(web_contents),
102 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())) {
103 if (!prerender_icon_) {
104 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
105 prerender_icon_ = rb.GetImageSkiaNamed(IDR_PRERENDER);
109 TabContentsResource::~TabContentsResource() {
112 bool TabContentsResource::HostsExtension() const {
113 return web_contents_->GetURL().SchemeIs(extensions::kExtensionScheme);
116 Resource::Type TabContentsResource::GetType() const {
117 return HostsExtension() ? EXTENSION : RENDERER;
120 base::string16 TabContentsResource::GetTitle() const {
121 // Fall back on the URL if there's no title.
122 GURL url = web_contents_->GetURL();
123 base::string16 tab_title = util::GetTitleFromWebContents(web_contents_);
125 // Only classify as an app if the URL is an app and the tab is hosting an
126 // extension process. (It's possible to be showing the URL from before it
127 // was installed as an app.)
128 ExtensionService* extension_service = profile_->GetExtensionService();
129 extensions::ProcessMap* process_map = extensions::ProcessMap::Get(profile_);
130 bool is_app = extension_service->IsInstalledApp(url) &&
131 process_map->Contains(web_contents_->GetRenderProcessHost()->GetID());
133 int message_id = util::GetMessagePrefixID(
134 is_app,
135 HostsExtension(),
136 profile_->IsOffTheRecord(),
137 IsContentsPrerendering(web_contents_),
138 false); // is_background
139 return l10n_util::GetStringFUTF16(message_id, tab_title);
142 base::string16 TabContentsResource::GetProfileName() const {
143 return util::GetProfileNameFromInfoCache(profile_);
146 gfx::ImageSkia TabContentsResource::GetIcon() const {
147 if (IsContentsPrerendering(web_contents_))
148 return *prerender_icon_;
149 FaviconTabHelper::CreateForWebContents(web_contents_);
150 return FaviconTabHelper::FromWebContents(web_contents_)->
151 GetFavicon().AsImageSkia();
154 WebContents* TabContentsResource::GetWebContents() const {
155 return web_contents_;
158 const Extension* TabContentsResource::GetExtension() const {
159 if (HostsExtension()) {
160 ExtensionService* extension_service = profile_->GetExtensionService();
161 return extension_service->extensions()->GetByID(
162 web_contents_->GetURL().host());
165 return NULL;
168 ////////////////////////////////////////////////////////////////////////////////
169 // TabContentsResourceProvider class
170 ////////////////////////////////////////////////////////////////////////////////
172 TabContentsResourceProvider::
173 TabContentsResourceProvider(TaskManager* task_manager)
174 : updating_(false),
175 task_manager_(task_manager) {
178 TabContentsResourceProvider::~TabContentsResourceProvider() {
181 Resource* TabContentsResourceProvider::GetResource(
182 int origin_pid,
183 int child_id,
184 int route_id) {
185 content::RenderFrameHost* rfh =
186 content::RenderFrameHost::FromID(child_id, route_id);
187 content::WebContents* web_contents =
188 content::WebContents::FromRenderFrameHost(rfh);
190 // If an origin PID was specified then the request originated in a plugin
191 // working on the WebContents's behalf, so ignore it.
192 if (origin_pid)
193 return NULL;
195 std::map<WebContents*, TabContentsResource*>::iterator
196 res_iter = resources_.find(web_contents);
197 if (res_iter == resources_.end()) {
198 // Can happen if the tab was closed while a network request was being
199 // performed.
200 return NULL;
202 return res_iter->second;
205 void TabContentsResourceProvider::StartUpdating() {
206 DCHECK(!updating_);
207 updating_ = true;
209 // The contents that are tracked by this resource provider are those that
210 // are tab contents (WebContents serving as a tab in a Browser), Instant
211 // pages, prerender pages, and background printed pages.
213 // Add all the existing WebContentses.
214 for (TabContentsIterator iterator; !iterator.done(); iterator.Next()) {
215 Add(*iterator);
216 DevToolsWindow* docked =
217 DevToolsWindow::GetDockedInstanceForInspectedTab(*iterator);
218 if (docked)
219 Add(docked->web_contents());
222 // Add all the prerender pages.
223 std::vector<Profile*> profiles(
224 g_browser_process->profile_manager()->GetLoadedProfiles());
225 for (size_t i = 0; i < profiles.size(); ++i) {
226 prerender::PrerenderManager* prerender_manager =
227 prerender::PrerenderManagerFactory::GetForProfile(profiles[i]);
228 if (prerender_manager) {
229 const std::vector<content::WebContents*> contentses =
230 prerender_manager->GetAllPrerenderingContents();
231 for (size_t j = 0; j < contentses.size(); ++j)
232 Add(contentses[j]);
236 #if defined(ENABLE_FULL_PRINTING)
237 // Add all the pages being background printed.
238 printing::BackgroundPrintingManager* printing_manager =
239 g_browser_process->background_printing_manager();
240 std::set<content::WebContents*> printing_contents =
241 printing_manager->CurrentContentSet();
242 for (std::set<content::WebContents*>::iterator i =
243 printing_contents.begin();
244 i != printing_contents.end(); ++i) {
245 Add(*i);
247 #endif
249 // Then we register for notifications to get new web contents.
250 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
251 content::NotificationService::AllBrowserContextsAndSources());
252 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
253 content::NotificationService::AllBrowserContextsAndSources());
254 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
255 content::NotificationService::AllBrowserContextsAndSources());
258 void TabContentsResourceProvider::StopUpdating() {
259 DCHECK(updating_);
260 updating_ = false;
262 // Then we unregister for notifications to get new web contents.
263 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
264 content::NotificationService::AllBrowserContextsAndSources());
265 registrar_.Remove(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
266 content::NotificationService::AllBrowserContextsAndSources());
267 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
268 content::NotificationService::AllBrowserContextsAndSources());
270 // Delete all the resources.
271 STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
273 resources_.clear();
276 void TabContentsResourceProvider::AddToTaskManager(WebContents* web_contents) {
277 TabContentsResource* resource = new TabContentsResource(web_contents);
278 resources_[web_contents] = resource;
279 task_manager_->AddResource(resource);
282 void TabContentsResourceProvider::Add(WebContents* web_contents) {
283 if (!updating_)
284 return;
286 // The contents that are tracked by this resource provider are those that
287 // are tab contents (WebContents serving as a tab in a Browser), Instant
288 // pages, prerender pages, and background printed pages.
289 if (!chrome::FindBrowserWithWebContents(web_contents) &&
290 !IsContentsPrerendering(web_contents) &&
291 !IsContentsBackgroundPrinted(web_contents) &&
292 !DevToolsWindow::IsDevToolsWindow(web_contents->GetRenderViewHost())) {
293 return;
296 // Don't add dead tabs or tabs that haven't yet connected.
297 if (!web_contents->GetRenderProcessHost()->GetHandle() ||
298 !web_contents->WillNotifyDisconnection()) {
299 return;
302 if (resources_.count(web_contents)) {
303 // The case may happen that we have added a WebContents as part of the
304 // iteration performed during StartUpdating() call but the notification that
305 // it has connected was not fired yet. So when the notification happens, we
306 // already know about this tab and just ignore it.
307 return;
309 AddToTaskManager(web_contents);
312 void TabContentsResourceProvider::Remove(WebContents* web_contents) {
313 if (!updating_)
314 return;
315 std::map<WebContents*, TabContentsResource*>::iterator
316 iter = resources_.find(web_contents);
317 if (iter == resources_.end()) {
318 // Since WebContents are destroyed asynchronously (see TabContentsCollector
319 // in navigation_controller.cc), we can be notified of a tab being removed
320 // that we don't know. This can happen if the user closes a tab and quickly
321 // opens the task manager, before the tab is actually destroyed.
322 return;
325 // Remove the resource from the Task Manager.
326 TabContentsResource* resource = iter->second;
327 task_manager_->RemoveResource(resource);
328 // And from the provider.
329 resources_.erase(iter);
330 // Finally, delete the resource.
331 delete resource;
334 void TabContentsResourceProvider::Observe(
335 int type,
336 const content::NotificationSource& source,
337 const content::NotificationDetails& details) {
338 WebContents* web_contents = content::Source<WebContents>(source).ptr();
340 switch (type) {
341 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
342 Add(web_contents);
343 break;
344 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED:
345 Remove(web_contents);
346 Add(web_contents);
347 break;
348 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
349 Remove(web_contents);
350 break;
351 default:
352 NOTREACHED() << "Unexpected notification.";
353 return;
357 } // namespace task_manager