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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_TAB_CONTENTS_THUMBNAIL_GENERATOR_H_ 6 #define CHROME_BROWSER_TAB_CONTENTS_THUMBNAIL_GENERATOR_H_ 7 #pragma once 8 9 #include <map> 10 #include <utility> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/callback.h" 15 #include "base/memory/linked_ptr.h" 16 #include "base/timer.h" 17 #include "content/browser/renderer_host/backing_store.h" 18 #include "content/common/notification_observer.h" 19 #include "content/common/notification_registrar.h" 20 21 class GURL; 22 class Profile; 23 class RenderWidgetHost; 24 class SkBitmap; 25 class TabContents; 26 27 namespace history { 28 class TopSites; 29 } 30 31 class ThumbnailGenerator : NotificationObserver { 32 public: 33 typedef Callback1<const SkBitmap&>::Type ThumbnailReadyCallback; 34 // The result of clipping. This can be used to determine if the 35 // generated thumbnail is good or not. 36 enum ClipResult { 37 // The source image is smaller. 38 kSourceIsSmaller, 39 // Wider than tall, clip horizontally. 40 kWiderThanTall, 41 // Taller than wide, clip vertically. 42 kTallerThanWide, 43 // The source and destination aspect ratios are identical. 44 kNotClipped, 45 }; 46 47 // Bitmasks of options for generating a thumbnail. 48 enum ThumbnailOptions { 49 // No options. 50 kNoOptions = 0, 51 // Request a clipped thumbnail with the aspect ratio preserved. 52 kClippedThumbnail = 1 << 0, 53 }; 54 55 // This class will do nothing until you call StartThumbnailing. 56 ThumbnailGenerator(); 57 ~ThumbnailGenerator(); 58 59 // Ensures that we're properly hooked in to generated thumbnails. This can 60 // be called repeatedly and with wild abandon to no ill effect. 61 void StartThumbnailing(); 62 63 // This registers a callback that can receive the resulting SkBitmap 64 // from the renderer when it is done rendering it. This differs 65 // from GetThumbnailForRenderer in that it may be asynchronous, and 66 // because it will also fetch the bitmap even if the tab is hidden. 67 // In addition, if the renderer has to be invoked, the scaling of 68 // the thumbnail happens on the rendering thread. 69 // 70 // Takes ownership of the callback object. 71 // 72 // If |prefer_backing_store| is set, then the function will try and 73 // use the backing store for the page if it exists. |page_size| is 74 // the size to render the page, and |desired_size| is the size to 75 // scale the resulting rendered page to (which is done efficiently 76 // if done in the rendering thread). If |prefer_backing_store| is 77 // set, and the backing store is used, then the resulting image will 78 // be less then twice the size of the |desired_size| in both 79 // dimensions, but might not be the exact size requested. 80 void AskForSnapshot(RenderWidgetHost* renderer, 81 bool prefer_backing_store, 82 ThumbnailReadyCallback* callback, 83 gfx::Size page_size, 84 gfx::Size desired_size); 85 86 // This returns a thumbnail of a fixed, small size for the given 87 // renderer. 88 SkBitmap GetThumbnailForRenderer(RenderWidgetHost* renderer) const; 89 90 // This returns a thumbnail of a fixed, small size for the given 91 // renderer. |options| is a bitmask of ThumbnailOptions. If 92 // |clip_result| is non-NULL, the result of clipping will be written. 93 SkBitmap GetThumbnailForRendererWithOptions(RenderWidgetHost* renderer, 94 int options, 95 ClipResult* clip_result) const; 96 97 // Start or stop monitoring notifications for |renderer| based on the value 98 // of |monitor|. 99 void MonitorRenderer(RenderWidgetHost* renderer, bool monitor); 100 101 // Calculates how "boring" a thumbnail is. The boring score is the 102 // 0,1 ranged percentage of pixels that are the most common 103 // luma. Higher boring scores indicate that a higher percentage of a 104 // bitmap are all the same brightness. 105 static double CalculateBoringScore(SkBitmap* bitmap); 106 107 // Gets the clipped bitmap from |bitmap| per the aspect ratio of the 108 // desired width and the desired height. For instance, if the input 109 // bitmap is vertically long (ex. 400x900) and the desired size is 110 // square (ex. 100x100), the clipped bitmap will be the top half of the 111 // input bitmap (400x400). 112 static SkBitmap GetClippedBitmap(const SkBitmap& bitmap, 113 int desired_width, 114 int desired_height, 115 ClipResult* clip_result); 116 117 // Update the thumbnail of the given tab contents if necessary. 118 void UpdateThumbnailIfNecessary(TabContents* tab_contents); 119 120 // Returns true if we should update the thumbnail of the given URL. 121 static bool ShouldUpdateThumbnail(Profile* profile, 122 history::TopSites* top_sites, 123 const GURL& url); 124 125 private: 126 virtual void WidgetDidReceivePaintAtSizeAck( 127 RenderWidgetHost* widget, 128 int tag, 129 const gfx::Size& size); 130 131 // NotificationObserver interface. 132 virtual void Observe(NotificationType type, 133 const NotificationSource& source, 134 const NotificationDetails& details); 135 136 // Indicates that the given widget has changed is visibility. 137 void WidgetHidden(RenderWidgetHost* widget); 138 139 // Called when the given tab contents are disconnected (either 140 // through being closed, or because the renderer is no longer there). 141 void TabContentsDisconnected(TabContents* contents); 142 143 NotificationRegistrar registrar_; 144 145 // Map of callback objects by sequence number. 146 struct AsyncRequestInfo; 147 typedef std::map<int, 148 linked_ptr<AsyncRequestInfo> > ThumbnailCallbackMap; 149 ThumbnailCallbackMap callback_map_; 150 151 DISALLOW_COPY_AND_ASSIGN(ThumbnailGenerator); 152 }; 153 154 #endif // CHROME_BROWSER_TAB_CONTENTS_THUMBNAIL_GENERATOR_H_ 155