This source file includes following definitions.
- UpdateThumbnail
- ProcessCapturedBitmap
- GotSnapshotFromRenderer
- AsyncProcessThumbnail
- load_interrupted_
- Observe
- RenderViewDeleted
- DidStartLoading
- NavigationStopped
- UpdateThumbnailIfNecessary
- RenderViewHostCreated
- WidgetHidden
#include "chrome/browser/thumbnails/thumbnail_tab_helper.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/thumbnails/thumbnail_service.h"
#include "chrome/browser/thumbnails/thumbnail_service_factory.h"
#include "chrome/browser/thumbnails/thumbnailing_algorithm.h"
#include "chrome/browser/thumbnails/thumbnailing_context.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/scrollbar_size.h"
#include "ui/gfx/skbitmap_operations.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
DEFINE_WEB_CONTENTS_USER_DATA_KEY(ThumbnailTabHelper);
class SkBitmap;
using content::RenderViewHost;
using content::RenderWidgetHost;
using content::WebContents;
using thumbnails::ClipResult;
using thumbnails::ThumbnailingContext;
using thumbnails::ThumbnailingAlgorithm;
namespace {
void UpdateThumbnail(const ThumbnailingContext& context,
const SkBitmap& thumbnail) {
gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail);
context.service->SetPageThumbnail(context, image);
VLOG(1) << "Thumbnail taken for " << context.url << ": "
<< context.score.ToString();
}
void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context,
scoped_refptr<ThumbnailingAlgorithm> algorithm,
bool succeeded,
const SkBitmap& bitmap) {
if (!succeeded)
return;
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap);
}
void GotSnapshotFromRenderer(base::Callback<void(const SkBitmap&)> callback,
bool success,
const SkBitmap& bitmap) {
if (success)
callback.Run(bitmap);
}
void AsyncProcessThumbnail(content::WebContents* web_contents,
scoped_refptr<ThumbnailingContext> context,
scoped_refptr<ThumbnailingAlgorithm> algorithm) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
RenderWidgetHost* render_widget_host = web_contents->GetRenderViewHost();
content::RenderWidgetHostView* view = render_widget_host->GetView();
if (!view)
return;
if (!view->IsSurfaceAvailableForCopy()) {
render_widget_host->GetSnapshotFromRenderer(
gfx::Rect(),
base::Bind(GotSnapshotFromRenderer, base::Bind(
&ThumbnailingAlgorithm::ProcessBitmap,
algorithm, context, base::Bind(&UpdateThumbnail))));
return;
}
gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size());
int scrollbar_size = gfx::scrollbar_size();
gfx::Size copy_size;
copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size);
if (copy_rect.IsEmpty())
return;
context->clip_result = algorithm->GetCanvasCopyInfo(
copy_rect.size(),
ui::GetScaleFactorForNativeView(view->GetNativeView()),
©_rect,
&context->requested_copy_size);
render_widget_host->CopyFromBackingStore(
copy_rect,
context->requested_copy_size,
base::Bind(&ProcessCapturedBitmap, context, algorithm),
SkBitmap::kARGB_8888_Config);
}
}
ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents)
: content::WebContentsObserver(contents),
enabled_(true),
load_interrupted_(false) {
registrar_.Add(this,
content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
content::Source<WebContents>(contents));
}
ThumbnailTabHelper::~ThumbnailTabHelper() {
}
void ThumbnailTabHelper::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED:
RenderViewHostCreated(content::Details<RenderViewHost>(details).ptr());
break;
case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED:
if (!*content::Details<bool>(details).ptr())
WidgetHidden(content::Source<RenderWidgetHost>(source).ptr());
break;
default:
NOTREACHED() << "Unexpected notification type: " << type;
}
}
void ThumbnailTabHelper::RenderViewDeleted(
content::RenderViewHost* render_view_host) {
bool registered = registrar_.IsRegistered(
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
content::Source<RenderWidgetHost>(render_view_host));
if (registered) {
registrar_.Remove(
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
content::Source<RenderWidgetHost>(render_view_host));
}
}
void ThumbnailTabHelper::DidStartLoading(
content::RenderViewHost* render_view_host) {
load_interrupted_ = false;
}
void ThumbnailTabHelper::NavigationStopped() {
load_interrupted_ = true;
}
void ThumbnailTabHelper::UpdateThumbnailIfNecessary(
WebContents* web_contents) {
if (!web_contents || web_contents->IsBeingDestroyed())
return;
if (web_contents->GetController().GetPendingEntry())
return;
const GURL& url = web_contents->GetURL();
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
scoped_refptr<thumbnails::ThumbnailService> thumbnail_service =
ThumbnailServiceFactory::GetForProfile(profile);
if (thumbnail_service.get() == NULL ||
!thumbnail_service->ShouldAcquirePageThumbnail(url)) {
return;
}
scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm(
thumbnail_service->GetThumbnailingAlgorithm());
scoped_refptr<ThumbnailingContext> context(new ThumbnailingContext(
web_contents, thumbnail_service.get(), load_interrupted_));
AsyncProcessThumbnail(web_contents, context, algorithm);
}
void ThumbnailTabHelper::RenderViewHostCreated(
content::RenderViewHost* renderer) {
bool registered = registrar_.IsRegistered(
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
content::Source<RenderWidgetHost>(renderer));
if (!registered) {
registrar_.Add(
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
content::Source<RenderWidgetHost>(renderer));
}
}
void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) {
if (!enabled_)
return;
UpdateThumbnailIfNecessary(web_contents());
}