15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/thumbnails/thumbnail_tab_helper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/thumbnails/render_widget_snapshot_taker.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/thumbnails/thumbnail_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/thumbnails/thumbnail_service_factory.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/thumbnails/thumbnailing_algorithm.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/thumbnails/thumbnailing_context.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/color_utils.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size_conversions.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/scrollbar_size.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skbitmap_operations.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(ThumbnailTabHelper);
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SkBitmap;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Overview
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class provides a service for updating thumbnails to be used in
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "Most visited" section of the new tab page. The service can be started
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by StartThumbnailing(). The current algorithm of the service is as
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple as follows:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    When a renderer is about to be hidden (this usually occurs when the
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    current tab is closed or another tab is clicked), update the
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    thumbnail for the tab rendered by the renderer, if needed. The
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    heuristics to judge whether or not to update the thumbnail is
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    implemented in ShouldUpdateThumbnail().
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using thumbnails::ClipResult;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using thumbnails::ThumbnailingContext;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using thumbnails::ThumbnailingAlgorithm;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Feed the constructed thumbnail to the thumbnail service.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UpdateThumbnail(const ThumbnailingContext& context,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const SkBitmap& thumbnail) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context.service->SetPageThumbnail(context, image);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Thumbnail taken for " << context.url << ": "
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << context.score.ToString();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           scoped_refptr<ThumbnailingAlgorithm> algorithm,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bool succeeded,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const SkBitmap& bitmap) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!succeeded)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GotSnapshotFromRenderer(base::Callback<void(const SkBitmap&)> callback,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             bool success,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const SkBitmap& bitmap) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (success)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(bitmap);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AsyncProcessThumbnail(content::WebContents* web_contents,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           scoped_refptr<ThumbnailingContext> context,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           scoped_refptr<ThumbnailingAlgorithm> algorithm) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderWidgetHost* render_widget_host = web_contents->GetRenderViewHost();
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::RenderWidgetHostView* view = render_widget_host->GetView();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!view)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!view->IsSurfaceAvailableForCopy()) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // On Windows XP and possibly due to driver issues, neither the backing
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // store nor the compositing surface is available in the browser when
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // accelerated compositing is active, so ask the renderer to send a snapshot
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // for creating the thumbnail.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_widget_host->GetSnapshotFromRenderer(
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect(),
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(GotSnapshotFromRenderer, base::Bind(
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &ThumbnailingAlgorithm::ProcessBitmap,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          algorithm, context, base::Bind(&UpdateThumbnail))));
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size());
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clip the pixels that will commonly hold a scrollbar, which looks bad in
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // thumbnails.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int scrollbar_size = gfx::scrollbar_size();
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size copy_size;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (copy_rect.IsEmpty())
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context->clip_result = algorithm->GetCanvasCopyInfo(
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      copy_rect.size(),
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::GetScaleFactorForNativeView(view->GetNativeView()),
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &copy_rect,
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &context->requested_copy_size);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_widget_host->CopyFromBackingStore(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      copy_rect,
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      context->requested_copy_size,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ProcessCapturedBitmap, context, algorithm));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : content::WebContentsObserver(contents),
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enabled_(true),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_interrupted_(false) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Even though we deal in RenderWidgetHosts, we only care about its
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subclass, RenderViewHost when it is in a tab. We don't make thumbnails
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for RenderViewHosts that aren't in tabs, or RenderWidgetHosts that
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // aren't views like select popups.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<WebContents>(contents));
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailTabHelper::~ThumbnailTabHelper() {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ThumbnailTabHelper::Observe(int type,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationSource& source,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationDetails& details) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderViewHostCreated(content::Details<RenderViewHost>(details).ptr());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!*content::Details<bool>(details).ptr())
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WidgetHidden(content::Source<RenderWidgetHost>(source).ptr());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected notification type: " << type;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThumbnailTabHelper::RenderViewDeleted(
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::RenderViewHost* render_view_host) {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_browser_process->GetRenderWidgetSnapshotTaker()->CancelSnapshot(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      render_view_host);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool registered = registrar_.IsRegistered(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<RenderWidgetHost>(render_view_host));
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (registered) {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    registrar_.Remove(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Source<RenderWidgetHost>(render_view_host));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThumbnailTabHelper::DidStartLoading(
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::RenderViewHost* render_view_host) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  load_interrupted_ = false;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThumbnailTabHelper::StopNavigation() {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This function gets called when the page loading is interrupted by the
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // stop button.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  load_interrupted_ = true;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ThumbnailTabHelper::UpdateThumbnailIfNecessary(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* web_contents) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroying a WebContents may trigger it to be hidden, prompting a snapshot
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which would be unwise to attempt <http://crbug.com/130097>. If the
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebContents is in the middle of destruction, do not risk it.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!web_contents || web_contents->IsBeingDestroyed())
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip if a pending entry exists. WidgetHidden can be called while navigating
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pages and this is not a time when thumbnails should be generated.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (web_contents->GetController().GetPendingEntry())
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url = web_contents->GetURL();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile =
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile::FromBrowserContext(web_contents->GetBrowserContext());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<thumbnails::ThumbnailService> thumbnail_service =
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ThumbnailServiceFactory::GetForProfile(profile);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip if we don't need to update the thumbnail.
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (thumbnail_service.get() == NULL ||
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !thumbnail_service->ShouldAcquirePageThumbnail(url)) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm(
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      thumbnail_service->GetThumbnailingAlgorithm());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<ThumbnailingContext> context(new ThumbnailingContext(
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      web_contents, thumbnail_service.get(), load_interrupted_));
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AsyncProcessThumbnail(web_contents, context, algorithm);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThumbnailTabHelper::RenderViewHostCreated(
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::RenderViewHost* renderer) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED is really a new
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // RenderView, not RenderViewHost, and there is no good way to get
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // notifications of RenderViewHosts. So just be tolerant of re-registrations.
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool registered = registrar_.IsRegistered(
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<RenderWidgetHost>(renderer));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!registered) {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    registrar_.Add(
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this,
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Source<RenderWidgetHost>(renderer));
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!enabled_)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateThumbnailIfNecessary(web_contents());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
244