| 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/tab_contents/thumbnail_generator.h" | 5 #include "chrome/browser/tab_contents/thumbnail_generator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "third_party/skia/include/core/SkBitmap.h" | 30 #include "third_party/skia/include/core/SkBitmap.h" |
| 31 #include "ui/gfx/color_utils.h" | 31 #include "ui/gfx/color_utils.h" |
| 32 #include "ui/gfx/rect.h" | 32 #include "ui/gfx/rect.h" |
| 33 #include "ui/gfx/skbitmap_operations.h" | 33 #include "ui/gfx/skbitmap_operations.h" |
| 34 | 34 |
| 35 // Overview | 35 // Overview |
| 36 // -------- | 36 // -------- |
| 37 // This class provides current thumbnails for tabs. The simplest operation is | 37 // This class provides current thumbnails for tabs. The simplest operation is |
| 38 // when a request for a thumbnail comes in, to grab the backing store and make | 38 // when a request for a thumbnail comes in, to grab the backing store and make |
| 39 // a smaller version of that. Clients of the class can send such a request by | 39 // a smaller version of that. Clients of the class can send such a request by |
| 40 // GetThumbnailForRenderer() and AskForSnapshot(). | 40 // AskForSnapshot(). |
| 41 // | 41 // |
| 42 // The class also provides a service for updating thumbnails to be used in | 42 // The class also provides a service for updating thumbnails to be used in |
| 43 // "Most visited" section of the new tab page. The service can be started | 43 // "Most visited" section of the new tab page. The service can be started |
| 44 // by StartThumbnailing(). The current algorithm of the service is as | 44 // by StartThumbnailing(). The current algorithm of the service is as |
| 45 // simple as follows: | 45 // simple as follows: |
| 46 // | 46 // |
| 47 // When a renderer is about to be hidden (this usually occurs when the | 47 // When a renderer is about to be hidden (this usually occurs when the |
| 48 // current tab is closed or another tab is clicked), update the | 48 // current tab is closed or another tab is clicked), update the |
| 49 // thumbnail for the tab rendered by the renderer, if needed. The | 49 // thumbnail for the tab rendered by the renderer, if needed. The |
| 50 // heuristics to judge whether or not to update the thumbnail is | 50 // heuristics to judge whether or not to update the thumbnail is |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 bmp.height() == result.height()) | 144 bmp.height() == result.height()) |
| 145 bmp.copyTo(&result, SkBitmap::kARGB_8888_Config); | 145 bmp.copyTo(&result, SkBitmap::kARGB_8888_Config); |
| 146 #endif | 146 #endif |
| 147 } | 147 } |
| 148 | 148 |
| 149 HISTOGRAM_TIMES(kThumbnailHistogramName, | 149 HISTOGRAM_TIMES(kThumbnailHistogramName, |
| 150 base::TimeTicks::Now() - begin_compute_thumbnail); | 150 base::TimeTicks::Now() - begin_compute_thumbnail); |
| 151 return result; | 151 return result; |
| 152 } | 152 } |
| 153 | 153 |
| 154 // Creates a downsampled thumbnail for the given RenderWidgetHost's backing | |
| 155 // store. The returned bitmap will be isNull if there was an error creating it. | |
| 156 SkBitmap GetBitmapForRenderWidgetHost( | |
| 157 RenderWidgetHost* render_widget_host, | |
| 158 int desired_width, | |
| 159 int desired_height, | |
| 160 int options, | |
| 161 ThumbnailGenerator::ClipResult* clip_result) { | |
| 162 // base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now(); | |
| 163 | |
| 164 // Get the bitmap as a Skia object so we can resample it. This is a large | |
| 165 // allocation and we can tolerate failure here, so give up if the allocation | |
| 166 // fails. | |
| 167 skia::PlatformCanvas temp_canvas; | |
| 168 content::RenderWidgetHostView* view = render_widget_host->GetView(); | |
| 169 if (!view) | |
| 170 return SkBitmap(); | |
| 171 const gfx::Size copy_size = | |
| 172 GetCopySizeForThumbnail(view->GetViewBounds().size(), | |
| 173 gfx::Size(desired_width, desired_height)); | |
| 174 if (!render_widget_host->CopyFromBackingStore( | |
| 175 gfx::Rect(), copy_size, &temp_canvas)) | |
| 176 return SkBitmap(); | |
| 177 | |
| 178 return CreateThumbnail(skia::GetTopDevice(temp_canvas)->accessBitmap(false), | |
| 179 desired_width, | |
| 180 desired_height, | |
| 181 options, | |
| 182 clip_result); | |
| 183 } | |
| 184 | |
| 185 } // namespace | 154 } // namespace |
| 186 | 155 |
| 187 struct ThumbnailGenerator::AsyncRequestInfo { | 156 struct ThumbnailGenerator::AsyncRequestInfo { |
| 188 ThumbnailReadyCallback callback; | 157 ThumbnailReadyCallback callback; |
| 189 scoped_ptr<TransportDIB> thumbnail_dib; | 158 scoped_ptr<TransportDIB> thumbnail_dib; |
| 190 RenderWidgetHost* renderer; // Not owned. | 159 RenderWidgetHost* renderer; // Not owned. |
| 191 }; | 160 }; |
| 192 | 161 |
| 193 ThumbnailGenerator::ThumbnailGenerator() | 162 ThumbnailGenerator::ThumbnailGenerator() |
| 194 : enabled_(true), | 163 : enabled_(true), |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 renderer_source); | 214 renderer_source); |
| 246 registrar_.Remove( | 215 registrar_.Remove( |
| 247 this, | 216 this, |
| 248 content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | 217 content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, |
| 249 renderer_source); | 218 renderer_source); |
| 250 } | 219 } |
| 251 } | 220 } |
| 252 } | 221 } |
| 253 | 222 |
| 254 void ThumbnailGenerator::AskForSnapshot(RenderWidgetHost* renderer, | 223 void ThumbnailGenerator::AskForSnapshot(RenderWidgetHost* renderer, |
| 255 bool prefer_backing_store, | |
| 256 const ThumbnailReadyCallback& callback, | 224 const ThumbnailReadyCallback& callback, |
| 257 gfx::Size page_size, | 225 gfx::Size page_size, |
| 258 gfx::Size desired_size) { | 226 gfx::Size desired_size) { |
| 259 if (prefer_backing_store) { | |
| 260 // We were able to find a non-null backing store for this renderer, so | |
| 261 // we'll go with it. | |
| 262 SkBitmap first_try = GetBitmapForRenderWidgetHost( | |
| 263 renderer, desired_size.width(), desired_size.height(), kNoOptions, | |
| 264 NULL); | |
| 265 if (!first_try.isNull()) { | |
| 266 callback.Run(first_try); | |
| 267 return; | |
| 268 } | |
| 269 // Now, if the backing store didn't exist, we will still try and | |
| 270 // render asynchronously. | |
| 271 } | |
| 272 | |
| 273 // We are going to render the thumbnail asynchronously now, so keep | 227 // We are going to render the thumbnail asynchronously now, so keep |
| 274 // this callback for later lookup when the rendering is done. | 228 // this callback for later lookup when the rendering is done. |
| 275 static int sequence_num = 0; | 229 static int sequence_num = 0; |
| 276 sequence_num++; | 230 sequence_num++; |
| 277 scoped_ptr<TransportDIB> thumbnail_dib(TransportDIB::Create( | 231 scoped_ptr<TransportDIB> thumbnail_dib(TransportDIB::Create( |
| 278 desired_size.width() * desired_size.height() * 4, sequence_num)); | 232 desired_size.width() * desired_size.height() * 4, sequence_num)); |
| 279 | 233 |
| 280 #if defined(USE_X11) | 234 #if defined(USE_X11) |
| 281 // TODO: IPC a handle to the renderer like Windows. | 235 // TODO: IPC a handle to the renderer like Windows. |
| 282 // http://code.google.com/p/chromium/issues/detail?id=89777 | 236 // http://code.google.com/p/chromium/issues/detail?id=89777 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 312 NOTREACHED() << "Callback already registered?"; | 266 NOTREACHED() << "Callback already registered?"; |
| 313 return; | 267 return; |
| 314 } | 268 } |
| 315 | 269 |
| 316 renderer->PaintAtSize( | 270 renderer->PaintAtSize( |
| 317 renderer_dib_handle, sequence_num, page_size, desired_size); | 271 renderer_dib_handle, sequence_num, page_size, desired_size); |
| 318 | 272 |
| 319 #endif // defined(USE_X11) | 273 #endif // defined(USE_X11) |
| 320 } | 274 } |
| 321 | 275 |
| 322 SkBitmap ThumbnailGenerator::GetThumbnailForRenderer( | |
| 323 RenderWidgetHost* renderer) const { | |
| 324 return GetThumbnailForRendererWithOptions(renderer, kNoOptions, NULL); | |
| 325 } | |
| 326 | |
| 327 SkBitmap ThumbnailGenerator::GetThumbnailForRendererWithOptions( | |
| 328 RenderWidgetHost* renderer, | |
| 329 int options, | |
| 330 ClipResult* clip_result) const { | |
| 331 return GetBitmapForRenderWidgetHost( | |
| 332 renderer, kThumbnailWidth, kThumbnailHeight, options, clip_result); | |
| 333 } | |
| 334 | |
| 335 void ThumbnailGenerator::WidgetDidReceivePaintAtSizeAck( | 276 void ThumbnailGenerator::WidgetDidReceivePaintAtSizeAck( |
| 336 RenderWidgetHost* widget, | 277 RenderWidgetHost* widget, |
| 337 int sequence_num, | 278 int sequence_num, |
| 338 const gfx::Size& size) { | 279 const gfx::Size& size) { |
| 339 // Lookup the callback, run it, and erase it. | 280 // Lookup the callback, run it, and erase it. |
| 340 ThumbnailCallbackMap::iterator item = callback_map_.find(sequence_num); | 281 ThumbnailCallbackMap::iterator item = callback_map_.find(sequence_num); |
| 341 if (item != callback_map_.end()) { | 282 if (item != callback_map_.end()) { |
| 342 TransportDIB* dib = item->second->thumbnail_dib.get(); | 283 TransportDIB* dib = item->second->thumbnail_dib.get(); |
| 343 DCHECK(dib); | 284 DCHECK(dib); |
| 344 if (!dib || !dib->Map()) { | 285 if (!dib || !dib->Map()) { |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 | 553 |
| 613 void ThumbnailGenerator::DidStartLoading() { | 554 void ThumbnailGenerator::DidStartLoading() { |
| 614 load_interrupted_ = false; | 555 load_interrupted_ = false; |
| 615 } | 556 } |
| 616 | 557 |
| 617 void ThumbnailGenerator::StopNavigation() { | 558 void ThumbnailGenerator::StopNavigation() { |
| 618 // This function gets called when the page loading is interrupted by the | 559 // This function gets called when the page loading is interrupted by the |
| 619 // stop button. | 560 // stop button. |
| 620 load_interrupted_ = true; | 561 load_interrupted_ = true; |
| 621 } | 562 } |
| OLD | NEW |