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