| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/thumbnails/thumbnail_tab_helper.h" | 5 #include "chrome/browser/thumbnails/thumbnail_tab_helper.h" |
| 6 | 6 |
| 7 #include "chrome/browser/browser_process.h" | 7 #include "chrome/browser/browser_process.h" |
| 8 #include "chrome/browser/profiles/profile.h" | 8 #include "chrome/browser/profiles/profile.h" |
| 9 #include "chrome/browser/thumbnails/thumbnail_service.h" | 9 #include "chrome/browser/thumbnails/thumbnail_service.h" |
| 10 #include "chrome/browser/thumbnails/thumbnail_service_factory.h" | 10 #include "chrome/browser/thumbnails/thumbnail_service_factory.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 using thumbnails::ClipResult; | 51 using thumbnails::ClipResult; |
| 52 using thumbnails::ThumbnailingContext; | 52 using thumbnails::ThumbnailingContext; |
| 53 using thumbnails::ThumbnailingAlgorithm; | 53 using thumbnails::ThumbnailingAlgorithm; |
| 54 | 54 |
| 55 namespace { | 55 namespace { |
| 56 | 56 |
| 57 // Feed the constructed thumbnail to the thumbnail service. | 57 // Feed the constructed thumbnail to the thumbnail service. |
| 58 void UpdateThumbnail(const ThumbnailingContext& context, | 58 void UpdateThumbnail(const ThumbnailingContext& context, |
| 59 const SkBitmap& thumbnail) { | 59 const SkBitmap& thumbnail) { |
| 60 gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail); | 60 gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail); |
| 61 context.service->SetPageThumbnail(context, image); | 61 context.service()->SetPageThumbnail(context, image); |
| 62 DVLOG(1) << "Thumbnail taken for " << context.url << ": " | 62 DVLOG(1) << "Thumbnail taken for " << context.GetURL() << ": " |
| 63 << context.score.ToString(); | 63 << context.score().ToString(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context, | 66 void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context, |
| 67 scoped_refptr<ThumbnailingAlgorithm> algorithm, | 67 scoped_refptr<ThumbnailingAlgorithm> algorithm, |
| 68 const SkBitmap& bitmap, | 68 const SkBitmap& bitmap, |
| 69 content::ReadbackResponse response) { | 69 content::ReadbackResponse response) { |
| 70 // Was the web contents destroyed before the thumbnail could be generated? |
| 71 if (!context->web_contents()) |
| 72 return; |
| 73 |
| 74 // Balance the IncrementCapturerCount() from UpdateThumbnailIfNecessary(). |
| 75 context->web_contents()->DecrementCapturerCount(); |
| 76 |
| 70 if (response != content::READBACK_SUCCESS) | 77 if (response != content::READBACK_SUCCESS) |
| 71 return; | 78 return; |
| 72 | 79 |
| 73 // On success, we must be on the UI thread (on failure because of shutdown we | 80 // On success, we must be on the UI thread (on failure because of shutdown we |
| 74 // are not on the UI thread). | 81 // are not on the UI thread). |
| 75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 82 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 76 | 83 |
| 77 algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap); | 84 algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap); |
| 78 } | 85 } |
| 79 | 86 |
| 80 void AsyncProcessThumbnail(content::WebContents* web_contents, | 87 void AsyncProcessThumbnail(scoped_refptr<ThumbnailingContext> context, |
| 81 scoped_refptr<ThumbnailingContext> context, | |
| 82 scoped_refptr<ThumbnailingAlgorithm> algorithm) { | 88 scoped_refptr<ThumbnailingAlgorithm> algorithm) { |
| 83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 89 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 84 RenderWidgetHost* render_widget_host = | 90 RenderWidgetHost* render_widget_host = |
| 85 web_contents->GetRenderViewHost()->GetWidget(); | 91 context->web_contents()->GetRenderViewHost()->GetWidget(); |
| 86 content::RenderWidgetHostView* view = render_widget_host->GetView(); | 92 content::RenderWidgetHostView* view = render_widget_host->GetView(); |
| 87 if (!view) | 93 if (!view) |
| 88 return; | 94 return; |
| 89 if (!view->IsSurfaceAvailableForCopy()) | 95 if (!view->IsSurfaceAvailableForCopy()) |
| 90 return; | 96 return; |
| 91 | 97 |
| 92 gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size()); | 98 gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size()); |
| 93 // Clip the pixels that will commonly hold a scrollbar, which looks bad in | 99 // Clip the pixels that will commonly hold a scrollbar, which looks bad in |
| 94 // thumbnails. | 100 // thumbnails. |
| 95 int scrollbar_size = gfx::scrollbar_size(); | 101 int scrollbar_size = gfx::scrollbar_size(); |
| 96 gfx::Size copy_size; | 102 gfx::Size copy_size; |
| 97 copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size); | 103 copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size); |
| 98 | 104 |
| 99 if (copy_rect.IsEmpty()) | 105 if (copy_rect.IsEmpty()) |
| 100 return; | 106 return; |
| 101 | 107 |
| 102 ui::ScaleFactor scale_factor = | 108 ui::ScaleFactor scale_factor = |
| 103 ui::GetSupportedScaleFactor( | 109 ui::GetSupportedScaleFactor( |
| 104 ui::GetScaleFactorForNativeView(view->GetNativeView())); | 110 ui::GetScaleFactorForNativeView(view->GetNativeView())); |
| 105 context->clip_result = algorithm->GetCanvasCopyInfo( | 111 gfx::Size requested_copy_size; |
| 112 context->set_clip_result(algorithm->GetCanvasCopyInfo( |
| 106 copy_rect.size(), | 113 copy_rect.size(), |
| 107 scale_factor, | 114 scale_factor, |
| 108 ©_rect, | 115 ©_rect, |
| 109 &context->requested_copy_size); | 116 &requested_copy_size)); |
| 117 context->set_requested_copy_size(requested_copy_size); |
| 110 render_widget_host->CopyFromBackingStore( | 118 render_widget_host->CopyFromBackingStore( |
| 111 copy_rect, | 119 copy_rect, |
| 112 context->requested_copy_size, | 120 requested_copy_size, |
| 113 base::Bind(&ProcessCapturedBitmap, context, algorithm), | 121 base::Bind(&ProcessCapturedBitmap, context, algorithm), |
| 114 kN32_SkColorType); | 122 kN32_SkColorType); |
| 115 } | 123 } |
| 116 | 124 |
| 117 } // namespace | 125 } // namespace |
| 118 | 126 |
| 119 ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents) | 127 ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents) |
| 120 : content::WebContentsObserver(contents), | 128 : content::WebContentsObserver(contents), |
| 121 enabled_(true), | 129 enabled_(true), |
| 122 load_interrupted_(false) { | 130 load_interrupted_(false) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 | 197 |
| 190 scoped_refptr<thumbnails::ThumbnailService> thumbnail_service = | 198 scoped_refptr<thumbnails::ThumbnailService> thumbnail_service = |
| 191 ThumbnailServiceFactory::GetForProfile(profile); | 199 ThumbnailServiceFactory::GetForProfile(profile); |
| 192 | 200 |
| 193 // Skip if we don't need to update the thumbnail. | 201 // Skip if we don't need to update the thumbnail. |
| 194 if (thumbnail_service.get() == NULL || | 202 if (thumbnail_service.get() == NULL || |
| 195 !thumbnail_service->ShouldAcquirePageThumbnail(url)) { | 203 !thumbnail_service->ShouldAcquirePageThumbnail(url)) { |
| 196 return; | 204 return; |
| 197 } | 205 } |
| 198 | 206 |
| 207 web_contents->IncrementCapturerCount(gfx::Size()); |
| 208 |
| 199 scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm( | 209 scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm( |
| 200 thumbnail_service->GetThumbnailingAlgorithm()); | 210 thumbnail_service->GetThumbnailingAlgorithm()); |
| 201 | 211 |
| 202 scoped_refptr<ThumbnailingContext> context(new ThumbnailingContext( | 212 scoped_refptr<ThumbnailingContext> context(new ThumbnailingContext( |
| 203 web_contents, thumbnail_service.get(), load_interrupted_)); | 213 web_contents, thumbnail_service.get(), load_interrupted_)); |
| 204 AsyncProcessThumbnail(web_contents, context, algorithm); | 214 AsyncProcessThumbnail(context, algorithm); |
| 205 } | 215 } |
| 206 | 216 |
| 207 void ThumbnailTabHelper::RenderViewHostCreated( | 217 void ThumbnailTabHelper::RenderViewHostCreated( |
| 208 content::RenderViewHost* renderer) { | 218 content::RenderViewHost* renderer) { |
| 209 // NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED is really a new | 219 // NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED is really a new |
| 210 // RenderView, not RenderViewHost, and there is no good way to get | 220 // RenderView, not RenderViewHost, and there is no good way to get |
| 211 // notifications of RenderViewHosts. So just be tolerant of re-registrations. | 221 // notifications of RenderViewHosts. So just be tolerant of re-registrations. |
| 212 bool registered = registrar_.IsRegistered( | 222 bool registered = registrar_.IsRegistered( |
| 213 this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | 223 this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, |
| 214 content::Source<RenderWidgetHost>(renderer->GetWidget())); | 224 content::Source<RenderWidgetHost>(renderer->GetWidget())); |
| 215 if (!registered) { | 225 if (!registered) { |
| 216 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | 226 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, |
| 217 content::Source<RenderWidgetHost>(renderer->GetWidget())); | 227 content::Source<RenderWidgetHost>(renderer->GetWidget())); |
| 218 } | 228 } |
| 219 } | 229 } |
| 220 | 230 |
| 221 void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) { | 231 void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) { |
| 222 if (!enabled_) | 232 if (!enabled_) |
| 223 return; | 233 return; |
| 224 UpdateThumbnailIfNecessary(web_contents()); | 234 UpdateThumbnailIfNecessary(web_contents()); |
| 225 } | 235 } |
| OLD | NEW |