1// Copyright 2014 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/bitmap_fetcher/bitmap_fetcher.h"
6
7#include "base/compiler_specific.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/test/base/in_process_browser_test.h"
11#include "content/public/test/test_utils.h"
12#include "net/base/load_flags.h"
13#include "net/http/http_status_code.h"
14#include "net/url_request/test_url_fetcher_factory.h"
15#include "net/url_request/url_fetcher.h"
16#include "net/url_request/url_request_status.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "third_party/skia/include/core/SkBitmap.h"
19#include "ui/gfx/codec/png_codec.h"
20#include "ui/gfx/size.h"
21#include "ui/gfx/skia_util.h"
22
23const bool kAsyncCall = true;
24const bool kSyncCall = false;
25
26namespace chrome {
27
28// Class to catch events from the BitmapFetcher for testing.
29class BitmapFetcherTestDelegate : public BitmapFetcherDelegate {
30 public:
31  explicit BitmapFetcherTestDelegate(bool async) : called_(false),
32                                                   success_(false),
33                                                   async_(async) {}
34
35  virtual ~BitmapFetcherTestDelegate() {
36    EXPECT_TRUE(called_);
37  }
38
39  // Method inherited from BitmapFetcherDelegate.
40  virtual void OnFetchComplete(const GURL url,
41                               const SkBitmap* bitmap) OVERRIDE {
42    called_ = true;
43    url_ = url;
44    if (bitmap) {
45      success_ = true;
46      bitmap->deepCopyTo(&bitmap_);
47    }
48    // For async calls, we need to quit the run loop so the test can continue.
49    if (async_)
50      run_loop_.Quit();
51  }
52
53  // Waits until OnFetchComplete() is called. Should only be used for
54  // async tests.
55  void Wait() {
56    ASSERT_TRUE(async_);
57    run_loop_.Run();
58  }
59
60  GURL url() const { return url_; }
61  bool success() const { return success_; }
62  const SkBitmap& bitmap() const { return bitmap_; }
63
64 private:
65  base::RunLoop run_loop_;
66  bool called_;
67  GURL url_;
68  bool success_;
69  bool async_;
70  SkBitmap bitmap_;
71
72  DISALLOW_COPY_AND_ASSIGN(BitmapFetcherTestDelegate);
73};
74
75class BitmapFetcherBrowserTest : public InProcessBrowserTest {
76 public:
77  virtual void SetUp() OVERRIDE {
78    url_fetcher_factory_.reset(
79        new net::FakeURLFetcherFactory(&url_fetcher_impl_factory_));
80    InProcessBrowserTest::SetUp();
81  }
82
83 protected:
84  net::URLFetcherImplFactory url_fetcher_impl_factory_;
85  scoped_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
86};
87
88// WARNING:  These tests work with --single_process, but not
89// --single-process.  The reason is that the sandbox does not get created
90// for us by the test process if --single-process is used.
91
92IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, StartTest) {
93  GURL url("http://example.com/this-should-work");
94
95  // Put some realistic looking bitmap data into the url_fetcher.
96  SkBitmap image;
97
98  // Put a real bitmap into "image".  2x2 bitmap of green 32 bit pixels.
99  image.allocN32Pixels(2, 2);
100  image.eraseColor(SK_ColorGREEN);
101
102  // Encode the bits as a PNG.
103  std::vector<unsigned char> compressed;
104  ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(image, true, &compressed));
105
106  // Copy the bits into the string, and put them into the FakeURLFetcher.
107  std::string image_string(compressed.begin(), compressed.end());
108
109  // Set up a delegate to wait for the callback.
110  BitmapFetcherTestDelegate delegate(kAsyncCall);
111
112  BitmapFetcher fetcher(url, &delegate);
113
114  url_fetcher_factory_->SetFakeResponse(
115      url, image_string, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
116
117  // We expect that the image decoder will get called and return
118  // an image in a callback to OnImageDecoded().
119  fetcher.Start(
120      browser()->profile()->GetRequestContext(),
121      std::string(),
122      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
123      net::LOAD_NORMAL);
124
125  // Blocks until test delegate is notified via a callback.
126  delegate.Wait();
127
128  ASSERT_TRUE(delegate.success());
129
130  // Make sure we get back the bitmap we expect.
131  const SkBitmap& found_image = delegate.bitmap();
132  EXPECT_TRUE(gfx::BitmapsAreEqual(image, found_image));
133}
134
135IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, OnImageDecodedTest) {
136  GURL url("http://example.com/this-should-work-as-well");
137  SkBitmap image;
138
139  // Put a real bitmap into "image".  2x2 bitmap of green 16 bit pixels.
140  image.allocN32Pixels(2, 2);
141  image.eraseColor(SK_ColorGREEN);
142
143  BitmapFetcherTestDelegate delegate(kSyncCall);
144
145  BitmapFetcher fetcher(url, &delegate);
146
147  fetcher.OnImageDecoded(NULL, image);
148
149  // Ensure image is marked as succeeded.
150  EXPECT_TRUE(delegate.success());
151
152  // Test that the image is what we expect.
153  EXPECT_TRUE(gfx::BitmapsAreEqual(image, delegate.bitmap()));
154}
155
156IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, OnURLFetchFailureTest) {
157  GURL url("http://example.com/this-should-be-fetch-failure");
158
159  // We intentionally put no data into the bitmap to simulate a failure.
160
161  // Set up a delegate to wait for the callback.
162  BitmapFetcherTestDelegate delegate(kAsyncCall);
163
164  BitmapFetcher fetcher(url, &delegate);
165
166  url_fetcher_factory_->SetFakeResponse(url,
167                                        std::string(),
168                                        net::HTTP_INTERNAL_SERVER_ERROR,
169                                        net::URLRequestStatus::FAILED);
170
171  fetcher.Start(
172      browser()->profile()->GetRequestContext(),
173      std::string(),
174      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
175      net::LOAD_NORMAL);
176
177  // Blocks until test delegate is notified via a callback.
178  delegate.Wait();
179
180  EXPECT_FALSE(delegate.success());
181}
182
183IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, HandleImageFailedTest) {
184  GURL url("http://example.com/this-should-be-a-decode-failure");
185  BitmapFetcherTestDelegate delegate(kAsyncCall);
186  BitmapFetcher fetcher(url, &delegate);
187  url_fetcher_factory_->SetFakeResponse(url,
188                                        std::string("Not a real bitmap"),
189                                        net::HTTP_OK,
190                                        net::URLRequestStatus::SUCCESS);
191
192  fetcher.Start(
193      browser()->profile()->GetRequestContext(),
194      std::string(),
195      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
196      net::LOAD_NORMAL);
197
198  // Blocks until test delegate is notified via a callback.
199  delegate.Wait();
200
201  EXPECT_FALSE(delegate.success());
202}
203
204}  // namespace chrome
205