• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 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 "components/precache/core/precache_fetcher.h"
6 
7 #include <list>
8 #include <set>
9 #include <string>
10 
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/command_line.h"
15 #include "base/compiler_specific.h"
16 #include "base/message_loop/message_loop.h"
17 #include "components/precache/core/precache_switches.h"
18 #include "components/precache/core/proto/precache.pb.h"
19 #include "net/http/http_response_headers.h"
20 #include "net/http/http_status_code.h"
21 #include "net/url_request/test_url_fetcher_factory.h"
22 #include "net/url_request/url_request_status.h"
23 #include "net/url_request/url_request_test_util.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 namespace precache {
27 
28 namespace {
29 
30 class TestURLFetcherCallback {
31  public:
CreateURLFetcher(const GURL & url,net::URLFetcherDelegate * delegate,const std::string & response_data,net::HttpStatusCode response_code,net::URLRequestStatus::Status status)32   scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
33       const GURL& url, net::URLFetcherDelegate* delegate,
34       const std::string& response_data, net::HttpStatusCode response_code,
35       net::URLRequestStatus::Status status) {
36     scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
37         url, delegate, response_data, response_code, status));
38 
39     if (response_code == net::HTTP_OK) {
40       scoped_refptr<net::HttpResponseHeaders> download_headers =
41           new net::HttpResponseHeaders("");
42       download_headers->AddHeader("Content-Type: text/html");
43       fetcher->set_response_headers(download_headers);
44     }
45 
46     requested_urls_.insert(url);
47     return fetcher.Pass();
48   }
49 
requested_urls() const50   const std::multiset<GURL>& requested_urls() const {
51     return requested_urls_;
52   }
53 
54  private:
55   // Multiset with one entry for each URL requested.
56   std::multiset<GURL> requested_urls_;
57 };
58 
59 class TestPrecacheDelegate : public PrecacheFetcher::PrecacheDelegate {
60  public:
TestPrecacheDelegate()61   TestPrecacheDelegate() : was_on_done_called_(false) {}
62 
OnDone()63   virtual void OnDone() OVERRIDE {
64     was_on_done_called_ = true;
65   }
66 
was_on_done_called() const67   bool was_on_done_called() const {
68     return was_on_done_called_;
69   }
70 
71  private:
72   bool was_on_done_called_;
73 };
74 
75 class PrecacheFetcherTest : public testing::Test {
76  public:
PrecacheFetcherTest()77   PrecacheFetcherTest()
78       : request_context_(new net::TestURLRequestContextGetter(
79             base::MessageLoopProxy::current())),
80         factory_(NULL, base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
81                                   base::Unretained(&url_callback_))) {}
82 
83  protected:
84   base::MessageLoopForUI loop_;
85   scoped_refptr<net::TestURLRequestContextGetter> request_context_;
86   TestURLFetcherCallback url_callback_;
87   net::FakeURLFetcherFactory factory_;
88   TestPrecacheDelegate precache_delegate_;
89 };
90 
91 const char kConfigURL[] = "http://config-url.com";
92 const char kManfiestURLPrefix[] = "http://manifest-url-prefix.com/";
93 const char kManifestFetchFailureURL[] =
94     "http://manifest-url-prefix.com/"
95     "http%253A%252F%252Fmanifest-fetch-failure.com%252F";
96 const char kBadManifestURL[] =
97     "http://manifest-url-prefix.com/http%253A%252F%252Fbad-manifest.com%252F";
98 const char kGoodManifestURL[] =
99     "http://manifest-url-prefix.com/http%253A%252F%252Fgood-manifest.com%252F";
100 const char kResourceFetchFailureURL[] = "http://resource-fetch-failure.com";
101 const char kGoodResourceURL[] = "http://good-resource.com";
102 const char kForcedStartingURLManifestURL[] =
103     "http://manifest-url-prefix.com/"
104     "http%253A%252F%252Fforced-starting-url.com%252F";
105 
TEST_F(PrecacheFetcherTest,FullPrecache)106 TEST_F(PrecacheFetcherTest, FullPrecache) {
107   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
108       switches::kPrecacheConfigSettingsURL, kConfigURL);
109   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
110       switches::kPrecacheManifestURLPrefix, kManfiestURLPrefix);
111 
112   std::list<GURL> starting_urls;
113   starting_urls.push_back(GURL("http://manifest-fetch-failure.com"));
114   starting_urls.push_back(GURL("http://bad-manifest.com"));
115   starting_urls.push_back(GURL("http://good-manifest.com"));
116   starting_urls.push_back(GURL("http://not-in-top-3.com"));
117 
118   PrecacheConfigurationSettings config;
119   config.set_top_sites_count(3);
120   config.add_forced_starting_url("http://forced-starting-url.com");
121   // Duplicate starting URL, the manifest for this should only be fetched once.
122   config.add_forced_starting_url("http://good-manifest.com");
123 
124   PrecacheManifest good_manifest;
125   good_manifest.add_resource()->set_url(kResourceFetchFailureURL);
126   good_manifest.add_resource();  // Resource with no URL, should not be fetched.
127   good_manifest.add_resource()->set_url(kGoodResourceURL);
128 
129   factory_.SetFakeResponse(GURL(kConfigURL), config.SerializeAsString(),
130                            net::HTTP_OK, net::URLRequestStatus::SUCCESS);
131   factory_.SetFakeResponse(GURL(kManifestFetchFailureURL), "",
132                            net::HTTP_INTERNAL_SERVER_ERROR,
133                            net::URLRequestStatus::FAILED);
134   factory_.SetFakeResponse(GURL(kBadManifestURL), "bad protobuf", net::HTTP_OK,
135                            net::URLRequestStatus::SUCCESS);
136   factory_.SetFakeResponse(GURL(kGoodManifestURL),
137                            good_manifest.SerializeAsString(), net::HTTP_OK,
138                            net::URLRequestStatus::SUCCESS);
139   factory_.SetFakeResponse(GURL(kResourceFetchFailureURL),
140                            "", net::HTTP_INTERNAL_SERVER_ERROR,
141                            net::URLRequestStatus::FAILED);
142   factory_.SetFakeResponse(GURL(kGoodResourceURL), "good", net::HTTP_OK,
143                            net::URLRequestStatus::SUCCESS);
144   factory_.SetFakeResponse(GURL(kForcedStartingURLManifestURL),
145                            PrecacheManifest().SerializeAsString(), net::HTTP_OK,
146                            net::URLRequestStatus::SUCCESS);
147 
148   PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
149                                    &precache_delegate_);
150   precache_fetcher.Start();
151 
152   base::MessageLoop::current()->RunUntilIdle();
153 
154   std::multiset<GURL> expected_requested_urls;
155   expected_requested_urls.insert(GURL(kConfigURL));
156   expected_requested_urls.insert(GURL(kManifestFetchFailureURL));
157   expected_requested_urls.insert(GURL(kBadManifestURL));
158   expected_requested_urls.insert(GURL(kGoodManifestURL));
159   expected_requested_urls.insert(GURL(kResourceFetchFailureURL));
160   expected_requested_urls.insert(GURL(kGoodResourceURL));
161   expected_requested_urls.insert(GURL(kForcedStartingURLManifestURL));
162 
163   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
164 
165   EXPECT_TRUE(precache_delegate_.was_on_done_called());
166 }
167 
TEST_F(PrecacheFetcherTest,ConfigFetchFailure)168 TEST_F(PrecacheFetcherTest, ConfigFetchFailure) {
169   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
170       switches::kPrecacheConfigSettingsURL, kConfigURL);
171 
172   std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
173 
174   factory_.SetFakeResponse(GURL(kConfigURL), "",
175                            net::HTTP_INTERNAL_SERVER_ERROR,
176                            net::URLRequestStatus::FAILED);
177 
178   PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
179                                    &precache_delegate_);
180   precache_fetcher.Start();
181 
182   base::MessageLoop::current()->RunUntilIdle();
183 
184   std::multiset<GURL> expected_requested_urls;
185   expected_requested_urls.insert(GURL(kConfigURL));
186   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
187 
188   EXPECT_TRUE(precache_delegate_.was_on_done_called());
189 }
190 
TEST_F(PrecacheFetcherTest,BadConfig)191 TEST_F(PrecacheFetcherTest, BadConfig) {
192   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
193       switches::kPrecacheConfigSettingsURL, kConfigURL);
194 
195   std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
196 
197   factory_.SetFakeResponse(GURL(kConfigURL), "bad protobuf", net::HTTP_OK,
198                            net::URLRequestStatus::SUCCESS);
199 
200   PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
201                                    &precache_delegate_);
202   precache_fetcher.Start();
203 
204   base::MessageLoop::current()->RunUntilIdle();
205 
206   std::multiset<GURL> expected_requested_urls;
207   expected_requested_urls.insert(GURL(kConfigURL));
208   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
209 
210   EXPECT_TRUE(precache_delegate_.was_on_done_called());
211 }
212 
TEST_F(PrecacheFetcherTest,Cancel)213 TEST_F(PrecacheFetcherTest, Cancel) {
214   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
215       switches::kPrecacheConfigSettingsURL, kConfigURL);
216 
217   std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
218 
219   PrecacheConfigurationSettings config;
220   config.set_top_sites_count(1);
221 
222   factory_.SetFakeResponse(GURL(kConfigURL), config.SerializeAsString(),
223                            net::HTTP_OK, net::URLRequestStatus::SUCCESS);
224 
225   scoped_ptr<PrecacheFetcher> precache_fetcher(new PrecacheFetcher(
226       starting_urls, request_context_.get(), &precache_delegate_));
227   precache_fetcher->Start();
228 
229   // Destroy the PrecacheFetcher to cancel precaching. This should not cause
230   // OnDone to be called on the precache delegate.
231   precache_fetcher.reset();
232 
233   base::MessageLoop::current()->RunUntilIdle();
234 
235   std::multiset<GURL> expected_requested_urls;
236   expected_requested_urls.insert(GURL(kConfigURL));
237   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
238 
239   EXPECT_FALSE(precache_delegate_.was_on_done_called());
240 }
241 
242 #if defined(PRECACHE_CONFIG_SETTINGS_URL)
243 
244 // If the default precache configuration settings URL is defined, then test that
245 // it works with the PrecacheFetcher.
TEST_F(PrecacheFetcherTest,PrecacheUsingDefaultConfigSettingsURL)246 TEST_F(PrecacheFetcherTest, PrecacheUsingDefaultConfigSettingsURL) {
247   std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
248 
249   PrecacheConfigurationSettings config;
250   config.set_top_sites_count(0);
251 
252   factory_.SetFakeResponse(GURL(PRECACHE_CONFIG_SETTINGS_URL),
253                            config.SerializeAsString(), net::HTTP_OK,
254                            net::URLRequestStatus::SUCCESS);
255 
256   PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
257                                    &precache_delegate_);
258   precache_fetcher.Start();
259 
260   base::MessageLoop::current()->RunUntilIdle();
261 
262   std::multiset<GURL> expected_requested_urls;
263   expected_requested_urls.insert(GURL(PRECACHE_CONFIG_SETTINGS_URL));
264   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
265 
266   EXPECT_TRUE(precache_delegate_.was_on_done_called());
267 }
268 
269 #endif  // PRECACHE_CONFIG_SETTINGS_URL
270 
271 #if defined(PRECACHE_MANIFEST_URL_PREFIX)
272 
273 // If the default precache manifest URL prefix is defined, then test that it
274 // works with the PrecacheFetcher.
TEST_F(PrecacheFetcherTest,PrecacheUsingDefaultManifestURLPrefix)275 TEST_F(PrecacheFetcherTest, PrecacheUsingDefaultManifestURLPrefix) {
276   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
277       switches::kPrecacheConfigSettingsURL, kConfigURL);
278 
279   std::list<GURL> starting_urls(1, GURL("http://starting-url.com"));
280 
281   PrecacheConfigurationSettings config;
282   config.set_top_sites_count(1);
283 
284   GURL manifest_url(PRECACHE_MANIFEST_URL_PREFIX
285                     "http%253A%252F%252Fstarting-url.com%252F");
286 
287   factory_.SetFakeResponse(GURL(kConfigURL), config.SerializeAsString(),
288                            net::HTTP_OK, net::URLRequestStatus::SUCCESS);
289   factory_.SetFakeResponse(manifest_url, PrecacheManifest().SerializeAsString(),
290                            net::HTTP_OK, net::URLRequestStatus::SUCCESS);
291 
292   PrecacheFetcher precache_fetcher(starting_urls, request_context_.get(),
293                                    &precache_delegate_);
294   precache_fetcher.Start();
295 
296   base::MessageLoop::current()->RunUntilIdle();
297 
298   std::multiset<GURL> expected_requested_urls;
299   expected_requested_urls.insert(GURL(kConfigURL));
300   expected_requested_urls.insert(manifest_url);
301   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
302 
303   EXPECT_TRUE(precache_delegate_.was_on_done_called());
304 }
305 
306 #endif  // PRECACHE_MANIFEST_URL_PREFIX
307 
308 }  // namespace
309 
310 }  // namespace precache
311