Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / proxy / proxy_script_fetcher_impl_unittest.cc
1 // Copyright (c) 2012 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 "net/proxy/proxy_script_fetcher_impl.h"
6
7 #include <string>
8
9 #include "base/compiler_specific.h"
10 #include "base/files/file_path.h"
11 #include "base/path_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/filename_util.h"
14 #include "net/base/load_flags.h"
15 #include "net/base/test_completion_callback.h"
16 #include "net/cert/mock_cert_verifier.h"
17 #include "net/disk_cache/disk_cache.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/http/http_cache.h"
20 #include "net/http/http_network_session.h"
21 #include "net/http/http_server_properties_impl.h"
22 #include "net/http/transport_security_state.h"
23 #include "net/ssl/ssl_config_service_defaults.h"
24 #include "net/test/spawned_test_server/spawned_test_server.h"
25 #include "net/url_request/url_request_context_storage.h"
26 #include "net/url_request/url_request_file_job.h"
27 #include "net/url_request/url_request_job_factory_impl.h"
28 #include "net/url_request/url_request_test_util.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "testing/platform_test.h"
31
32 #if !defined(DISABLE_FILE_SUPPORT)
33 #include "net/url_request/file_protocol_handler.h"
34 #endif
35
36 using base::ASCIIToUTF16;
37
38 namespace net {
39
40 // TODO(eroman):
41 //   - Test canceling an outstanding request.
42 //   - Test deleting ProxyScriptFetcher while a request is in progress.
43
44 namespace {
45
46 const base::FilePath::CharType kDocRoot[] =
47     FILE_PATH_LITERAL("net/data/proxy_script_fetcher_unittest");
48
49 struct FetchResult {
50   int code;
51   base::string16 text;
52 };
53
54 // A non-mock URL request which can access http:// and file:// urls, in the case
55 // the tests were built with file support.
56 class RequestContext : public URLRequestContext {
57  public:
58   RequestContext() : storage_(this) {
59     ProxyConfig no_proxy;
60     storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver));
61     storage_.set_cert_verifier(new MockCertVerifier);
62     storage_.set_transport_security_state(new TransportSecurityState);
63     storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy));
64     storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
65     storage_.set_http_server_properties(
66         scoped_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
67
68     HttpNetworkSession::Params params;
69     params.host_resolver = host_resolver();
70     params.cert_verifier = cert_verifier();
71     params.transport_security_state = transport_security_state();
72     params.proxy_service = proxy_service();
73     params.ssl_config_service = ssl_config_service();
74     params.http_server_properties = http_server_properties();
75     scoped_refptr<HttpNetworkSession> network_session(
76         new HttpNetworkSession(params));
77     storage_.set_http_transaction_factory(new HttpCache(
78         network_session.get(), HttpCache::DefaultBackend::InMemory(0)));
79     URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl();
80 #if !defined(DISABLE_FILE_SUPPORT)
81     job_factory->SetProtocolHandler(
82         "file", new FileProtocolHandler(base::MessageLoopProxy::current()));
83 #endif
84     storage_.set_job_factory(job_factory);
85   }
86
87   virtual ~RequestContext() {
88   }
89
90  private:
91   URLRequestContextStorage storage_;
92 };
93
94 // Get a file:// url relative to net/data/proxy/proxy_script_fetcher_unittest.
95 GURL GetTestFileUrl(const std::string& relpath) {
96   base::FilePath path;
97   PathService::Get(base::DIR_SOURCE_ROOT, &path);
98   path = path.AppendASCII("net");
99   path = path.AppendASCII("data");
100   path = path.AppendASCII("proxy_script_fetcher_unittest");
101   GURL base_url = FilePathToFileURL(path);
102   return GURL(base_url.spec() + "/" + relpath);
103 }
104
105 // Really simple NetworkDelegate so we can allow local file access on ChromeOS
106 // without introducing layering violations.  Also causes a test failure if a
107 // request is seen that doesn't set a load flag to bypass revocation checking.
108
109 class BasicNetworkDelegate : public NetworkDelegate {
110  public:
111   BasicNetworkDelegate() {}
112   virtual ~BasicNetworkDelegate() {}
113
114  private:
115   virtual int OnBeforeURLRequest(URLRequest* request,
116                                  const CompletionCallback& callback,
117                                  GURL* new_url) OVERRIDE {
118     EXPECT_TRUE(request->load_flags() & LOAD_DISABLE_CERT_REVOCATION_CHECKING);
119     return OK;
120   }
121
122   virtual int OnBeforeSendHeaders(URLRequest* request,
123                                   const CompletionCallback& callback,
124                                   HttpRequestHeaders* headers) OVERRIDE {
125     return OK;
126   }
127
128   virtual void OnSendHeaders(URLRequest* request,
129                              const HttpRequestHeaders& headers) OVERRIDE {}
130
131   virtual int OnHeadersReceived(
132       URLRequest* request,
133       const CompletionCallback& callback,
134       const HttpResponseHeaders* original_response_headers,
135       scoped_refptr<HttpResponseHeaders>* override_response_headers,
136       GURL* allowed_unsafe_redirect_url) OVERRIDE {
137     return OK;
138   }
139
140   virtual void OnBeforeRedirect(URLRequest* request,
141                                 const GURL& new_location) OVERRIDE {}
142
143   virtual void OnResponseStarted(URLRequest* request) OVERRIDE {}
144
145   virtual void OnRawBytesRead(const URLRequest& request,
146                               int bytes_read) OVERRIDE {}
147
148   virtual void OnCompleted(URLRequest* request, bool started) OVERRIDE {}
149
150   virtual void OnURLRequestDestroyed(URLRequest* request) OVERRIDE {}
151
152   virtual void OnPACScriptError(int line_number,
153                                 const base::string16& error) OVERRIDE {}
154
155   virtual NetworkDelegate::AuthRequiredResponse OnAuthRequired(
156       URLRequest* request,
157       const AuthChallengeInfo& auth_info,
158       const AuthCallback& callback,
159       AuthCredentials* credentials) OVERRIDE {
160     return NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
161   }
162
163   virtual bool OnCanGetCookies(const URLRequest& request,
164                                const CookieList& cookie_list) OVERRIDE {
165     return true;
166   }
167
168   virtual bool OnCanSetCookie(const URLRequest& request,
169                               const std::string& cookie_line,
170                               CookieOptions* options) OVERRIDE {
171     return true;
172   }
173
174   virtual bool OnCanAccessFile(const net::URLRequest& request,
175                                const base::FilePath& path) const OVERRIDE {
176     return true;
177   }
178   virtual bool OnCanThrottleRequest(const URLRequest& request) const OVERRIDE {
179     return false;
180   }
181
182   virtual int OnBeforeSocketStreamConnect(
183       SocketStream* stream,
184       const CompletionCallback& callback) OVERRIDE {
185     return OK;
186   }
187
188   DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
189 };
190
191 }  // namespace
192
193 class ProxyScriptFetcherImplTest : public PlatformTest {
194  public:
195   ProxyScriptFetcherImplTest()
196       : test_server_(SpawnedTestServer::TYPE_HTTP,
197                      net::SpawnedTestServer::kLocalhost,
198                      base::FilePath(kDocRoot)) {
199     context_.set_network_delegate(&network_delegate_);
200   }
201
202  protected:
203   SpawnedTestServer test_server_;
204   BasicNetworkDelegate network_delegate_;
205   RequestContext context_;
206 };
207
208 #if !defined(DISABLE_FILE_SUPPORT)
209 TEST_F(ProxyScriptFetcherImplTest, FileUrl) {
210   ProxyScriptFetcherImpl pac_fetcher(&context_);
211
212   { // Fetch a non-existent file.
213     base::string16 text;
214     TestCompletionCallback callback;
215     int result = pac_fetcher.Fetch(GetTestFileUrl("does-not-exist"),
216                                    &text, callback.callback());
217     EXPECT_EQ(ERR_IO_PENDING, result);
218     EXPECT_EQ(ERR_FILE_NOT_FOUND, callback.WaitForResult());
219     EXPECT_TRUE(text.empty());
220   }
221   { // Fetch a file that exists.
222     base::string16 text;
223     TestCompletionCallback callback;
224     int result = pac_fetcher.Fetch(GetTestFileUrl("pac.txt"),
225                                    &text, callback.callback());
226     EXPECT_EQ(ERR_IO_PENDING, result);
227     EXPECT_EQ(OK, callback.WaitForResult());
228     EXPECT_EQ(ASCIIToUTF16("-pac.txt-\n"), text);
229   }
230 }
231 #endif  // !defined(DISABLE_FILE_SUPPORT)
232
233 // Note that all mime types are allowed for PAC file, to be consistent
234 // with other browsers.
235 TEST_F(ProxyScriptFetcherImplTest, HttpMimeType) {
236   ASSERT_TRUE(test_server_.Start());
237
238   ProxyScriptFetcherImpl pac_fetcher(&context_);
239
240   { // Fetch a PAC with mime type "text/plain"
241     GURL url(test_server_.GetURL("files/pac.txt"));
242     base::string16 text;
243     TestCompletionCallback callback;
244     int result = pac_fetcher.Fetch(url, &text, callback.callback());
245     EXPECT_EQ(ERR_IO_PENDING, result);
246     EXPECT_EQ(OK, callback.WaitForResult());
247     EXPECT_EQ(ASCIIToUTF16("-pac.txt-\n"), text);
248   }
249   { // Fetch a PAC with mime type "text/html"
250     GURL url(test_server_.GetURL("files/pac.html"));
251     base::string16 text;
252     TestCompletionCallback callback;
253     int result = pac_fetcher.Fetch(url, &text, callback.callback());
254     EXPECT_EQ(ERR_IO_PENDING, result);
255     EXPECT_EQ(OK, callback.WaitForResult());
256     EXPECT_EQ(ASCIIToUTF16("-pac.html-\n"), text);
257   }
258   { // Fetch a PAC with mime type "application/x-ns-proxy-autoconfig"
259     GURL url(test_server_.GetURL("files/pac.nsproxy"));
260     base::string16 text;
261     TestCompletionCallback callback;
262     int result = pac_fetcher.Fetch(url, &text, callback.callback());
263     EXPECT_EQ(ERR_IO_PENDING, result);
264     EXPECT_EQ(OK, callback.WaitForResult());
265     EXPECT_EQ(ASCIIToUTF16("-pac.nsproxy-\n"), text);
266   }
267 }
268
269 TEST_F(ProxyScriptFetcherImplTest, HttpStatusCode) {
270   ASSERT_TRUE(test_server_.Start());
271
272   ProxyScriptFetcherImpl pac_fetcher(&context_);
273
274   { // Fetch a PAC which gives a 500 -- FAIL
275     GURL url(test_server_.GetURL("files/500.pac"));
276     base::string16 text;
277     TestCompletionCallback callback;
278     int result = pac_fetcher.Fetch(url, &text, callback.callback());
279     EXPECT_EQ(ERR_IO_PENDING, result);
280     EXPECT_EQ(ERR_PAC_STATUS_NOT_OK, callback.WaitForResult());
281     EXPECT_TRUE(text.empty());
282   }
283   { // Fetch a PAC which gives a 404 -- FAIL
284     GURL url(test_server_.GetURL("files/404.pac"));
285     base::string16 text;
286     TestCompletionCallback callback;
287     int result = pac_fetcher.Fetch(url, &text, callback.callback());
288     EXPECT_EQ(ERR_IO_PENDING, result);
289     EXPECT_EQ(ERR_PAC_STATUS_NOT_OK, callback.WaitForResult());
290     EXPECT_TRUE(text.empty());
291   }
292 }
293
294 TEST_F(ProxyScriptFetcherImplTest, ContentDisposition) {
295   ASSERT_TRUE(test_server_.Start());
296
297   ProxyScriptFetcherImpl pac_fetcher(&context_);
298
299   // Fetch PAC scripts via HTTP with a Content-Disposition header -- should
300   // have no effect.
301   GURL url(test_server_.GetURL("files/downloadable.pac"));
302   base::string16 text;
303   TestCompletionCallback callback;
304   int result = pac_fetcher.Fetch(url, &text, callback.callback());
305   EXPECT_EQ(ERR_IO_PENDING, result);
306   EXPECT_EQ(OK, callback.WaitForResult());
307   EXPECT_EQ(ASCIIToUTF16("-downloadable.pac-\n"), text);
308 }
309
310 // Verifies that PAC scripts are not being cached.
311 TEST_F(ProxyScriptFetcherImplTest, NoCache) {
312   ASSERT_TRUE(test_server_.Start());
313
314   ProxyScriptFetcherImpl pac_fetcher(&context_);
315
316   // Fetch a PAC script whose HTTP headers make it cacheable for 1 hour.
317   GURL url(test_server_.GetURL("files/cacheable_1hr.pac"));
318   {
319     base::string16 text;
320     TestCompletionCallback callback;
321     int result = pac_fetcher.Fetch(url, &text, callback.callback());
322     EXPECT_EQ(ERR_IO_PENDING, result);
323     EXPECT_EQ(OK, callback.WaitForResult());
324     EXPECT_EQ(ASCIIToUTF16("-cacheable_1hr.pac-\n"), text);
325   }
326
327   // Kill the HTTP server.
328   ASSERT_TRUE(test_server_.Stop());
329
330   // Try to fetch the file again. Since the server is not running anymore, the
331   // call should fail, thus indicating that the file was not fetched from the
332   // local cache.
333   {
334     base::string16 text;
335     TestCompletionCallback callback;
336     int result = pac_fetcher.Fetch(url, &text, callback.callback());
337     EXPECT_EQ(ERR_IO_PENDING, result);
338
339     // Expect any error. The exact error varies by platform.
340     EXPECT_NE(OK, callback.WaitForResult());
341   }
342 }
343
344 TEST_F(ProxyScriptFetcherImplTest, TooLarge) {
345   ASSERT_TRUE(test_server_.Start());
346
347   ProxyScriptFetcherImpl pac_fetcher(&context_);
348
349   // Set the maximum response size to 50 bytes.
350   int prev_size = pac_fetcher.SetSizeConstraint(50);
351
352   // These two URLs are the same file, but are http:// vs file://
353   GURL urls[] = {
354     test_server_.GetURL("files/large-pac.nsproxy"),
355     GetTestFileUrl("large-pac.nsproxy")
356   };
357
358   // Try fetching URLs that are 101 bytes large. We should abort the request
359   // after 50 bytes have been read, and fail with a too large error.
360   for (size_t i = 0; i < arraysize(urls); ++i) {
361     const GURL& url = urls[i];
362     base::string16 text;
363     TestCompletionCallback callback;
364     int result = pac_fetcher.Fetch(url, &text, callback.callback());
365     EXPECT_EQ(ERR_IO_PENDING, result);
366     EXPECT_EQ(ERR_FILE_TOO_BIG, callback.WaitForResult());
367     EXPECT_TRUE(text.empty());
368   }
369
370   // Restore the original size bound.
371   pac_fetcher.SetSizeConstraint(prev_size);
372
373   { // Make sure we can still fetch regular URLs.
374     GURL url(test_server_.GetURL("files/pac.nsproxy"));
375     base::string16 text;
376     TestCompletionCallback callback;
377     int result = pac_fetcher.Fetch(url, &text, callback.callback());
378     EXPECT_EQ(ERR_IO_PENDING, result);
379     EXPECT_EQ(OK, callback.WaitForResult());
380     EXPECT_EQ(ASCIIToUTF16("-pac.nsproxy-\n"), text);
381   }
382 }
383
384 TEST_F(ProxyScriptFetcherImplTest, Hang) {
385   ASSERT_TRUE(test_server_.Start());
386
387   ProxyScriptFetcherImpl pac_fetcher(&context_);
388
389   // Set the timeout period to 0.5 seconds.
390   base::TimeDelta prev_timeout = pac_fetcher.SetTimeoutConstraint(
391       base::TimeDelta::FromMilliseconds(500));
392
393   // Try fetching a URL which takes 1.2 seconds. We should abort the request
394   // after 500 ms, and fail with a timeout error.
395   {
396     GURL url(test_server_.GetURL("slow/proxy.pac?1.2"));
397     base::string16 text;
398     TestCompletionCallback callback;
399     int result = pac_fetcher.Fetch(url, &text, callback.callback());
400     EXPECT_EQ(ERR_IO_PENDING, result);
401     EXPECT_EQ(ERR_TIMED_OUT, callback.WaitForResult());
402     EXPECT_TRUE(text.empty());
403   }
404
405   // Restore the original timeout period.
406   pac_fetcher.SetTimeoutConstraint(prev_timeout);
407
408   { // Make sure we can still fetch regular URLs.
409     GURL url(test_server_.GetURL("files/pac.nsproxy"));
410     base::string16 text;
411     TestCompletionCallback callback;
412     int result = pac_fetcher.Fetch(url, &text, callback.callback());
413     EXPECT_EQ(ERR_IO_PENDING, result);
414     EXPECT_EQ(OK, callback.WaitForResult());
415     EXPECT_EQ(ASCIIToUTF16("-pac.nsproxy-\n"), text);
416   }
417 }
418
419 // The ProxyScriptFetcher should decode any content-codings
420 // (like gzip, bzip, etc.), and apply any charset conversions to yield
421 // UTF8.
422 TEST_F(ProxyScriptFetcherImplTest, Encodings) {
423   ASSERT_TRUE(test_server_.Start());
424
425   ProxyScriptFetcherImpl pac_fetcher(&context_);
426
427   // Test a response that is gzip-encoded -- should get inflated.
428   {
429     GURL url(test_server_.GetURL("files/gzipped_pac"));
430     base::string16 text;
431     TestCompletionCallback callback;
432     int result = pac_fetcher.Fetch(url, &text, callback.callback());
433     EXPECT_EQ(ERR_IO_PENDING, result);
434     EXPECT_EQ(OK, callback.WaitForResult());
435     EXPECT_EQ(ASCIIToUTF16("This data was gzipped.\n"), text);
436   }
437
438   // Test a response that was served as UTF-16 (BE). It should
439   // be converted to UTF8.
440   {
441     GURL url(test_server_.GetURL("files/utf16be_pac"));
442     base::string16 text;
443     TestCompletionCallback callback;
444     int result = pac_fetcher.Fetch(url, &text, callback.callback());
445     EXPECT_EQ(ERR_IO_PENDING, result);
446     EXPECT_EQ(OK, callback.WaitForResult());
447     EXPECT_EQ(ASCIIToUTF16("This was encoded as UTF-16BE.\n"), text);
448   }
449 }
450
451 TEST_F(ProxyScriptFetcherImplTest, DataURLs) {
452   ProxyScriptFetcherImpl pac_fetcher(&context_);
453
454   const char kEncodedUrl[] =
455       "data:application/x-ns-proxy-autoconfig;base64,ZnVuY3Rpb24gRmluZFByb3h5R"
456       "m9yVVJMKHVybCwgaG9zdCkgewogIGlmIChob3N0ID09ICdmb29iYXIuY29tJykKICAgIHJl"
457       "dHVybiAnUFJPWFkgYmxhY2tob2xlOjgwJzsKICByZXR1cm4gJ0RJUkVDVCc7Cn0=";
458   const char kPacScript[] =
459       "function FindProxyForURL(url, host) {\n"
460       "  if (host == 'foobar.com')\n"
461       "    return 'PROXY blackhole:80';\n"
462       "  return 'DIRECT';\n"
463       "}";
464
465   // Test fetching a "data:"-url containing a base64 encoded PAC script.
466   {
467     GURL url(kEncodedUrl);
468     base::string16 text;
469     TestCompletionCallback callback;
470     int result = pac_fetcher.Fetch(url, &text, callback.callback());
471     EXPECT_EQ(OK, result);
472     EXPECT_EQ(ASCIIToUTF16(kPacScript), text);
473   }
474
475   const char kEncodedUrlBroken[] =
476       "data:application/x-ns-proxy-autoconfig;base64,ZnVuY3Rpb24gRmluZFByb3h5R";
477
478   // Test a broken "data:"-url containing a base64 encoded PAC script.
479   {
480     GURL url(kEncodedUrlBroken);
481     base::string16 text;
482     TestCompletionCallback callback;
483     int result = pac_fetcher.Fetch(url, &text, callback.callback());
484     EXPECT_EQ(ERR_FAILED, result);
485   }
486 }
487
488 }  // namespace net