| 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 |