OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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 #include "base/basictypes.h" |
| 6 #include "chrome/browser/renderer_host/backing_store_manager.h" |
| 7 #include "chrome/browser/renderer_host/mock_render_process_host.h" |
| 8 #include "chrome/browser/renderer_host/test_render_view_host.h" |
| 9 #include "chrome/browser/tab_contents/thumbnail_generator.h" |
| 10 #include "chrome/common/notification_service.h" |
| 11 #include "chrome/common/render_messages.h" |
| 12 #include "chrome/common/transport_dib.h" |
| 13 #include "chrome/test/testing_profile.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 #include "skia/ext/platform_canvas.h" |
| 16 #include "third_party/skia/include/core/SkColorPriv.h" |
| 17 |
| 18 static const int kBitmapWidth = 100; |
| 19 static const int kBitmapHeight = 100; |
| 20 |
| 21 // TODO(brettw) enable this when GetThumbnailForBackingStore is implemented |
| 22 // for other platforms in thumbnail_generator.cc |
| 23 //#if defined(OS_WIN) |
| 24 // TODO(brettw) enable this on Windows after we clobber a build to see if the |
| 25 // failures of this on the buildbot can be resolved. |
| 26 #if 0 |
| 27 |
| 28 class ThumbnailGeneratorTest : public testing::Test { |
| 29 public: |
| 30 ThumbnailGeneratorTest() |
| 31 : profile_(), |
| 32 process_(new MockRenderProcessHost(&profile_)), |
| 33 widget_(process_, 1), |
| 34 view_(&widget_) { |
| 35 // Paiting will be skipped if there's no view. |
| 36 widget_.set_view(&view_); |
| 37 |
| 38 // Need to send out a create notification for the RWH to get hooked. This is |
| 39 // a little scary in that we don't have a RenderView, but the only listener |
| 40 // will want a RenderWidget, so it works out OK. |
| 41 NotificationService::current()->Notify( |
| 42 NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB, |
| 43 Source<RenderViewHostManager>(NULL), |
| 44 Details<RenderViewHost>(reinterpret_cast<RenderViewHost*>(&widget_))); |
| 45 |
| 46 transport_dib_.reset(TransportDIB::Create(kBitmapWidth * kBitmapHeight * 4, |
| 47 1)); |
| 48 |
| 49 // We don't want to be sensitive to timing. |
| 50 generator_.set_no_timeout(true); |
| 51 } |
| 52 |
| 53 protected: |
| 54 // Indicates what bitmap should be sent with the paint message. _OTHER will |
| 55 // only be retrned by CheckFirstPixel if the pixel is none of the others. |
| 56 enum TransportType { TRANSPORT_BLACK, TRANSPORT_WHITE, TRANSPORT_OTHER }; |
| 57 |
| 58 void SendPaint(TransportType type) { |
| 59 ViewHostMsg_PaintRect_Params params; |
| 60 params.bitmap_rect = gfx::Rect(0, 0, kBitmapWidth, kBitmapHeight); |
| 61 params.view_size = params.bitmap_rect.size(); |
| 62 params.flags = 0; |
| 63 |
| 64 scoped_ptr<skia::PlatformCanvas> canvas( |
| 65 transport_dib_->GetPlatformCanvas(kBitmapWidth, kBitmapHeight)); |
| 66 switch (type) { |
| 67 case TRANSPORT_BLACK: |
| 68 canvas->getTopPlatformDevice().accessBitmap(true).eraseARGB( |
| 69 0xFF, 0, 0, 0); |
| 70 break; |
| 71 case TRANSPORT_WHITE: |
| 72 canvas->getTopPlatformDevice().accessBitmap(true).eraseARGB( |
| 73 0xFF, 0xFF, 0xFF, 0xFF); |
| 74 break; |
| 75 case TRANSPORT_OTHER: |
| 76 default: |
| 77 NOTREACHED(); |
| 78 break; |
| 79 } |
| 80 |
| 81 params.bitmap = transport_dib_->id(); |
| 82 |
| 83 ViewHostMsg_PaintRect msg(1, params); |
| 84 widget_.OnMessageReceived(msg); |
| 85 } |
| 86 |
| 87 TransportType ClassifyFirstPixel(const SkBitmap& bitmap) { |
| 88 // Returns the color of the first pixel of the bitmap. The bitmap must be |
| 89 // non-empty. |
| 90 SkAutoLockPixels lock(bitmap); |
| 91 uint32 pixel = *bitmap.getAddr32(0, 0); |
| 92 |
| 93 if (SkGetPackedA32(pixel) != 0xFF) |
| 94 return TRANSPORT_OTHER; // All values expect an opqaue alpha channel |
| 95 |
| 96 if (SkGetPackedR32(pixel) == 0 && |
| 97 SkGetPackedG32(pixel) == 0 && |
| 98 SkGetPackedB32(pixel) == 0) |
| 99 return TRANSPORT_BLACK; |
| 100 |
| 101 if (SkGetPackedR32(pixel) == 0xFF && |
| 102 SkGetPackedG32(pixel) == 0xFF && |
| 103 SkGetPackedB32(pixel) == 0xFF) |
| 104 return TRANSPORT_WHITE; |
| 105 |
| 106 EXPECT_TRUE(false) << "Got weird color: " << pixel; |
| 107 return TRANSPORT_OTHER; |
| 108 } |
| 109 |
| 110 MessageLoopForUI message_loop_; |
| 111 |
| 112 TestingProfile profile_; |
| 113 |
| 114 // This will get deleted when the last RHWH associated with it is destroyed. |
| 115 MockRenderProcessHost* process_; |
| 116 |
| 117 RenderWidgetHost widget_; |
| 118 TestRenderWidgetHostView view_; |
| 119 ThumbnailGenerator generator_; |
| 120 |
| 121 scoped_ptr<TransportDIB> transport_dib_; |
| 122 |
| 123 private: |
| 124 // testing::Test implementation. |
| 125 void SetUp() { |
| 126 } |
| 127 void TearDown() { |
| 128 } |
| 129 }; |
| 130 |
| 131 TEST_F(ThumbnailGeneratorTest, NoThumbnail) { |
| 132 // This is the case where there is no thumbnail available on the tab and |
| 133 // there is no backing store. There should be no image returned. |
| 134 SkBitmap result = generator_.GetThumbnailForRenderer(&widget_); |
| 135 EXPECT_TRUE(result.isNull()); |
| 136 } |
| 137 |
| 138 // Tests basic thumbnail generation when a backing store is discarded. |
| 139 TEST_F(ThumbnailGeneratorTest, DiscardBackingStore) { |
| 140 // First set up a backing store and then discard it. |
| 141 SendPaint(TRANSPORT_BLACK); |
| 142 widget_.WasHidden(); |
| 143 ASSERT_TRUE(BackingStoreManager::ExpireBackingStoreForTest(&widget_)); |
| 144 ASSERT_FALSE(widget_.GetBackingStore(false)); |
| 145 |
| 146 // The thumbnail generator should have stashed a thumbnail of the page. |
| 147 SkBitmap result = generator_.GetThumbnailForRenderer(&widget_); |
| 148 ASSERT_FALSE(result.isNull()); |
| 149 EXPECT_EQ(TRANSPORT_BLACK, ClassifyFirstPixel(result)); |
| 150 } |
| 151 |
| 152 TEST_F(ThumbnailGeneratorTest, QuickShow) { |
| 153 // Set up a hidden widget with a black cached thumbnail and an expired |
| 154 // backing store. |
| 155 SendPaint(TRANSPORT_BLACK); |
| 156 widget_.WasHidden(); |
| 157 ASSERT_TRUE(BackingStoreManager::ExpireBackingStoreForTest(&widget_)); |
| 158 ASSERT_FALSE(widget_.GetBackingStore(false)); |
| 159 |
| 160 // Now show the widget and paint white. |
| 161 widget_.WasRestored(); |
| 162 SendPaint(TRANSPORT_WHITE); |
| 163 |
| 164 // The black thumbnail should still be cached because it hasn't processed the |
| 165 // timer message yet. |
| 166 SkBitmap result = generator_.GetThumbnailForRenderer(&widget_); |
| 167 ASSERT_FALSE(result.isNull()); |
| 168 EXPECT_EQ(TRANSPORT_BLACK, ClassifyFirstPixel(result)); |
| 169 |
| 170 // Running the message loop will process the timer, which should expire the |
| 171 // cached thumbnail. Asking again should give us a new one computed from the |
| 172 // backing store. |
| 173 message_loop_.RunAllPending(); |
| 174 result = generator_.GetThumbnailForRenderer(&widget_); |
| 175 ASSERT_FALSE(result.isNull()); |
| 176 EXPECT_EQ(TRANSPORT_WHITE, ClassifyFirstPixel(result)); |
| 177 } |
| 178 |
| 179 #endif |
OLD | NEW |