OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 // | 43 // |
44 // When a renderer is about to be hidden (this usually occurs when the | 44 // When a renderer is about to be hidden (this usually occurs when the |
45 // current tab is closed or another tab is clicked), update the | 45 // current tab is closed or another tab is clicked), update the |
46 // thumbnail for the tab rendered by the renderer, if needed. The | 46 // thumbnail for the tab rendered by the renderer, if needed. The |
47 // heuristics to judge whether or not to update the thumbnail is | 47 // heuristics to judge whether or not to update the thumbnail is |
48 // implemented in ShouldUpdateThumbnail(). | 48 // implemented in ShouldUpdateThumbnail(). |
49 // | 49 // |
50 // We'll likely revise the algorithm to improve quality of thumbnails this | 50 // We'll likely revise the algorithm to improve quality of thumbnails this |
51 // service generates. | 51 // service generates. |
52 | 52 |
| 53 using content::WebContents; |
| 54 |
53 namespace { | 55 namespace { |
54 | 56 |
55 static const int kThumbnailWidth = 212; | 57 static const int kThumbnailWidth = 212; |
56 static const int kThumbnailHeight = 132; | 58 static const int kThumbnailHeight = 132; |
57 | 59 |
58 static const char kThumbnailHistogramName[] = "Thumbnail.ComputeMS"; | 60 static const char kThumbnailHistogramName[] = "Thumbnail.ComputeMS"; |
59 | 61 |
60 // Creates a downsampled thumbnail for the given backing store. The returned | 62 // Creates a downsampled thumbnail for the given backing store. The returned |
61 // bitmap will be isNull if there was an error creating it. | 63 // bitmap will be isNull if there was an error creating it. |
62 SkBitmap GetBitmapForBackingStore( | 64 SkBitmap GetBitmapForBackingStore( |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 case content::NOTIFICATION_TAB_CONTENTS_DISCONNECTED: | 355 case content::NOTIFICATION_TAB_CONTENTS_DISCONNECTED: |
354 TabContentsDisconnected(content::Source<TabContents>(source).ptr()); | 356 TabContentsDisconnected(content::Source<TabContents>(source).ptr()); |
355 break; | 357 break; |
356 | 358 |
357 default: | 359 default: |
358 NOTREACHED() << "Unexpected notification type: " << type; | 360 NOTREACHED() << "Unexpected notification type: " << type; |
359 } | 361 } |
360 } | 362 } |
361 | 363 |
362 void ThumbnailGenerator::WidgetHidden(RenderWidgetHost* widget) { | 364 void ThumbnailGenerator::WidgetHidden(RenderWidgetHost* widget) { |
363 // tab_contents_ can be NULL, if StartThumbnailing() is not called, but | 365 // web_contents() can be NULL, if StartThumbnailing() is not called, but |
364 // MonitorRenderer() is called. The use case is found in | 366 // MonitorRenderer() is called. The use case is found in |
365 // chrome/test/base/ui_test_utils.cc. | 367 // chrome/test/base/ui_test_utils.cc. |
366 if (!tab_contents()) | 368 if (!web_contents()) |
367 return; | 369 return; |
368 UpdateThumbnailIfNecessary(tab_contents()); | 370 UpdateThumbnailIfNecessary(web_contents()); |
369 } | 371 } |
370 | 372 |
371 void ThumbnailGenerator::TabContentsDisconnected(TabContents* contents) { | 373 void ThumbnailGenerator::TabContentsDisconnected(TabContents* contents) { |
372 // Go through the existing callbacks, and find any that have the | 374 // Go through the existing callbacks, and find any that have the |
373 // same renderer as this TabContents and remove them so they don't | 375 // same renderer as this TabContents and remove them so they don't |
374 // hang around. | 376 // hang around. |
375 ThumbnailCallbackMap::iterator iterator = callback_map_.begin(); | 377 ThumbnailCallbackMap::iterator iterator = callback_map_.begin(); |
376 RenderWidgetHost* renderer = contents->GetRenderViewHost(); | 378 RenderWidgetHost* renderer = contents->GetRenderViewHost(); |
377 while (iterator != callback_map_.end()) { | 379 while (iterator != callback_map_.end()) { |
378 if (iterator->second->renderer == renderer) { | 380 if (iterator->second->renderer == renderer) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 *clip_result = ThumbnailGenerator::kNotClipped; | 441 *clip_result = ThumbnailGenerator::kNotClipped; |
440 } | 442 } |
441 } | 443 } |
442 | 444 |
443 SkBitmap clipped_bitmap; | 445 SkBitmap clipped_bitmap; |
444 bitmap.extractSubset(&clipped_bitmap, src_rect); | 446 bitmap.extractSubset(&clipped_bitmap, src_rect); |
445 return clipped_bitmap; | 447 return clipped_bitmap; |
446 } | 448 } |
447 | 449 |
448 void ThumbnailGenerator::UpdateThumbnailIfNecessary( | 450 void ThumbnailGenerator::UpdateThumbnailIfNecessary( |
449 TabContents* tab_contents) { | 451 WebContents* web_contents) { |
450 const GURL& url = tab_contents->GetURL(); | 452 const GURL& url = web_contents->GetURL(); |
451 Profile* profile = | 453 Profile* profile = |
452 Profile::FromBrowserContext(tab_contents->GetBrowserContext()); | 454 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
453 history::TopSites* top_sites = profile->GetTopSites(); | 455 history::TopSites* top_sites = profile->GetTopSites(); |
454 // Skip if we don't need to update the thumbnail. | 456 // Skip if we don't need to update the thumbnail. |
455 if (!ShouldUpdateThumbnail(profile, top_sites, url)) | 457 if (!ShouldUpdateThumbnail(profile, top_sites, url)) |
456 return; | 458 return; |
457 | 459 |
458 const int options = ThumbnailGenerator::kClippedThumbnail; | 460 const int options = ThumbnailGenerator::kClippedThumbnail; |
459 ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped; | 461 ThumbnailGenerator::ClipResult clip_result = ThumbnailGenerator::kNotClipped; |
460 SkBitmap thumbnail = GetThumbnailForRendererWithOptions( | 462 SkBitmap thumbnail = GetThumbnailForRendererWithOptions( |
461 tab_contents->GetRenderViewHost(), options, &clip_result); | 463 web_contents->GetRenderViewHost(), options, &clip_result); |
462 // Failed to generate a thumbnail. Maybe the tab is in the background? | 464 // Failed to generate a thumbnail. Maybe the tab is in the background? |
463 if (thumbnail.isNull()) | 465 if (thumbnail.isNull()) |
464 return; | 466 return; |
465 | 467 |
466 // Compute the thumbnail score. | 468 // Compute the thumbnail score. |
467 ThumbnailScore score; | 469 ThumbnailScore score; |
468 score.at_top = | 470 score.at_top = |
469 (tab_contents->GetRenderViewHost()->last_scroll_offset().y() == 0); | 471 (web_contents->GetRenderViewHost()->last_scroll_offset().y() == 0); |
470 score.boring_score = ThumbnailGenerator::CalculateBoringScore(&thumbnail); | 472 score.boring_score = ThumbnailGenerator::CalculateBoringScore(&thumbnail); |
471 score.good_clipping = | 473 score.good_clipping = |
472 (clip_result == ThumbnailGenerator::kTallerThanWide || | 474 (clip_result == ThumbnailGenerator::kTallerThanWide || |
473 clip_result == ThumbnailGenerator::kNotClipped); | 475 clip_result == ThumbnailGenerator::kNotClipped); |
474 score.load_completed = (!load_interrupted_ && !tab_contents->IsLoading()); | 476 score.load_completed = (!load_interrupted_ && !web_contents->IsLoading()); |
475 | 477 |
476 gfx::Image image(new SkBitmap(thumbnail)); | 478 gfx::Image image(new SkBitmap(thumbnail)); |
477 top_sites->SetPageThumbnail(url, &image, score); | 479 top_sites->SetPageThumbnail(url, &image, score); |
478 VLOG(1) << "Thumbnail taken for " << url << ": " << score.ToString(); | 480 VLOG(1) << "Thumbnail taken for " << url << ": " << score.ToString(); |
479 } | 481 } |
480 | 482 |
481 bool ThumbnailGenerator::ShouldUpdateThumbnail(Profile* profile, | 483 bool ThumbnailGenerator::ShouldUpdateThumbnail(Profile* profile, |
482 history::TopSites* top_sites, | 484 history::TopSites* top_sites, |
483 const GURL& url) { | 485 const GURL& url) { |
484 if (!profile || !top_sites) | 486 if (!profile || !top_sites) |
(...skipping 24 matching lines...) Expand all Loading... |
509 | 511 |
510 void ThumbnailGenerator::DidStartLoading() { | 512 void ThumbnailGenerator::DidStartLoading() { |
511 load_interrupted_ = false; | 513 load_interrupted_ = false; |
512 } | 514 } |
513 | 515 |
514 void ThumbnailGenerator::StopNavigation() { | 516 void ThumbnailGenerator::StopNavigation() { |
515 // This function gets called when the page loading is interrupted by the | 517 // This function gets called when the page loading is interrupted by the |
516 // stop button. | 518 // stop button. |
517 load_interrupted_ = true; | 519 load_interrupted_ = true; |
518 } | 520 } |
OLD | NEW |