Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Unified Diff: chrome/browser/thumbnails/thumbnail_tab_helper.cc

Issue 1461463002: Reland fix for thumbnail generation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rework IsFullscreenForTabOrPending() (per mia@). Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/thumbnails/thumbnail_tab_helper.cc
diff --git a/chrome/browser/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/thumbnails/thumbnail_tab_helper.cc
index a5de4ee96d333b457f869314119c46252b4aef3a..93f6f42dc8a3eb3d2a5250cbf6ce5ba0e8c617e7 100644
--- a/chrome/browser/thumbnails/thumbnail_tab_helper.cc
+++ b/chrome/browser/thumbnails/thumbnail_tab_helper.cc
@@ -53,73 +53,10 @@ using thumbnails::ClipResult;
using thumbnails::ThumbnailingContext;
using thumbnails::ThumbnailingAlgorithm;
-namespace {
-
-// Feed the constructed thumbnail to the thumbnail service.
-void UpdateThumbnail(const ThumbnailingContext& context,
- const SkBitmap& thumbnail) {
- gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail);
- context.service->SetPageThumbnail(context, image);
- DVLOG(1) << "Thumbnail taken for " << context.url << ": "
- << context.score.ToString();
-}
-
-void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context,
- scoped_refptr<ThumbnailingAlgorithm> algorithm,
- const SkBitmap& bitmap,
- content::ReadbackResponse response) {
- if (response != content::READBACK_SUCCESS)
- return;
-
- // On success, we must be on the UI thread (on failure because of shutdown we
- // are not on the UI thread).
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap);
-}
-
-void AsyncProcessThumbnail(content::WebContents* web_contents,
- scoped_refptr<ThumbnailingContext> context,
- scoped_refptr<ThumbnailingAlgorithm> algorithm) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- RenderWidgetHost* render_widget_host =
- web_contents->GetRenderViewHost()->GetWidget();
- content::RenderWidgetHostView* view = render_widget_host->GetView();
- if (!view)
- return;
- if (!view->IsSurfaceAvailableForCopy())
- return;
-
- gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size());
- // Clip the pixels that will commonly hold a scrollbar, which looks bad in
- // thumbnails.
- int scrollbar_size = gfx::scrollbar_size();
- gfx::Size copy_size;
- copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size);
-
- if (copy_rect.IsEmpty())
- return;
-
- ui::ScaleFactor scale_factor =
- ui::GetSupportedScaleFactor(
- ui::GetScaleFactorForNativeView(view->GetNativeView()));
- context->clip_result = algorithm->GetCanvasCopyInfo(
- copy_rect.size(),
- scale_factor,
- &copy_rect,
- &context->requested_copy_size);
- render_widget_host->CopyFromBackingStore(
- copy_rect,
- context->requested_copy_size,
- base::Bind(&ProcessCapturedBitmap, context, algorithm),
- kN32_SkColorType);
-}
-
-} // namespace
-
ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents)
: content::WebContentsObserver(contents),
- load_interrupted_(false) {
+ load_interrupted_(false),
+ weak_factory_(this) {
// Even though we deal in RenderWidgetHosts, we only care about its
// subclass, RenderViewHost when it is in a tab. We don't make thumbnails
// for RenderViewHosts that aren't in tabs, or RenderWidgetHosts that
@@ -172,20 +109,29 @@ void ThumbnailTabHelper::NavigationStopped() {
load_interrupted_ = true;
}
-void ThumbnailTabHelper::UpdateThumbnailIfNecessary(
- WebContents* web_contents) {
+void ThumbnailTabHelper::UpdateThumbnailIfNecessary() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // Ignore thumbnail update requests if one is already in progress. This can
+ // happen at the end of thumbnail generation when
+ // CleanUpFromThumbnailGeneration() calls DecrementCapturerCount(), triggering
+ // a call to content::WebContentsImpl::WasHidden() which eventually calls
+ // ThumbnailTabHelper::UpdateThumbnailIfNecessary().
+ if (thumbnailing_context_) {
+ return;
+ }
+
// Destroying a WebContents may trigger it to be hidden, prompting a snapshot
// which would be unwise to attempt <http://crbug.com/130097>. If the
// WebContents is in the middle of destruction, do not risk it.
- if (!web_contents || web_contents->IsBeingDestroyed())
+ if (!web_contents() || web_contents()->IsBeingDestroyed())
return;
// Skip if a pending entry exists. WidgetHidden can be called while navigating
// pages and this is not a time when thumbnails should be generated.
- if (web_contents->GetController().GetPendingEntry())
+ if (web_contents()->GetController().GetPendingEntry())
return;
- const GURL& url = web_contents->GetURL();
+ const GURL& url = web_contents()->GetURL();
Profile* profile =
- Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ Profile::FromBrowserContext(web_contents()->GetBrowserContext());
scoped_refptr<thumbnails::ThumbnailService> thumbnail_service =
ThumbnailServiceFactory::GetForProfile(profile);
@@ -196,12 +142,102 @@ void ThumbnailTabHelper::UpdateThumbnailIfNecessary(
return;
}
+ // Prevent the web contents from disappearing before the async thumbnail
+ // generation code executes. See https://crbug.com/530707 .
+ web_contents()->IncrementCapturerCount(gfx::Size());
+
+ AsyncProcessThumbnail(thumbnail_service);
+}
+
+void ThumbnailTabHelper::AsyncProcessThumbnail(
+ scoped_refptr<thumbnails::ThumbnailService> thumbnail_service) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ RenderWidgetHost* render_widget_host =
+ web_contents()->GetRenderViewHost()->GetWidget();
+ content::RenderWidgetHostView* view = render_widget_host->GetView();
+ if (!view || !view->IsSurfaceAvailableForCopy()) {
+ return;
+ }
+
+ gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size());
+ // Clip the pixels that will commonly hold a scrollbar, which looks bad in
+ // thumbnails.
+ int scrollbar_size = gfx::scrollbar_size();
+ gfx::Size copy_size;
+ copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size);
+
+ if (copy_rect.IsEmpty()) {
+ 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);
+ thumbnailing_context_ = new ThumbnailingContext(web_contents(),
+ thumbnail_service.get(),
+ load_interrupted_);
+
+ ui::ScaleFactor scale_factor =
+ ui::GetSupportedScaleFactor(
+ ui::GetScaleFactorForNativeView(view->GetNativeView()));
+ thumbnailing_context_->clip_result = algorithm->GetCanvasCopyInfo(
+ copy_rect.size(),
+ scale_factor,
+ &copy_rect,
+ &thumbnailing_context_->requested_copy_size);
+ render_widget_host->CopyFromBackingStore(
+ copy_rect,
+ thumbnailing_context_->requested_copy_size,
+ base::Bind(&ThumbnailTabHelper::ProcessCapturedBitmap,
+ weak_factory_.GetWeakPtr(),
+ algorithm),
+ kN32_SkColorType);
+}
+
+void ThumbnailTabHelper::ProcessCapturedBitmap(
+ scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm,
+ const SkBitmap& bitmap,
+ content::ReadbackResponse response) {
+ if (response == content::READBACK_SUCCESS) {
+ // On success, we must be on the UI thread.
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ algorithm->ProcessBitmap(thumbnailing_context_,
+ base::Bind(&ThumbnailTabHelper::UpdateThumbnail,
+ weak_factory_.GetWeakPtr()),
+ bitmap);
+ } else {
+ // On failure because of shutdown we are not on the UI thread, so ensure
+ // that cleanup happens on that thread.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&ThumbnailTabHelper::CleanUpFromThumbnailGeneration,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+void ThumbnailTabHelper::CleanUpFromThumbnailGeneration() {
+ if (web_contents()) {
+ // Balance the call to IncrementCapturerCount() made in
+ // UpdateThumbnailIfNecessary().
+ web_contents()->DecrementCapturerCount();
+ }
+
+ // Make a note that thumbnail generation is complete.
+ thumbnailing_context_ = nullptr;
+}
+
+void ThumbnailTabHelper::UpdateThumbnail(
+ const thumbnails::ThumbnailingContext& context,
+ const SkBitmap& thumbnail) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // Feed the constructed thumbnail to the thumbnail service.
+ gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail);
+ context.service->SetPageThumbnail(context, image);
+ DVLOG(1) << "Thumbnail taken for " << context.url << ": "
+ << context.score.ToString();
+
+ CleanUpFromThumbnailGeneration();
}
void ThumbnailTabHelper::RenderViewHostCreated(
@@ -219,5 +255,5 @@ void ThumbnailTabHelper::RenderViewHostCreated(
}
void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) {
- UpdateThumbnailIfNecessary(web_contents());
+ UpdateThumbnailIfNecessary();
}
« no previous file with comments | « chrome/browser/thumbnails/thumbnail_tab_helper.h ('k') | chrome/browser/ui/exclusive_access/fullscreen_controller.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698