text: // Copyright 2014 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/task_manager/tab_contents_information.h"
  
  #include <stddef.h>
  
  #include "base/callback.h"
  #include "base/macros.h"
  #include "base/strings/utf_string_conversions.h"
  #include "chrome/browser/browser_process.h"
  #include "chrome/browser/devtools/devtools_window.h"
  #include "chrome/browser/favicon/favicon_utils.h"
  #include "chrome/browser/prerender/prerender_manager.h"
  #include "chrome/browser/prerender/prerender_manager_factory.h"
  #include "chrome/browser/profiles/profile.h"
  #include "chrome/browser/profiles/profile_manager.h"
  #include "chrome/browser/task_manager/renderer_resource.h"
  #include "chrome/browser/task_manager/task_manager_util.h"
  #include "chrome/browser/ui/browser.h"
  #include "chrome/browser/ui/browser_finder.h"
  #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
  #include "components/favicon/content/content_favicon_driver.h"
  #include "content/public/browser/render_process_host.h"
  #include "content/public/browser/web_contents.h"
  #include "extensions/browser/extension_registry.h"
  #include "extensions/browser/process_map.h"
  #include "extensions/common/constants.h"
  #include "extensions/common/extension_set.h"
  #include "grit/theme_resources.h"
  #include "ui/base/l10n/l10n_util.h"
  #include "ui/base/resource/resource_bundle.h"
  #include "ui/gfx/image/image_skia.h"
  
  using content::WebContents;
  
  namespace task_manager {
  
  namespace {
  
  // Returns true if the WebContents is currently owned by the prerendering
  // manager.
  bool IsContentsPrerendering(WebContents* web_contents) {
    Profile* profile =
        Profile::FromBrowserContext(web_contents->GetBrowserContext());
    prerender::PrerenderManager* prerender_manager =
        prerender::PrerenderManagerFactory::GetForProfile(profile);
    return prerender_manager &&
           prerender_manager->IsWebContentsPrerendering(web_contents, NULL);
  }
  
  }  // namespace
  
  // Tracks a single tab contents, prerendered page, or Instant page.
  class TabContentsResource : public RendererResource {
   public:
    explicit TabContentsResource(content::WebContents* web_contents);
    ~TabContentsResource() override;
  
    // Resource methods:
    Type GetType() const override;
    base::string16 GetTitle() const override;
    gfx::ImageSkia GetIcon() const override;
    content::WebContents* GetWebContents() const override;
  
   private:
    // Returns true if contains content rendered by an extension.
    bool HostsExtension() const;
  
    static gfx::ImageSkia* prerender_icon_;
    content::WebContents* web_contents_;
    Profile* profile_;
  
    DISALLOW_COPY_AND_ASSIGN(TabContentsResource);
  };
  
  gfx::ImageSkia* TabContentsResource::prerender_icon_ = NULL;
  
  TabContentsResource::TabContentsResource(WebContents* web_contents)
      : RendererResource(web_contents->GetRenderProcessHost()->GetHandle(),
                         web_contents->GetRenderViewHost()),
        web_contents_(web_contents),
        profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())) {
    if (!prerender_icon_) {
      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
      prerender_icon_ = rb.GetImageSkiaNamed(IDR_PRERENDER);
    }
  }
  
  TabContentsResource::~TabContentsResource() {}
  
  bool TabContentsResource::HostsExtension() const {
    return web_contents_->GetURL().SchemeIs(extensions::kExtensionScheme);
  }
  
  Resource::Type TabContentsResource::GetType() const {
    // A tab that loads an extension URL is considered to be an extension for
    // these purposes, although it's tracked as a TabContentsResource.
    return HostsExtension() ? EXTENSION : RENDERER;
  }
  
  base::string16 TabContentsResource::GetTitle() const {
    // Fall back on the URL if there's no title.
    GURL url = web_contents_->GetURL();
    base::string16 tab_title = util::GetTitleFromWebContents(web_contents_);
  
    // Only classify as an app if the URL is an app and the tab is hosting an
    // extension process.  (It's possible to be showing the URL from before it
    // was installed as an app.)
    extensions::ProcessMap* process_map = extensions::ProcessMap::Get(profile_);
    bool is_app =
        extensions::ExtensionRegistry::Get(profile_)
            ->enabled_extensions().GetAppByURL(url) != NULL &&
        process_map->Contains(web_contents_->GetRenderProcessHost()->GetID());
  
    int message_id = util::GetMessagePrefixID(
        is_app,
        HostsExtension(),
        profile_->IsOffTheRecord(),
        IsContentsPrerendering(web_contents_),
        false);  // is_background
    return l10n_util::GetStringFUTF16(message_id, tab_title);
  }
  
  gfx::ImageSkia TabContentsResource::GetIcon() const {
    if (IsContentsPrerendering(web_contents_))
      return *prerender_icon_;
    favicon::CreateContentFaviconDriverForWebContents(web_contents_);
    return favicon::ContentFaviconDriver::FromWebContents(web_contents_)
        ->GetFavicon()
        .AsImageSkia();
  }
  
  WebContents* TabContentsResource::GetWebContents() const {
    return web_contents_;
  }
  
  TabContentsInformation::TabContentsInformation() {}
  
  TabContentsInformation::~TabContentsInformation() {}
  
  bool TabContentsInformation::CheckOwnership(
      content::WebContents* web_contents) {
    return chrome::FindBrowserWithWebContents(web_contents) ||
           DevToolsWindow::IsDevToolsWindow(web_contents) ||
           IsContentsPrerendering(web_contents);
  }
  
  void TabContentsInformation::GetAll(const NewWebContentsCallback& callback) {
    for (TabContentsIterator iterator; !iterator.done(); iterator.Next()) {
      callback.Run(*iterator);
      WebContents* devtools =
          DevToolsWindow::GetInTabWebContents(*iterator, NULL);
      if (devtools)
        callback.Run(devtools);
    }
  
    // Because a WebContents* may start its life as a prerender, and later be
    // put into a tab, this class tracks the prerender contents in the same
    // way as the tab contents.
    std::vector<Profile*> profiles(
        g_browser_process->profile_manager()->GetLoadedProfiles());
    for (size_t i = 0; i < profiles.size(); ++i) {
      prerender::PrerenderManager* prerender_manager =
          prerender::PrerenderManagerFactory::GetForProfile(profiles[i]);
      if (prerender_manager) {
        const std::vector<content::WebContents*> contentses =
            prerender_manager->GetAllPrerenderingContents();
        for (size_t j = 0; j < contentses.size(); ++j)
          callback.Run(contentses[j]);
      }
    }
  }
  
  std::unique_ptr<RendererResource> TabContentsInformation::MakeResource(
      content::WebContents* web_contents) {
    return std::unique_ptr<RendererResource>(
        new TabContentsResource(web_contents));
  }
  
  }  // namespace task_manager
  