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 | |
65 // Now that we're completely finished with the web contents, balance the | |
66 // IncrementCapturerCount() from UpdateThumbnailIfNecessary(). | |
67 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
Lei Zhang
2015/11/18 18:06:43
This generally should be at the top of the functio
shrike
2015/11/18 18:20:16
I actually wasn't sure if it was needed at all (bu
Lei Zhang
2015/11/18 18:24:00
Move it to the top.
| |
68 context.web_contents()->DecrementCapturerCount(); | |
64 } | 69 } |
65 | 70 |
66 void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context, | 71 void ProcessCapturedBitmap(scoped_refptr<ThumbnailingContext> context, |
67 scoped_refptr<ThumbnailingAlgorithm> algorithm, | 72 scoped_refptr<ThumbnailingAlgorithm> algorithm, |
68 const SkBitmap& bitmap, | 73 const SkBitmap& bitmap, |
69 content::ReadbackResponse response) { | 74 content::ReadbackResponse response) { |
70 if (response != content::READBACK_SUCCESS) | 75 // Was the web contents destroyed before the thumbnail could be generated? |
76 if (!context->web_contents()) | |
71 return; | 77 return; |
72 | 78 |
79 if (response != content::READBACK_SUCCESS) { | |
80 // Balance the IncrementCapturerCount() from UpdateThumbnailIfNecessary(). | |
81 context->web_contents()->DecrementCapturerCount(); | |
82 return; | |
83 } | |
84 | |
73 // On success, we must be on the UI thread (on failure because of shutdown we | 85 // On success, we must be on the UI thread (on failure because of shutdown we |
74 // are not on the UI thread). | 86 // are not on the UI thread). |
75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 87 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
76 | 88 |
77 algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap); | 89 algorithm->ProcessBitmap(context, base::Bind(&UpdateThumbnail), bitmap); |
78 } | 90 } |
79 | 91 |
80 void AsyncProcessThumbnail(content::WebContents* web_contents, | 92 void AsyncProcessThumbnail(scoped_refptr<ThumbnailingContext> context, |
81 scoped_refptr<ThumbnailingContext> context, | |
82 scoped_refptr<ThumbnailingAlgorithm> algorithm) { | 93 scoped_refptr<ThumbnailingAlgorithm> algorithm) { |
83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 94 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
84 RenderWidgetHost* render_widget_host = | 95 RenderWidgetHost* render_widget_host = |
85 web_contents->GetRenderViewHost()->GetWidget(); | 96 context->web_contents()->GetRenderViewHost()->GetWidget(); |
86 content::RenderWidgetHostView* view = render_widget_host->GetView(); | 97 content::RenderWidgetHostView* view = render_widget_host->GetView(); |
87 if (!view) | 98 if (!view) |
88 return; | 99 return; |
89 if (!view->IsSurfaceAvailableForCopy()) | 100 if (!view->IsSurfaceAvailableForCopy()) |
90 return; | 101 return; |
91 | 102 |
92 gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size()); | 103 gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size()); |
93 // Clip the pixels that will commonly hold a scrollbar, which looks bad in | 104 // Clip the pixels that will commonly hold a scrollbar, which looks bad in |
94 // thumbnails. | 105 // thumbnails. |
95 int scrollbar_size = gfx::scrollbar_size(); | 106 int scrollbar_size = gfx::scrollbar_size(); |
96 gfx::Size copy_size; | 107 gfx::Size copy_size; |
97 copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size); | 108 copy_rect.Inset(0, 0, scrollbar_size, scrollbar_size); |
98 | 109 |
99 if (copy_rect.IsEmpty()) | 110 if (copy_rect.IsEmpty()) |
100 return; | 111 return; |
101 | 112 |
102 ui::ScaleFactor scale_factor = | 113 ui::ScaleFactor scale_factor = |
103 ui::GetSupportedScaleFactor( | 114 ui::GetSupportedScaleFactor( |
104 ui::GetScaleFactorForNativeView(view->GetNativeView())); | 115 ui::GetScaleFactorForNativeView(view->GetNativeView())); |
105 context->clip_result = algorithm->GetCanvasCopyInfo( | 116 gfx::Size requested_copy_size; |
117 context->set_clip_result(algorithm->GetCanvasCopyInfo( | |
106 copy_rect.size(), | 118 copy_rect.size(), |
107 scale_factor, | 119 scale_factor, |
108 ©_rect, | 120 ©_rect, |
109 &context->requested_copy_size); | 121 &requested_copy_size)); |
122 context->set_requested_copy_size(requested_copy_size); | |
110 render_widget_host->CopyFromBackingStore( | 123 render_widget_host->CopyFromBackingStore( |
111 copy_rect, | 124 copy_rect, |
112 context->requested_copy_size, | 125 requested_copy_size, |
113 base::Bind(&ProcessCapturedBitmap, context, algorithm), | 126 base::Bind(&ProcessCapturedBitmap, context, algorithm), |
114 kN32_SkColorType); | 127 kN32_SkColorType); |
115 } | 128 } |
116 | 129 |
117 } // namespace | 130 } // namespace |
118 | 131 |
119 ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents) | 132 ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents) |
120 : content::WebContentsObserver(contents), | 133 : content::WebContentsObserver(contents), |
121 load_interrupted_(false) { | 134 load_interrupted_(false) { |
122 // Even though we deal in RenderWidgetHosts, we only care about its | 135 // Even though we deal in RenderWidgetHosts, we only care about its |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 | 201 |
189 scoped_refptr<thumbnails::ThumbnailService> thumbnail_service = | 202 scoped_refptr<thumbnails::ThumbnailService> thumbnail_service = |
190 ThumbnailServiceFactory::GetForProfile(profile); | 203 ThumbnailServiceFactory::GetForProfile(profile); |
191 | 204 |
192 // Skip if we don't need to update the thumbnail. | 205 // Skip if we don't need to update the thumbnail. |
193 if (thumbnail_service.get() == NULL || | 206 if (thumbnail_service.get() == NULL || |
194 !thumbnail_service->ShouldAcquirePageThumbnail(url)) { | 207 !thumbnail_service->ShouldAcquirePageThumbnail(url)) { |
195 return; | 208 return; |
196 } | 209 } |
197 | 210 |
211 web_contents->IncrementCapturerCount(gfx::Size()); | |
212 // Stop responding to notifications. It turns out that the corresponding | |
213 // DecrementCapturerCount() can trigger a call to | |
214 // content::WebContentsImpl::WasHidden(), which eventually calls | |
215 // ThumbnailTabHelper::UpdateThumbnailIfNecessary(), starting the thumbnail | |
216 // generation process all over again. | |
217 registrar_.RemoveAll(); | |
Lei Zhang
2015/11/18 18:06:43
Is ThumbnailTabHelper one-shot? If not, then this
shrike
2015/11/18 18:20:16
It appears to be one per web contents (tab_helpers
Lei Zhang
2015/11/18 18:24:00
That I understand. My question is, will a Thumbnai
shrike
2015/11/18 19:18:06
Sorry (need more coffee).
My assumption in turnin
| |
218 | |
198 scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm( | 219 scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm( |
199 thumbnail_service->GetThumbnailingAlgorithm()); | 220 thumbnail_service->GetThumbnailingAlgorithm()); |
200 | 221 |
201 scoped_refptr<ThumbnailingContext> context(new ThumbnailingContext( | 222 scoped_refptr<ThumbnailingContext> context(new ThumbnailingContext( |
202 web_contents, thumbnail_service.get(), load_interrupted_)); | 223 web_contents, thumbnail_service.get(), load_interrupted_)); |
203 AsyncProcessThumbnail(web_contents, context, algorithm); | 224 AsyncProcessThumbnail(context, algorithm); |
204 } | 225 } |
205 | 226 |
206 void ThumbnailTabHelper::RenderViewHostCreated( | 227 void ThumbnailTabHelper::RenderViewHostCreated( |
207 content::RenderViewHost* renderer) { | 228 content::RenderViewHost* renderer) { |
208 // NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED is really a new | 229 // NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED is really a new |
209 // RenderView, not RenderViewHost, and there is no good way to get | 230 // RenderView, not RenderViewHost, and there is no good way to get |
210 // notifications of RenderViewHosts. So just be tolerant of re-registrations. | 231 // notifications of RenderViewHosts. So just be tolerant of re-registrations. |
211 bool registered = registrar_.IsRegistered( | 232 bool registered = registrar_.IsRegistered( |
212 this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | 233 this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, |
213 content::Source<RenderWidgetHost>(renderer->GetWidget())); | 234 content::Source<RenderWidgetHost>(renderer->GetWidget())); |
214 if (!registered) { | 235 if (!registered) { |
215 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | 236 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, |
216 content::Source<RenderWidgetHost>(renderer->GetWidget())); | 237 content::Source<RenderWidgetHost>(renderer->GetWidget())); |
217 } | 238 } |
218 } | 239 } |
219 | 240 |
220 void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) { | 241 void ThumbnailTabHelper::WidgetHidden(RenderWidgetHost* widget) { |
221 UpdateThumbnailIfNecessary(web_contents()); | 242 UpdateThumbnailIfNecessary(web_contents()); |
222 } | 243 } |
OLD | NEW |