OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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 "chrome/browser/notifications/sync_notifier/notification_bitmap_fetcher
.h" |
| 6 |
| 7 #include "chrome/common/chrome_notification_types.h" |
| 8 #include "chrome/test/base/in_process_browser_test.h" |
| 9 #include "content/public/browser/browser_thread.h" |
| 10 #include "content/public/browser/notification_service.h" |
| 11 #include "content/public/test/test_utils.h" |
| 12 #include "net/url_request/url_fetcher.h" |
| 13 #include "net/url_request/url_request_status.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 #include "third_party/skia/include/core/SKBitmap.h" |
| 16 #include "ui/gfx/codec/png_codec.h" |
| 17 #include "ui/gfx/size.h" |
| 18 |
| 19 namespace { |
| 20 // FF0000FF is 100% alpha and max green.(A, R, B, G) |
| 21 uint32_t kMaxGreen = 0xFF0000FF; |
| 22 } // namespace |
| 23 |
| 24 namespace notifier { |
| 25 |
| 26 class StubURLFetcher : public net::URLFetcher { |
| 27 public: |
| 28 typedef std::vector<std::string> ResponseCookies; |
| 29 StubURLFetcher() : fetch_started_(false) {} |
| 30 |
| 31 virtual ~StubURLFetcher() {} |
| 32 static URLFetcher* Create(const GURL& url, |
| 33 URLFetcher::RequestType request_type, |
| 34 net::URLFetcherDelegate* d) { return NULL; } |
| 35 static URLFetcher* Create(int id, |
| 36 const GURL& url, |
| 37 URLFetcher::RequestType request_type, |
| 38 net::URLFetcherDelegate* d) { return NULL; } |
| 39 static void CancelAll() {} |
| 40 static void SetEnableInterceptionForTests(bool enabled) {} |
| 41 |
| 42 static void SetIgnoreCertificateRequests(bool ignored) {} |
| 43 void SetUploadData(const std::string& upload_content_type, |
| 44 const std::string& upload_content) {} |
| 45 void SetUploadFilePath( |
| 46 const std::string& upload_content_type, |
| 47 const base::FilePath& file_path, |
| 48 uint64 range_offset, |
| 49 uint64 range_length, |
| 50 scoped_refptr<base::TaskRunner> file_task_runner) {} |
| 51 void SetChunkedUpload(const std::string& upload_content_type) {} |
| 52 void AppendChunkToUpload(const std::string& data, |
| 53 bool is_last_chunk) {} |
| 54 void SetLoadFlags(int load_flags) {} |
| 55 int GetLoadFlags() const { return 0; } |
| 56 void SetReferrer(const std::string& referrer) {} |
| 57 void SetExtraRequestHeaders( |
| 58 const std::string& extra_request_headers) {} |
| 59 void AddExtraRequestHeader(const std::string& header_line) {} |
| 60 void GetExtraRequestHeaders(net::HttpRequestHeaders* headers) const {} |
| 61 void SetRequestContext( |
| 62 net::URLRequestContextGetter* request_context_getter) {} |
| 63 void SetFirstPartyForCookies( |
| 64 const GURL& first_party_for_cookies) {} |
| 65 void SetURLRequestUserData( |
| 66 const void* key, |
| 67 const CreateDataCallback& create_data_callback) {} |
| 68 void SetStopOnRedirect(bool stop_on_redirect) {} |
| 69 void SetAutomaticallyRetryOn5xx(bool retry) {} |
| 70 void SetMaxRetriesOn5xx(int max_retries) {} |
| 71 int GetMaxRetriesOn5xx() const { return 0; } |
| 72 base::TimeDelta GetBackoffDelay() const { return base::TimeDelta(); } |
| 73 void SetAutomaticallyRetryOnNetworkChanges(int max_retries) {} |
| 74 void SaveResponseToFileAtPath( |
| 75 const base::FilePath& file_path, |
| 76 scoped_refptr<base::TaskRunner> file_task_runner) {} |
| 77 void SaveResponseToTemporaryFile( |
| 78 scoped_refptr<base::TaskRunner> file_task_runner) {} |
| 79 net::HttpResponseHeaders* GetResponseHeaders() const { return NULL; } |
| 80 net::HostPortPair GetSocketAddress() const { return net::HostPortPair(); } |
| 81 bool WasFetchedViaProxy() const { return true; } |
| 82 void Start() { |
| 83 fetch_started_ = true; |
| 84 } |
| 85 const GURL& GetOriginalURL() const { return gurl_; } |
| 86 const GURL& GetURL() const { return gurl_; } |
| 87 const net::URLRequestStatus& GetStatus() const { |
| 88 return request_status; |
| 89 } |
| 90 int GetResponseCode() const { return 0; } |
| 91 const net::ResponseCookies& GetCookies() const { |
| 92 return response_cookies_; |
| 93 } |
| 94 bool FileErrorOccurred(int* out_error_code) const { return false; } |
| 95 void ReceivedContentWasMalformed() {} |
| 96 bool GetResponseAsString(std::string* out_response_string) const { |
| 97 *out_response_string = return_string_; |
| 98 return true; |
| 99 } |
| 100 bool GetResponseAsFilePath( |
| 101 bool take_ownership, |
| 102 base::FilePath* out_response_path) const { return true; } |
| 103 // For testing only, not a method of the base class, lets us input mock data. |
| 104 void SetReturnString(std::string& return_string) { |
| 105 return_string_ = return_string; |
| 106 } |
| 107 bool fetch_started() { |
| 108 return fetch_started_; |
| 109 } |
| 110 |
| 111 private: |
| 112 GURL gurl_; |
| 113 net::ResponseCookies response_cookies_; |
| 114 net::URLRequestStatus request_status; |
| 115 std::string return_string_; |
| 116 bool fetch_started_; |
| 117 |
| 118 }; |
| 119 |
| 120 class NotificationBitmapFetcherBrowserTest : public InProcessBrowserTest { |
| 121 |
| 122 }; |
| 123 |
| 124 // WARNING: These tests work with --single_process, but not |
| 125 // --single-process. The reason is that the sandbox does not get created |
| 126 // for us by the test process if --single-process is used. |
| 127 |
| 128 IN_PROC_BROWSER_TEST_F(NotificationBitmapFetcherBrowserTest, |
| 129 OnURLFetchCompleteTest) { |
| 130 GURL url("http://localhost"); |
| 131 StubURLFetcher* stub_url_fetcher = new StubURLFetcher(); |
| 132 scoped_ptr<net::URLFetcher> url_fetcher(stub_url_fetcher); |
| 133 scoped_refptr<base::MessageLoopProxy> task_runner = |
| 134 content::BrowserThread::GetMessageLoopProxyForThread( |
| 135 content::BrowserThread::UI); |
| 136 |
| 137 // Put some realistic looking bitmap data into the url_fetcher. |
| 138 SkBitmap image; |
| 139 |
| 140 // Put a real bitmap into "image". 2x2 bitmap of green 32 bit pixels. |
| 141 image.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); |
| 142 image.allocPixels(); |
| 143 SkColor c = kMaxGreen; |
| 144 image.eraseColor(c); |
| 145 // Test that the image is stored and ready. Pixel [0,0] should be green. |
| 146 EXPECT_EQ(16, image.getSize()); |
| 147 EXPECT_EQ(kMaxGreen, image.getColor(0, 0)); |
| 148 |
| 149 // Get vital stats from the bitmap for width, height, size, etc. |
| 150 SkAutoLockPixels lock(image); |
| 151 int width = image.width(); |
| 152 int height = image.height(); |
| 153 int row_length = static_cast<int>(image.rowBytes()); |
| 154 size_t size = row_length * height; |
| 155 // Actual bitmap data in arrays of RGBAs. |
| 156 std::vector<unsigned char> data; |
| 157 data.resize(size); |
| 158 memcpy(&*data.begin(), image.getAddr(0, 0), size); |
| 159 |
| 160 // Encode the bits as a PNG. |
| 161 std::vector<unsigned char> compressed; |
| 162 ASSERT_TRUE(gfx::PNGCodec::Encode(&*data.begin(), |
| 163 gfx::PNGCodec::FORMAT_BGRA, |
| 164 gfx::Size(width, height), |
| 165 static_cast<int>(row_length), |
| 166 true, |
| 167 std::vector<gfx::PNGCodec::Comment>(), |
| 168 &compressed)); |
| 169 |
| 170 // Copy the bits into the string, and put them into the StubURLFetcher. |
| 171 std::string image_string; |
| 172 image_string.resize(compressed.size()); |
| 173 // TODO(petewil): It might be better to have STL to write this loop for us |
| 174 // with for_each or a function. Make sure it handles embedded nulls. |
| 175 for (size_t ii = 0; ii < compressed.size(); ++ii) { |
| 176 image_string[ii] = compressed[ii]; |
| 177 } |
| 178 stub_url_fetcher->SetReturnString(image_string); |
| 179 |
| 180 // The fetcher controls the lifetime of url_fetcher, but we keep a |
| 181 // pointer to it with stub_url_fetcher. |
| 182 scoped_refptr<NotificationBitmapFetcher> fetcher = |
| 183 new NotificationBitmapFetcher(url, url_fetcher, task_runner); |
| 184 |
| 185 // Set up a signal to wait for the bitmap fetch to be done. |
| 186 content::WindowedNotificationObserver signal( |
| 187 chrome::NOTIFICATION_NOTIFY_BITMAP_FETCH_COMPLETE, |
| 188 content::NotificationService::AllSources()); |
| 189 |
| 190 // We expect that the image decoder will get called and return |
| 191 // an image in a callback to OnImageDecoded(). |
| 192 fetcher->OnURLFetchComplete(stub_url_fetcher); |
| 193 |
| 194 // Wait for the callback, test succeeds if callback looks good. |
| 195 signal.Wait(); |
| 196 |
| 197 ASSERT_FALSE(fetcher->image_failed()); |
| 198 ASSERT_TRUE(fetcher->image_ready()); |
| 199 |
| 200 // Make sure we get back the bitmap we expect. |
| 201 SkBitmap* found_image = fetcher->bitmap(); |
| 202 EXPECT_EQ(16, found_image->getSize()); |
| 203 EXPECT_EQ(kMaxGreen, found_image->getColor(0, 0)); |
| 204 } |
| 205 |
| 206 IN_PROC_BROWSER_TEST_F(NotificationBitmapFetcherBrowserTest, |
| 207 OnDecodeImageFailedTest) { |
| 208 GURL url("http://localhost"); |
| 209 StubURLFetcher* stub_url_fetcher = new StubURLFetcher(); |
| 210 scoped_ptr<net::URLFetcher> url_fetcher(stub_url_fetcher); |
| 211 scoped_refptr<base::MessageLoopProxy> task_runner = |
| 212 content::BrowserThread::GetMessageLoopProxyForThread( |
| 213 content::BrowserThread::UI); |
| 214 |
| 215 // The fetcher controls the lifetime of url_fetcher, but we keep a |
| 216 // pointer to it with stub_url_fetcher. |
| 217 scoped_refptr<NotificationBitmapFetcher> fetcher = |
| 218 new NotificationBitmapFetcher(url, url_fetcher, task_runner); |
| 219 |
| 220 // Set up a signal to wait for the bitmap fetch to be done. |
| 221 content::WindowedNotificationObserver signal( |
| 222 chrome::NOTIFICATION_NOTIFY_BITMAP_FETCH_COMPLETE, |
| 223 content::NotificationService::AllSources()); |
| 224 |
| 225 // We expect that the image decoder will get called and return |
| 226 // in a callback to OnImageDecodFailed(). |
| 227 fetcher->OnURLFetchComplete(stub_url_fetcher); |
| 228 |
| 229 // Wait for the callback, test succeeds if callback looks good. |
| 230 signal.Wait(); |
| 231 |
| 232 ASSERT_TRUE(fetcher->image_failed()); |
| 233 ASSERT_FALSE(fetcher->image_ready()); |
| 234 |
| 235 // Make sure we didn't get any bitmap. |
| 236 SkBitmap* found_image = fetcher->bitmap(); |
| 237 EXPECT_EQ(NULL, found_image); |
| 238 } |
| 239 |
| 240 IN_PROC_BROWSER_TEST_F(NotificationBitmapFetcherBrowserTest, |
| 241 OnURLFetchFailureTest) { |
| 242 GURL url("http://localhost"); |
| 243 StubURLFetcher* stub_url_fetcher = new StubURLFetcher(); |
| 244 scoped_ptr<net::URLFetcher> url_fetcher(stub_url_fetcher); |
| 245 scoped_refptr<base::MessageLoopProxy> task_runner = |
| 246 content::BrowserThread::GetMessageLoopProxyForThread( |
| 247 content::BrowserThread::UI); |
| 248 |
| 249 // We intentionally put no data into the bitmap to simulate a failure. |
| 250 |
| 251 // The fetcher controls the lifetime of url_fetcher, but we keep a |
| 252 // pointer to it with stub_url_fetcher. |
| 253 scoped_refptr<NotificationBitmapFetcher> fetcher = |
| 254 new NotificationBitmapFetcher(url, url_fetcher, task_runner); |
| 255 |
| 256 // Set up a signal to wait for the bitmap fetch to be done. |
| 257 content::WindowedNotificationObserver signal( |
| 258 chrome::NOTIFICATION_NOTIFY_BITMAP_FETCH_COMPLETE, |
| 259 content::NotificationService::AllSources()); |
| 260 |
| 261 // We expect that the fetch complete notification will be sent, but that the |
| 262 // image will be marked as failed. |
| 263 fetcher->OnURLFetchComplete(stub_url_fetcher); |
| 264 |
| 265 // Wait for the callback, test succeeds if callback looks good. |
| 266 signal.Wait(); |
| 267 |
| 268 ASSERT_TRUE(fetcher->image_failed()); |
| 269 ASSERT_FALSE(fetcher->image_ready()); |
| 270 |
| 271 // Make sure we don't get a bitmap. |
| 272 SkBitmap* found_image = fetcher->bitmap(); |
| 273 EXPECT_EQ(NULL, found_image); |
| 274 } |
| 275 |
| 276 } // namespace notifier |
OLD | NEW |