Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(579)

Side by Side Diff: chrome/browser/task_manager/task_manager_tab_contents_resource_provider.cc

Issue 15196003: Create task_manager namespace and wrap classes related to TaskManager with it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: RendererResource Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/task_manager/task_manager_tab_contents_resource_provide r.h"
6
7 #include <string>
8
9 #include "base/i18n/rtl.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/favicon/favicon_tab_helper.h"
14 #include "chrome/browser/prerender/prerender_manager.h"
15 #include "chrome/browser/prerender/prerender_manager_factory.h"
16 #include "chrome/browser/printing/background_printing_manager.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/profiles/profile_info_cache.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/tab_contents/tab_util.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/browser_instant_controller.h"
24 #include "chrome/browser/ui/browser_iterator.h"
25 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
26 #include "chrome/common/chrome_notification_types.h"
27 #include "chrome/common/extensions/extension.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/render_process_host.h"
30 #include "content/public/browser/web_contents.h"
31 #include "extensions/common/constants.h"
32 #include "grit/generated_resources.h"
33 #include "grit/theme_resources.h"
34 #include "ui/base/l10n/l10n_util.h"
35 #include "ui/base/resource/resource_bundle.h"
36 #include "ui/gfx/image/image_skia.h"
37
38 using content::WebContents;
39 using extensions::Extension;
40
41 namespace {
42
43 // Returns the appropriate message prefix ID for tabs and extensions,
44 // reflecting whether they are apps or in incognito mode.
45 int GetMessagePrefixID(bool is_app,
46 bool is_extension,
47 bool is_incognito,
48 bool is_prerender,
49 bool is_instant_overlay,
50 bool is_background) {
51 if (is_app) {
52 if (is_background) {
53 return IDS_TASK_MANAGER_BACKGROUND_PREFIX;
54 } else if (is_incognito) {
55 return IDS_TASK_MANAGER_APP_INCOGNITO_PREFIX;
56 } else {
57 return IDS_TASK_MANAGER_APP_PREFIX;
58 }
59 } else if (is_extension) {
60 if (is_incognito)
61 return IDS_TASK_MANAGER_EXTENSION_INCOGNITO_PREFIX;
62 else
63 return IDS_TASK_MANAGER_EXTENSION_PREFIX;
64 } else if (is_prerender) {
65 return IDS_TASK_MANAGER_PRERENDER_PREFIX;
66 } else if (is_instant_overlay) {
67 return IDS_TASK_MANAGER_INSTANT_OVERLAY_PREFIX;
68 } else {
69 return IDS_TASK_MANAGER_TAB_PREFIX;
70 }
71 }
72
73 string16 GetProfileNameFromInfoCache(Profile* profile) {
74 ProfileInfoCache& cache =
75 g_browser_process->profile_manager()->GetProfileInfoCache();
76 size_t index = cache.GetIndexOfProfileWithPath(
77 profile->GetOriginalProfile()->GetPath());
78 if (index == std::string::npos)
79 return string16();
80 else
81 return cache.GetNameOfProfileAtIndex(index);
82 }
83
84 string16 GetTitleFromWebContents(WebContents* web_contents) {
85 string16 title = web_contents->GetTitle();
86 if (title.empty()) {
87 GURL url = web_contents->GetURL();
88 title = UTF8ToUTF16(url.spec());
89 // Force URL to be LTR.
90 title = base::i18n::GetDisplayStringInLTRDirectionality(title);
91 } else {
92 // Since the tab_title will be concatenated with
93 // IDS_TASK_MANAGER_TAB_PREFIX, we need to explicitly set the tab_title to
94 // be LTR format if there is no strong RTL charater in it. Otherwise, if
95 // IDS_TASK_MANAGER_TAB_PREFIX is an RTL word, the concatenated result
96 // might be wrong. For example, http://mail.yahoo.com, whose title is
97 // "Yahoo! Mail: The best web-based Email!", without setting it explicitly
98 // as LTR format, the concatenated result will be "!Yahoo! Mail: The best
99 // web-based Email :BAT", in which the capital letters "BAT" stands for
100 // the Hebrew word for "tab".
101 base::i18n::AdjustStringForLocaleDirection(&title);
102 }
103 return title;
104 }
105
106 bool IsContentsPrerendering(WebContents* web_contents) {
107 Profile* profile =
108 Profile::FromBrowserContext(web_contents->GetBrowserContext());
109 prerender::PrerenderManager* prerender_manager =
110 prerender::PrerenderManagerFactory::GetForProfile(profile);
111 return prerender_manager &&
112 prerender_manager->IsWebContentsPrerendering(web_contents, NULL);
113 }
114
115 bool IsContentsInstant(WebContents* web_contents) {
116 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
117 if (it->instant_controller() &&
118 it->instant_controller()->instant()->
119 GetOverlayContents() == web_contents) {
120 return true;
121 }
122 }
123
124 return false;
125 }
126
127 bool IsContentsBackgroundPrinted(WebContents* web_contents) {
128 printing::BackgroundPrintingManager* printing_manager =
129 g_browser_process->background_printing_manager();
130 return printing_manager->HasPrintPreviewDialog(web_contents);
131 }
132
133 } // namespace
134
135 ////////////////////////////////////////////////////////////////////////////////
136 // TaskManagerTabContentsResource class
137 ////////////////////////////////////////////////////////////////////////////////
138
139 // static
140 gfx::ImageSkia* TaskManagerTabContentsResource::prerender_icon_ = NULL;
141
142 TaskManagerTabContentsResource::TaskManagerTabContentsResource(
143 WebContents* web_contents)
144 : TaskManagerRendererResource(
145 web_contents->GetRenderProcessHost()->GetHandle(),
146 web_contents->GetRenderViewHost()),
147 web_contents_(web_contents),
148 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
149 is_instant_overlay_(IsContentsInstant(web_contents)) {
150 if (!prerender_icon_) {
151 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
152 prerender_icon_ = rb.GetImageSkiaNamed(IDR_PRERENDER);
153 }
154 }
155
156 TaskManagerTabContentsResource::~TaskManagerTabContentsResource() {
157 }
158
159 void TaskManagerTabContentsResource::InstantCommitted() {
160 DCHECK(is_instant_overlay_);
161 is_instant_overlay_ = false;
162 }
163
164 bool TaskManagerTabContentsResource::HostsExtension() const {
165 return web_contents_->GetURL().SchemeIs(extensions::kExtensionScheme);
166 }
167
168 TaskManager::Resource::Type TaskManagerTabContentsResource::GetType() const {
169 return HostsExtension() ? EXTENSION : RENDERER;
170 }
171
172 string16 TaskManagerTabContentsResource::GetTitle() const {
173 // Fall back on the URL if there's no title.
174 GURL url = web_contents_->GetURL();
175 string16 tab_title = GetTitleFromWebContents(web_contents_);
176
177 // Only classify as an app if the URL is an app and the tab is hosting an
178 // extension process. (It's possible to be showing the URL from before it
179 // was installed as an app.)
180 ExtensionService* extension_service = profile_->GetExtensionService();
181 extensions::ProcessMap* process_map = extension_service->process_map();
182 bool is_app = extension_service->IsInstalledApp(url) &&
183 process_map->Contains(web_contents_->GetRenderProcessHost()->GetID());
184
185 int message_id = GetMessagePrefixID(
186 is_app,
187 HostsExtension(),
188 profile_->IsOffTheRecord(),
189 IsContentsPrerendering(web_contents_),
190 is_instant_overlay_,
191 false);
192 return l10n_util::GetStringFUTF16(message_id, tab_title);
193 }
194
195 string16 TaskManagerTabContentsResource::GetProfileName() const {
196 return GetProfileNameFromInfoCache(profile_);
197 }
198
199 gfx::ImageSkia TaskManagerTabContentsResource::GetIcon() const {
200 if (IsContentsPrerendering(web_contents_))
201 return *prerender_icon_;
202 return FaviconTabHelper::FromWebContents(web_contents_)->
203 GetFavicon().AsImageSkia();
204 }
205
206 WebContents* TaskManagerTabContentsResource::GetWebContents() const {
207 return web_contents_;
208 }
209
210 const Extension* TaskManagerTabContentsResource::GetExtension() const {
211 if (HostsExtension()) {
212 ExtensionService* extension_service = profile_->GetExtensionService();
213 return extension_service->extensions()->GetByID(
214 web_contents_->GetURL().host());
215 }
216
217 return NULL;
218 }
219
220 ////////////////////////////////////////////////////////////////////////////////
221 // TaskManagerTabContentsResourceProvider class
222 ////////////////////////////////////////////////////////////////////////////////
223
224 TaskManagerTabContentsResourceProvider::
225 TaskManagerTabContentsResourceProvider(TaskManager* task_manager)
226 : updating_(false),
227 task_manager_(task_manager) {
228 }
229
230 TaskManagerTabContentsResourceProvider::
231 ~TaskManagerTabContentsResourceProvider() {
232 }
233
234 TaskManager::Resource* TaskManagerTabContentsResourceProvider::GetResource(
235 int origin_pid,
236 int render_process_host_id,
237 int routing_id) {
238 WebContents* web_contents =
239 tab_util::GetWebContentsByID(render_process_host_id, routing_id);
240 if (!web_contents) // Not one of our resource.
241 return NULL;
242
243 // If an origin PID was specified then the request originated in a plugin
244 // working on the WebContents's behalf, so ignore it.
245 if (origin_pid)
246 return NULL;
247
248 std::map<WebContents*, TaskManagerTabContentsResource*>::iterator
249 res_iter = resources_.find(web_contents);
250 if (res_iter == resources_.end()) {
251 // Can happen if the tab was closed while a network request was being
252 // performed.
253 return NULL;
254 }
255 return res_iter->second;
256 }
257
258 void TaskManagerTabContentsResourceProvider::StartUpdating() {
259 DCHECK(!updating_);
260 updating_ = true;
261
262 // The contents that are tracked by this resource provider are those that
263 // are tab contents (WebContents serving as a tab in a Browser), Instant
264 // pages, prerender pages, and background printed pages.
265
266 // Add all the existing WebContentses.
267 for (TabContentsIterator iterator; !iterator.done(); iterator.Next())
268 Add(*iterator);
269
270 // Add all the Instant pages.
271 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
272 if (it->instant_controller() &&
273 it->instant_controller()->instant()->GetOverlayContents()) {
274 Add(it->instant_controller()->instant()->GetOverlayContents());
275 }
276 }
277
278 // Add all the prerender pages.
279 std::vector<Profile*> profiles(
280 g_browser_process->profile_manager()->GetLoadedProfiles());
281 for (size_t i = 0; i < profiles.size(); ++i) {
282 prerender::PrerenderManager* prerender_manager =
283 prerender::PrerenderManagerFactory::GetForProfile(profiles[i]);
284 if (prerender_manager) {
285 const std::vector<content::WebContents*> contentses =
286 prerender_manager->GetAllPrerenderingContents();
287 for (size_t j = 0; j < contentses.size(); ++j)
288 Add(contentses[j]);
289 }
290 }
291
292 // Add all the pages being background printed.
293 printing::BackgroundPrintingManager* printing_manager =
294 g_browser_process->background_printing_manager();
295 for (printing::BackgroundPrintingManager::WebContentsSet::iterator i =
296 printing_manager->begin();
297 i != printing_manager->end(); ++i) {
298 Add(*i);
299 }
300
301 // Then we register for notifications to get new web contents.
302 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
303 content::NotificationService::AllBrowserContextsAndSources());
304 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
305 content::NotificationService::AllBrowserContextsAndSources());
306 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
307 content::NotificationService::AllBrowserContextsAndSources());
308 registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
309 content::NotificationService::AllBrowserContextsAndSources());
310 }
311
312 void TaskManagerTabContentsResourceProvider::StopUpdating() {
313 DCHECK(updating_);
314 updating_ = false;
315
316 // Then we unregister for notifications to get new web contents.
317 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
318 content::NotificationService::AllBrowserContextsAndSources());
319 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
320 content::NotificationService::AllBrowserContextsAndSources());
321 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
322 content::NotificationService::AllBrowserContextsAndSources());
323 registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
324 content::NotificationService::AllBrowserContextsAndSources());
325
326 // Delete all the resources.
327 STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
328
329 resources_.clear();
330 }
331
332 void TaskManagerTabContentsResourceProvider::AddToTaskManager(
333 WebContents* web_contents) {
334 TaskManagerTabContentsResource* resource =
335 new TaskManagerTabContentsResource(web_contents);
336 resources_[web_contents] = resource;
337 task_manager_->AddResource(resource);
338 }
339
340 void TaskManagerTabContentsResourceProvider::Add(WebContents* web_contents) {
341 if (!updating_)
342 return;
343
344 // The contents that are tracked by this resource provider are those that
345 // are tab contents (WebContents serving as a tab in a Browser), Instant
346 // pages, prerender pages, and background printed pages.
347 if (!chrome::FindBrowserWithWebContents(web_contents) &&
348 !IsContentsPrerendering(web_contents) &&
349 !IsContentsInstant(web_contents) &&
350 !IsContentsBackgroundPrinted(web_contents)) {
351 return;
352 }
353
354 // Don't add dead tabs or tabs that haven't yet connected.
355 if (!web_contents->GetRenderProcessHost()->GetHandle() ||
356 !web_contents->WillNotifyDisconnection()) {
357 return;
358 }
359
360 if (resources_.count(web_contents)) {
361 // The case may happen that we have added a WebContents as part of the
362 // iteration performed during StartUpdating() call but the notification that
363 // it has connected was not fired yet. So when the notification happens, we
364 // already know about this tab and just ignore it.
365 return;
366 }
367 AddToTaskManager(web_contents);
368 }
369
370 void TaskManagerTabContentsResourceProvider::Remove(WebContents* web_contents) {
371 if (!updating_)
372 return;
373 std::map<WebContents*, TaskManagerTabContentsResource*>::iterator
374 iter = resources_.find(web_contents);
375 if (iter == resources_.end()) {
376 // Since WebContents are destroyed asynchronously (see TabContentsCollector
377 // in navigation_controller.cc), we can be notified of a tab being removed
378 // that we don't know. This can happen if the user closes a tab and quickly
379 // opens the task manager, before the tab is actually destroyed.
380 return;
381 }
382
383 // Remove the resource from the Task Manager.
384 TaskManagerTabContentsResource* resource = iter->second;
385 task_manager_->RemoveResource(resource);
386 // And from the provider.
387 resources_.erase(iter);
388 // Finally, delete the resource.
389 delete resource;
390 }
391
392 void TaskManagerTabContentsResourceProvider::InstantCommitted(
393 WebContents* web_contents) {
394 if (!updating_)
395 return;
396 std::map<WebContents*, TaskManagerTabContentsResource*>::iterator
397 iter = resources_.find(web_contents);
398 DCHECK(iter != resources_.end());
399 if (iter != resources_.end())
400 iter->second->InstantCommitted();
401 }
402
403 void TaskManagerTabContentsResourceProvider::Observe(
404 int type,
405 const content::NotificationSource& source,
406 const content::NotificationDetails& details) {
407 WebContents* web_contents = content::Source<WebContents>(source).ptr();
408
409 switch (type) {
410 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
411 Add(web_contents);
412 break;
413 case content::NOTIFICATION_WEB_CONTENTS_SWAPPED:
414 Remove(web_contents);
415 Add(web_contents);
416 break;
417 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
418 Remove(web_contents);
419 break;
420 case chrome::NOTIFICATION_INSTANT_COMMITTED:
421 InstantCommitted(web_contents);
422 break;
423 default:
424 NOTREACHED() << "Unexpected notification.";
425 return;
426 }
427 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698