1// Copyright 2014 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/tab_contents_information.h"
6
7#include "base/callback.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/devtools/devtools_window.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/task_manager/renderer_resource.h"
17#include "chrome/browser/task_manager/task_manager_util.h"
18#include "chrome/browser/ui/browser.h"
19#include "chrome/browser/ui/browser_finder.h"
20#include "chrome/browser/ui/browser_iterator.h"
21#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
22#include "content/public/browser/render_process_host.h"
23#include "content/public/browser/web_contents.h"
24#include "extensions/browser/extension_registry.h"
25#include "extensions/browser/process_map.h"
26#include "extensions/common/constants.h"
27#include "extensions/common/extension_set.h"
28#include "grit/generated_resources.h"
29#include "grit/theme_resources.h"
30#include "ui/base/l10n/l10n_util.h"
31#include "ui/base/resource/resource_bundle.h"
32#include "ui/gfx/image/image_skia.h"
33
34using content::WebContents;
35
36namespace task_manager {
37
38namespace {
39
40// Returns true if the WebContents is currently owned by the prerendering
41// manager.
42bool IsContentsPrerendering(WebContents* web_contents) {
43  Profile* profile =
44      Profile::FromBrowserContext(web_contents->GetBrowserContext());
45  prerender::PrerenderManager* prerender_manager =
46      prerender::PrerenderManagerFactory::GetForProfile(profile);
47  return prerender_manager &&
48         prerender_manager->IsWebContentsPrerendering(web_contents, NULL);
49}
50
51}  // namespace
52
53// Tracks a single tab contents, prerendered page, or Instant page.
54class TabContentsResource : public RendererResource {
55 public:
56  explicit TabContentsResource(content::WebContents* web_contents);
57  virtual ~TabContentsResource();
58
59  // Resource methods:
60  virtual Type GetType() const OVERRIDE;
61  virtual base::string16 GetTitle() const OVERRIDE;
62  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
63  virtual content::WebContents* GetWebContents() const OVERRIDE;
64
65 private:
66  // Returns true if contains content rendered by an extension.
67  bool HostsExtension() const;
68
69  static gfx::ImageSkia* prerender_icon_;
70  content::WebContents* web_contents_;
71  Profile* profile_;
72
73  DISALLOW_COPY_AND_ASSIGN(TabContentsResource);
74};
75
76gfx::ImageSkia* TabContentsResource::prerender_icon_ = NULL;
77
78TabContentsResource::TabContentsResource(WebContents* web_contents)
79    : RendererResource(web_contents->GetRenderProcessHost()->GetHandle(),
80                       web_contents->GetRenderViewHost()),
81      web_contents_(web_contents),
82      profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())) {
83  if (!prerender_icon_) {
84    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
85    prerender_icon_ = rb.GetImageSkiaNamed(IDR_PRERENDER);
86  }
87}
88
89TabContentsResource::~TabContentsResource() {}
90
91bool TabContentsResource::HostsExtension() const {
92  return web_contents_->GetURL().SchemeIs(extensions::kExtensionScheme);
93}
94
95Resource::Type TabContentsResource::GetType() const {
96  // A tab that loads an extension URL is considered to be an extension for
97  // these purposes, although it's tracked as a TabContentsResource.
98  return HostsExtension() ? EXTENSION : RENDERER;
99}
100
101base::string16 TabContentsResource::GetTitle() const {
102  // Fall back on the URL if there's no title.
103  GURL url = web_contents_->GetURL();
104  base::string16 tab_title = util::GetTitleFromWebContents(web_contents_);
105
106  // Only classify as an app if the URL is an app and the tab is hosting an
107  // extension process.  (It's possible to be showing the URL from before it
108  // was installed as an app.)
109  extensions::ProcessMap* process_map = extensions::ProcessMap::Get(profile_);
110  bool is_app =
111      extensions::ExtensionRegistry::Get(profile_)
112          ->enabled_extensions().GetAppByURL(url) != NULL &&
113      process_map->Contains(web_contents_->GetRenderProcessHost()->GetID());
114
115  int message_id = util::GetMessagePrefixID(
116      is_app,
117      HostsExtension(),
118      profile_->IsOffTheRecord(),
119      IsContentsPrerendering(web_contents_),
120      false);  // is_background
121  return l10n_util::GetStringFUTF16(message_id, tab_title);
122}
123
124gfx::ImageSkia TabContentsResource::GetIcon() const {
125  if (IsContentsPrerendering(web_contents_))
126    return *prerender_icon_;
127  FaviconTabHelper::CreateForWebContents(web_contents_);
128  return FaviconTabHelper::FromWebContents(web_contents_)->
129      GetFavicon().AsImageSkia();
130}
131
132WebContents* TabContentsResource::GetWebContents() const {
133  return web_contents_;
134}
135
136TabContentsInformation::TabContentsInformation() {}
137
138TabContentsInformation::~TabContentsInformation() {}
139
140bool TabContentsInformation::CheckOwnership(
141    content::WebContents* web_contents) {
142  return chrome::FindBrowserWithWebContents(web_contents) ||
143         DevToolsWindow::IsDevToolsWindow(web_contents->GetRenderViewHost()) ||
144         IsContentsPrerendering(web_contents);
145}
146
147void TabContentsInformation::GetAll(const NewWebContentsCallback& callback) {
148  for (TabContentsIterator iterator; !iterator.done(); iterator.Next()) {
149    callback.Run(*iterator);
150    WebContents* devtools =
151        DevToolsWindow::GetInTabWebContents(*iterator, NULL);
152    if (devtools)
153      callback.Run(devtools);
154  }
155
156  // Because a WebContents* may start its life as a prerender, and later be
157  // put into a tab, this class tracks the prerender contents in the same
158  // way as the tab contents.
159  std::vector<Profile*> profiles(
160      g_browser_process->profile_manager()->GetLoadedProfiles());
161  for (size_t i = 0; i < profiles.size(); ++i) {
162    prerender::PrerenderManager* prerender_manager =
163        prerender::PrerenderManagerFactory::GetForProfile(profiles[i]);
164    if (prerender_manager) {
165      const std::vector<content::WebContents*> contentses =
166          prerender_manager->GetAllPrerenderingContents();
167      for (size_t j = 0; j < contentses.size(); ++j)
168        callback.Run(contentses[j]);
169    }
170  }
171}
172
173scoped_ptr<RendererResource> TabContentsInformation::MakeResource(
174    content::WebContents* web_contents) {
175  return scoped_ptr<RendererResource>(new TabContentsResource(web_contents));
176}
177
178}  // namespace task_manager
179