Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ppapi / tests / test_url_loader.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 "ppapi/tests/test_url_loader.h"
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <string>
10
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/c/ppb_file_io.h"
13 #include "ppapi/c/ppb_url_loader.h"
14 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
15 #include "ppapi/cpp/dev/url_util_dev.h"
16 #include "ppapi/cpp/file_io.h"
17 #include "ppapi/cpp/file_ref.h"
18 #include "ppapi/cpp/file_system.h"
19 #include "ppapi/cpp/instance.h"
20 #include "ppapi/cpp/module.h"
21 #include "ppapi/cpp/private/file_io_private.h"
22 #include "ppapi/cpp/url_loader.h"
23 #include "ppapi/cpp/url_request_info.h"
24 #include "ppapi/cpp/url_response_info.h"
25 #include "ppapi/tests/test_utils.h"
26 #include "ppapi/tests/testing_instance.h"
27
28 REGISTER_TEST_CASE(URLLoader);
29
30 namespace {
31
32 int32_t WriteEntireBuffer(PP_Instance instance,
33                           pp::FileIO* file_io,
34                           int32_t offset,
35                           const std::string& data,
36                           CallbackType callback_type) {
37   TestCompletionCallback callback(instance, callback_type);
38   int32_t write_offset = offset;
39   const char* buf = data.c_str();
40   int32_t size = data.size();
41
42   while (write_offset < offset + size) {
43     callback.WaitForResult(file_io->Write(write_offset,
44                                           &buf[write_offset - offset],
45                                           size - write_offset + offset,
46                                           callback.GetCallback()));
47     if (callback.result() < 0)
48       return callback.result();
49     if (callback.result() == 0)
50       return PP_ERROR_FAILED;
51     write_offset += callback.result();
52   }
53
54   return PP_OK;
55 }
56
57 }  // namespace
58
59 TestURLLoader::TestURLLoader(TestingInstance* instance)
60     : TestCase(instance),
61       file_io_private_interface_(NULL),
62       url_loader_trusted_interface_(NULL) {
63 }
64
65 bool TestURLLoader::Init() {
66   if (!CheckTestingInterface()) {
67     instance_->AppendError("Testing interface not available");
68     return false;
69   }
70
71   const PPB_FileIO* file_io_interface = static_cast<const PPB_FileIO*>(
72       pp::Module::Get()->GetBrowserInterface(PPB_FILEIO_INTERFACE));
73   if (!file_io_interface)
74     instance_->AppendError("FileIO interface not available");
75
76   file_io_private_interface_ = static_cast<const PPB_FileIO_Private*>(
77       pp::Module::Get()->GetBrowserInterface(PPB_FILEIO_PRIVATE_INTERFACE));
78   if (!file_io_private_interface_)
79     instance_->AppendError("FileIO_Private interface not available");
80   url_loader_trusted_interface_ = static_cast<const PPB_URLLoaderTrusted*>(
81       pp::Module::Get()->GetBrowserInterface(PPB_URLLOADERTRUSTED_INTERFACE));
82   if (!testing_interface_->IsOutOfProcess()) {
83     // Trusted interfaces are not supported under NaCl.
84 #if !(defined __native_client__)
85     if (!url_loader_trusted_interface_)
86       instance_->AppendError("URLLoaderTrusted interface not available");
87 #else
88     if (url_loader_trusted_interface_)
89       instance_->AppendError("URLLoaderTrusted interface is supported by NaCl");
90 #endif
91   }
92   return EnsureRunningOverHTTP();
93 }
94
95 /*
96  * The test order is important here, as running tests out of order may cause
97  * test timeout.
98  *
99  * Here is the environment:
100  *
101  * 1. TestServer.py only accepts one open connection at the time.
102  * 2. HTTP socket pool keeps sockets open for several seconds after last use
103  * (hoping that there will be another request that could reuse the connection).
104  * 3. HTTP socket pool is separated by host/port and privacy mode (which is
105  * based on cookies set/get permissions). So, connections to 127.0.0.1,
106  * localhost and localhost in privacy mode cannot reuse existing socket and will
107  * try to open another connection.
108  *
109  * Here is the problem:
110  *
111  * Original test order was repeatedly accessing 127.0.0.1, localhost and
112  * localhost in privacy mode, causing new sockets to open and try to connect to
113  * testserver, which they couldn't until previous connection is closed by socket
114  * pool idle socket timeout (10 seconds).
115  *
116  * Because of this the test run was taking around 45 seconds, and test was
117  * reported as 'timed out' by trybot.
118  *
119  * Re-ordering of tests provides more sequential access to 127.0.0.1, localhost
120  * and localhost in privacy mode. It decreases the number of times when socket
121  * pool doesn't have existing connection to host and has to wait, therefore
122  * reducing total test time and ensuring its completion under 30 seconds.
123  */
124 void TestURLLoader::RunTests(const std::string& filter) {
125   // These tests connect to 127.0.0.1:
126   RUN_CALLBACK_TEST(TestURLLoader, BasicGET, filter);
127   RUN_CALLBACK_TEST(TestURLLoader, BasicPOST, filter);
128   RUN_CALLBACK_TEST(TestURLLoader, BasicFilePOST, filter);
129   RUN_CALLBACK_TEST(TestURLLoader, BasicFileRangePOST, filter);
130   RUN_CALLBACK_TEST(TestURLLoader, CompoundBodyPOST, filter);
131   RUN_CALLBACK_TEST(TestURLLoader, EmptyDataPOST, filter);
132   RUN_CALLBACK_TEST(TestURLLoader, BinaryDataPOST, filter);
133   RUN_CALLBACK_TEST(TestURLLoader, CustomRequestHeader, filter);
134   RUN_CALLBACK_TEST(TestURLLoader, FailsBogusContentLength, filter);
135   RUN_CALLBACK_TEST(TestURLLoader, StreamToFile, filter);
136   RUN_CALLBACK_TEST(TestURLLoader, UntrustedJavascriptURLRestriction, filter);
137   RUN_CALLBACK_TEST(TestURLLoader, TrustedJavascriptURLRestriction, filter);
138   RUN_CALLBACK_TEST(TestURLLoader, UntrustedHttpRequests, filter);
139   RUN_CALLBACK_TEST(TestURLLoader, TrustedHttpRequests, filter);
140   RUN_CALLBACK_TEST(TestURLLoader, FollowURLRedirect, filter);
141   RUN_CALLBACK_TEST(TestURLLoader, AuditURLRedirect, filter);
142   RUN_CALLBACK_TEST(TestURLLoader, AbortCalls, filter);
143   RUN_CALLBACK_TEST(TestURLLoader, UntendedLoad, filter);
144   RUN_CALLBACK_TEST(TestURLLoader, PrefetchBufferThreshold, filter);
145   // These tests connect to localhost with privacy mode enabled:
146   RUN_CALLBACK_TEST(TestURLLoader, UntrustedSameOriginRestriction, filter);
147   RUN_CALLBACK_TEST(TestURLLoader, UntrustedCrossOriginRequest, filter);
148   // These tests connect to localhost with privacy mode disabled:
149   RUN_CALLBACK_TEST(TestURLLoader, TrustedSameOriginRestriction, filter);
150   RUN_CALLBACK_TEST(TestURLLoader, TrustedCrossOriginRequest, filter);
151 }
152
153 std::string TestURLLoader::ReadEntireFile(pp::FileIO* file_io,
154                                           std::string* data) {
155   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
156   char buf[256];
157   int64_t offset = 0;
158
159   for (;;) {
160     callback.WaitForResult(file_io->Read(offset, buf, sizeof(buf),
161                            callback.GetCallback()));
162     if (callback.result() < 0)
163       return ReportError("FileIO::Read", callback.result());
164     if (callback.result() == 0)
165       break;
166     offset += callback.result();
167     data->append(buf, callback.result());
168   }
169
170   PASS();
171 }
172
173 std::string TestURLLoader::ReadEntireResponseBody(pp::URLLoader* loader,
174                                                   std::string* body) {
175   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
176   char buf[2];  // Small so that multiple reads are needed.
177
178   for (;;) {
179     callback.WaitForResult(
180         loader->ReadResponseBody(buf, sizeof(buf), callback.GetCallback()));
181     if (callback.result() < 0)
182       return ReportError("URLLoader::ReadResponseBody", callback.result());
183     if (callback.result() == 0)
184       break;
185     body->append(buf, callback.result());
186   }
187
188   PASS();
189 }
190
191 std::string TestURLLoader::LoadAndCompareBody(
192     const pp::URLRequestInfo& request,
193     const std::string& expected_body) {
194   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
195
196   pp::URLLoader loader(instance_);
197   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
198   CHECK_CALLBACK_BEHAVIOR(callback);
199   ASSERT_EQ(PP_OK, callback.result());
200
201   pp::URLResponseInfo response_info(loader.GetResponseInfo());
202   if (response_info.is_null())
203     return "URLLoader::GetResponseInfo returned null";
204   int32_t status_code = response_info.GetStatusCode();
205   if (status_code != 200)
206     return "Unexpected HTTP status code";
207
208   std::string body;
209   std::string error = ReadEntireResponseBody(&loader, &body);
210   if (!error.empty())
211     return error;
212
213   if (body.size() != expected_body.size())
214     return "URLLoader::ReadResponseBody returned unexpected content length";
215   if (body != expected_body)
216     return "URLLoader::ReadResponseBody returned unexpected content";
217
218   PASS();
219 }
220
221 int32_t TestURLLoader::OpenFileSystem(pp::FileSystem* file_system,
222                                       std::string* message) {
223   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
224   callback.WaitForResult(file_system->Open(1024, callback.GetCallback()));
225   if (callback.failed()) {
226     message->assign(callback.errors());
227     return callback.result();
228   }
229   if (callback.result() != PP_OK) {
230     message->assign("FileSystem::Open");
231     return callback.result();
232   }
233   return callback.result();
234 }
235
236 int32_t TestURLLoader::PrepareFileForPost(
237       const pp::FileRef& file_ref,
238       const std::string& data,
239       std::string* message) {
240   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
241   pp::FileIO file_io(instance_);
242   callback.WaitForResult(file_io.Open(file_ref,
243                                       PP_FILEOPENFLAG_CREATE |
244                                       PP_FILEOPENFLAG_TRUNCATE |
245                                       PP_FILEOPENFLAG_WRITE,
246                                       callback.GetCallback()));
247   if (callback.failed()) {
248     message->assign(callback.errors());
249     return callback.result();
250   }
251   if (callback.result() != PP_OK) {
252     message->assign("FileIO::Open failed.");
253     return callback.result();
254   }
255
256   int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0, data,
257                                  callback_type());
258   if (rv != PP_OK) {
259     message->assign("FileIO::Write failed.");
260     return rv;
261   }
262
263   return rv;
264 }
265
266 std::string TestURLLoader::GetReachableAbsoluteURL(
267     const std::string& file_name) {
268   // Get the absolute page URL and replace the test case file name
269   // with the given one.
270   pp::Var document_url(
271       pp::PASS_REF,
272       testing_interface_->GetDocumentURL(instance_->pp_instance(),
273                                          NULL));
274   std::string url(document_url.AsString());
275   std::string old_name("test_case.html");
276   size_t index = url.find(old_name);
277   ASSERT_NE(index, std::string::npos);
278   url.replace(index, old_name.length(), file_name);
279   return url;
280 }
281
282 std::string TestURLLoader::GetReachableCrossOriginURL(
283     const std::string& file_name) {
284   // Get an absolute URL and use it to construct a URL that will be
285   // considered cross-origin by the CORS access control code, and yet be
286   // reachable by the test server.
287   std::string url = GetReachableAbsoluteURL(file_name);
288   // Replace '127.0.0.1' with 'localhost'.
289   std::string host("127.0.0.1");
290   size_t index = url.find(host);
291   ASSERT_NE(index, std::string::npos);
292   url.replace(index, host.length(), "localhost");
293   return url;
294 }
295
296 int32_t TestURLLoader::OpenUntrusted(const std::string& method,
297                                      const std::string& header) {
298   pp::URLRequestInfo request(instance_);
299   request.SetURL("/echo");
300   request.SetMethod(method);
301   request.SetHeaders(header);
302
303   return OpenUntrusted(request);
304 }
305
306 int32_t TestURLLoader::OpenTrusted(const std::string& method,
307                                    const std::string& header) {
308   pp::URLRequestInfo request(instance_);
309   request.SetURL("/echo");
310   request.SetMethod(method);
311   request.SetHeaders(header);
312
313   return OpenTrusted(request);
314 }
315
316 int32_t TestURLLoader::OpenUntrusted(const pp::URLRequestInfo& request) {
317   return Open(request, false);
318 }
319
320 int32_t TestURLLoader::OpenTrusted(const pp::URLRequestInfo& request) {
321   return Open(request, true);
322 }
323
324 int32_t TestURLLoader::Open(const pp::URLRequestInfo& request,
325                             bool trusted) {
326   pp::URLLoader loader(instance_);
327   if (trusted)
328     url_loader_trusted_interface_->GrantUniversalAccess(loader.pp_resource());
329   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
330   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
331   return callback.result();
332 }
333
334 std::string TestURLLoader::TestBasicGET() {
335   pp::URLRequestInfo request(instance_);
336   request.SetURL("test_url_loader_data/hello.txt");
337   return LoadAndCompareBody(request, "hello\n");
338 }
339
340 std::string TestURLLoader::TestBasicPOST() {
341   pp::URLRequestInfo request(instance_);
342   request.SetURL("/echo");
343   request.SetMethod("POST");
344   std::string postdata("postdata");
345   request.AppendDataToBody(postdata.data(), postdata.length());
346   return LoadAndCompareBody(request, postdata);
347 }
348
349 std::string TestURLLoader::TestBasicFilePOST() {
350   std::string message;
351
352   pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
353   int32_t rv = OpenFileSystem(&file_system, &message);
354   if (rv != PP_OK)
355     return ReportError(message.c_str(), rv);
356
357   pp::FileRef file_ref(file_system, "/file_post_test");
358   std::string postdata("postdata");
359   rv = PrepareFileForPost(file_ref, postdata, &message);
360   if (rv != PP_OK)
361     return ReportError(message.c_str(), rv);
362
363   pp::URLRequestInfo request(instance_);
364   request.SetURL("/echo");
365   request.SetMethod("POST");
366   request.AppendFileToBody(file_ref, 0);
367   return LoadAndCompareBody(request, postdata);
368 }
369
370 std::string TestURLLoader::TestBasicFileRangePOST() {
371   std::string message;
372
373   pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
374   int32_t rv = OpenFileSystem(&file_system, &message);
375   if (rv != PP_OK)
376     return ReportError(message.c_str(), rv);
377
378   pp::FileRef file_ref(file_system, "/file_range_post_test");
379   std::string postdata("postdatapostdata");
380   rv = PrepareFileForPost(file_ref, postdata, &message);
381   if (rv != PP_OK)
382     return ReportError(message.c_str(), rv);
383
384   pp::URLRequestInfo request(instance_);
385   request.SetURL("/echo");
386   request.SetMethod("POST");
387   request.AppendFileRangeToBody(file_ref, 4, 12, 0);
388   return LoadAndCompareBody(request, postdata.substr(4, 12));
389 }
390
391 std::string TestURLLoader::TestCompoundBodyPOST() {
392   pp::URLRequestInfo request(instance_);
393   request.SetURL("/echo");
394   request.SetMethod("POST");
395   std::string postdata1("post");
396   request.AppendDataToBody(postdata1.data(), postdata1.length());
397   std::string postdata2("data");
398   request.AppendDataToBody(postdata2.data(), postdata2.length());
399   return LoadAndCompareBody(request, postdata1 + postdata2);
400 }
401
402 std::string TestURLLoader::TestEmptyDataPOST() {
403   pp::URLRequestInfo request(instance_);
404   request.SetURL("/echo");
405   request.SetMethod("POST");
406   request.AppendDataToBody("", 0);
407   return LoadAndCompareBody(request, std::string());
408 }
409
410 std::string TestURLLoader::TestBinaryDataPOST() {
411   pp::URLRequestInfo request(instance_);
412   request.SetURL("/echo");
413   request.SetMethod("POST");
414   const char postdata_chars[] =
415       "\x00\x01\x02\x03\x04\x05postdata\xfa\xfb\xfc\xfd\xfe\xff";
416   std::string postdata(postdata_chars,
417                        sizeof(postdata_chars) / sizeof(postdata_chars[0]));
418   request.AppendDataToBody(postdata.data(), postdata.length());
419   return LoadAndCompareBody(request, postdata);
420 }
421
422 std::string TestURLLoader::TestCustomRequestHeader() {
423   pp::URLRequestInfo request(instance_);
424   request.SetURL("/echoheader?Foo");
425   request.SetHeaders("Foo: 1");
426   return LoadAndCompareBody(request, "1");
427 }
428
429 std::string TestURLLoader::TestFailsBogusContentLength() {
430   pp::URLRequestInfo request(instance_);
431   request.SetURL("/echo");
432   request.SetMethod("POST");
433   request.SetHeaders("Content-Length: 400");
434   std::string postdata("postdata");
435   request.AppendDataToBody(postdata.data(), postdata.length());
436
437   int32_t rv;
438   rv = OpenUntrusted(request);
439   if (rv != PP_ERROR_NOACCESS)
440     return ReportError(
441         "Untrusted request with bogus Content-Length restriction", rv);
442
443   PASS();
444 }
445
446 std::string TestURLLoader::TestStreamToFile() {
447   pp::URLRequestInfo request(instance_);
448   request.SetURL("test_url_loader_data/hello.txt");
449   request.SetStreamToFile(true);
450
451   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
452
453   pp::URLLoader loader(instance_);
454   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
455   CHECK_CALLBACK_BEHAVIOR(callback);
456   ASSERT_EQ(PP_OK, callback.result());
457
458   pp::URLResponseInfo response_info(loader.GetResponseInfo());
459   if (response_info.is_null())
460     return "URLLoader::GetResponseInfo returned null";
461   int32_t status_code = response_info.GetStatusCode();
462   if (status_code != 200)
463     return "Unexpected HTTP status code";
464
465   pp::FileRef body(response_info.GetBodyAsFileRef());
466   if (body.is_null())
467     return "URLResponseInfo::GetBody returned null";
468
469   callback.WaitForResult(loader.FinishStreamingToFile(callback.GetCallback()));
470   CHECK_CALLBACK_BEHAVIOR(callback);
471   ASSERT_EQ(PP_OK, callback.result());
472
473   pp::FileIO reader(instance_);
474   callback.WaitForResult(reader.Open(body, PP_FILEOPENFLAG_READ,
475                                      callback.GetCallback()));
476   CHECK_CALLBACK_BEHAVIOR(callback);
477   ASSERT_EQ(PP_OK, callback.result());
478
479   std::string data;
480   std::string error = ReadEntireFile(&reader, &data);
481   if (!error.empty())
482     return error;
483
484   std::string expected_body = "hello\n";
485   if (data.size() != expected_body.size())
486     return "ReadEntireFile returned unexpected content length";
487   if (data != expected_body)
488     return "ReadEntireFile returned unexpected content";
489
490   PASS();
491 }
492
493 // Untrusted, unintended cross-origin requests should fail.
494 std::string TestURLLoader::TestUntrustedSameOriginRestriction() {
495   pp::URLRequestInfo request(instance_);
496   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
497   request.SetURL(cross_origin_url);
498
499   int32_t rv = OpenUntrusted(request);
500   if (rv != PP_ERROR_NOACCESS)
501     return ReportError(
502         "Untrusted, unintended cross-origin request restriction", rv);
503
504   PASS();
505 }
506
507 // Trusted, unintended cross-origin requests should succeed.
508 std::string TestURLLoader::TestTrustedSameOriginRestriction() {
509   pp::URLRequestInfo request(instance_);
510   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
511   request.SetURL(cross_origin_url);
512
513   int32_t rv = OpenTrusted(request);
514   if (rv != PP_OK)
515     return ReportError("Trusted cross-origin request failed", rv);
516
517   PASS();
518 }
519
520 // Untrusted, intended cross-origin requests should use CORS and succeed.
521 std::string TestURLLoader::TestUntrustedCrossOriginRequest() {
522   pp::URLRequestInfo request(instance_);
523   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
524   request.SetURL(cross_origin_url);
525   request.SetAllowCrossOriginRequests(true);
526
527   int32_t rv = OpenUntrusted(request);
528   if (rv != PP_OK)
529     return ReportError(
530         "Untrusted, intended cross-origin request failed", rv);
531
532   PASS();
533 }
534
535 // Trusted, intended cross-origin requests should use CORS and succeed.
536 std::string TestURLLoader::TestTrustedCrossOriginRequest() {
537   pp::URLRequestInfo request(instance_);
538   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
539   request.SetURL(cross_origin_url);
540   request.SetAllowCrossOriginRequests(true);
541
542   int32_t rv = OpenTrusted(request);
543   if (rv != PP_OK)
544     return ReportError("Trusted cross-origin request failed", rv);
545
546   PASS();
547 }
548
549 // Untrusted Javascript URLs requests should fail.
550 std::string TestURLLoader::TestUntrustedJavascriptURLRestriction() {
551   pp::URLRequestInfo request(instance_);
552   request.SetURL("javascript:foo = bar");
553
554   int32_t rv = OpenUntrusted(request);
555   if (rv != PP_ERROR_NOACCESS)
556     return ReportError(
557         "Untrusted Javascript URL request restriction failed", rv);
558
559   PASS();
560 }
561
562 // Trusted Javascript URLs requests should succeed.
563 std::string TestURLLoader::TestTrustedJavascriptURLRestriction() {
564   pp::URLRequestInfo request(instance_);
565   request.SetURL("javascript:foo = bar");
566
567   int32_t rv = OpenTrusted(request);
568   if (rv == PP_ERROR_NOACCESS)
569   return ReportError(
570       "Trusted Javascript URL request", rv);
571
572   PASS();
573 }
574
575 std::string TestURLLoader::TestUntrustedHttpRequests() {
576   // HTTP methods are restricted only for untrusted loaders. Forbidden
577   // methods are CONNECT, TRACE, and TRACK, and any string that is not a
578   // valid token (containing special characters like CR, LF).
579   // http://www.w3.org/TR/XMLHttpRequest/
580   {
581     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("cOnNeCt", std::string()));
582     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("tRaCk", std::string()));
583     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("tRaCe", std::string()));
584     ASSERT_EQ(PP_ERROR_NOACCESS,
585         OpenUntrusted("POST\x0d\x0ax-csrf-token:\x20test1234", std::string()));
586   }
587   // HTTP methods are restricted only for untrusted loaders. Try all headers
588   // that are forbidden by http://www.w3.org/TR/XMLHttpRequest/.
589   {
590     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Accept-Charset:\n"));
591     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Accept-Encoding:\n"));
592     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Connection:\n"));
593     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Content-Length:\n"));
594     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Cookie:\n"));
595     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Cookie2:\n"));
596     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Date:\n"));
597     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Dnt:\n"));
598     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Expect:\n"));
599     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Host:\n"));
600     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Keep-Alive:\n"));
601     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Referer:\n"));
602     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "TE:\n"));
603     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Trailer:\n"));
604     ASSERT_EQ(PP_ERROR_NOACCESS,
605               OpenUntrusted("GET", "Transfer-Encoding:\n"));
606     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Upgrade:\n"));
607     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "User-Agent:\n"));
608     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Via:\n"));
609     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted(
610         "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
611     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Sec-foo:\n"));
612   }
613   // Untrusted requests with custom referrer should fail.
614   {
615     pp::URLRequestInfo request(instance_);
616     request.SetCustomReferrerURL("http://www.google.com/");
617
618     int32_t rv = OpenUntrusted(request);
619     if (rv != PP_ERROR_NOACCESS)
620       return ReportError(
621           "Untrusted request with custom referrer restriction", rv);
622   }
623   // Untrusted requests with custom transfer encodings should fail.
624   {
625     pp::URLRequestInfo request(instance_);
626     request.SetCustomContentTransferEncoding("foo");
627
628     int32_t rv = OpenUntrusted(request);
629     if (rv != PP_ERROR_NOACCESS)
630       return ReportError(
631           "Untrusted request with content-transfer-encoding restriction", rv);
632   }
633
634   PASS();
635 }
636
637 std::string TestURLLoader::TestTrustedHttpRequests() {
638   // Trusted requests can use restricted methods.
639   {
640     ASSERT_EQ(PP_OK, OpenTrusted("cOnNeCt", std::string()));
641     ASSERT_EQ(PP_OK, OpenTrusted("tRaCk", std::string()));
642     ASSERT_EQ(PP_OK, OpenTrusted("tRaCe", std::string()));
643   }
644   // Trusted requests can use restricted headers.
645   {
646     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Accept-Charset:\n"));
647     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Accept-Encoding:\n"));
648     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Connection:\n"));
649     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Content-Length:\n"));
650     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Cookie:\n"));
651     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Cookie2:\n"));
652     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Content-Transfer-Encoding:\n"));
653     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Date:\n"));
654     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Expect:\n"));
655     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Host:\n"));
656     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Keep-Alive:\n"));
657     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Referer:\n"));
658     ASSERT_EQ(PP_OK, OpenTrusted("GET", "TE:\n"));
659     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Trailer:\n"));
660     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Transfer-Encoding:\n"));
661     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Upgrade:\n"));
662     ASSERT_EQ(PP_OK, OpenTrusted("GET", "User-Agent:\n"));
663     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Via:\n"));
664     ASSERT_EQ(PP_OK,
665               OpenTrusted("GET",
666                   "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
667     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Sec-foo:\n"));
668   }
669   // Trusted requests with custom referrer should succeed.
670   {
671     pp::URLRequestInfo request(instance_);
672     request.SetCustomReferrerURL("http://www.google.com/");
673
674     int32_t rv = OpenTrusted(request);
675     if (rv != PP_OK)
676       return ReportError("Trusted request with custom referrer", rv);
677   }
678   // Trusted requests with custom transfer encodings should succeed.
679   {
680     pp::URLRequestInfo request(instance_);
681     request.SetCustomContentTransferEncoding("foo");
682
683     int32_t rv = OpenTrusted(request);
684     if (rv != PP_OK)
685       return ReportError(
686           "Trusted request with content-transfer-encoding failed", rv);
687   }
688
689   PASS();
690 }
691
692 // This test should cause a redirect and ensure that the loader follows it.
693 std::string TestURLLoader::TestFollowURLRedirect() {
694   pp::URLRequestInfo request(instance_);
695   // This prefix causes the test server to return a 301 redirect.
696   std::string redirect_prefix("/server-redirect?");
697   // We need an absolute path for the redirect to actually work.
698   std::string redirect_url =
699       GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
700   request.SetURL(redirect_prefix.append(redirect_url));
701   return LoadAndCompareBody(request, "hello\n");
702 }
703
704 // This test should cause a redirect and ensure that the loader runs
705 // the callback, rather than following the redirect.
706 std::string TestURLLoader::TestAuditURLRedirect() {
707   pp::URLRequestInfo request(instance_);
708   // This path will cause the server to return a 301 redirect.
709   // This prefix causes the test server to return a 301 redirect.
710   std::string redirect_prefix("/server-redirect?");
711   // We need an absolute path for the redirect to actually work.
712   std::string redirect_url =
713       GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
714   request.SetURL(redirect_prefix.append(redirect_url));
715   request.SetFollowRedirects(false);
716
717   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
718
719   pp::URLLoader loader(instance_);
720   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
721   CHECK_CALLBACK_BEHAVIOR(callback);
722   ASSERT_EQ(PP_OK, callback.result());
723
724   // Checks that the response indicates a redirect, and that the URL
725   // is correct.
726   pp::URLResponseInfo response_info(loader.GetResponseInfo());
727   if (response_info.is_null())
728     return "URLLoader::GetResponseInfo returned null";
729   int32_t status_code = response_info.GetStatusCode();
730   if (status_code != 301)
731     return "Response status should be 301";
732
733   // Test that the paused loader can be resumed.
734   callback.WaitForResult(loader.FollowRedirect(callback.GetCallback()));
735   CHECK_CALLBACK_BEHAVIOR(callback);
736   ASSERT_EQ(PP_OK, callback.result());
737   std::string body;
738   std::string error = ReadEntireResponseBody(&loader, &body);
739   if (!error.empty())
740     return error;
741
742   if (body != "hello\n")
743     return "URLLoader::FollowRedirect failed";
744
745   PASS();
746 }
747
748 std::string TestURLLoader::TestAbortCalls() {
749   pp::URLRequestInfo request(instance_);
750   request.SetURL("test_url_loader_data/hello.txt");
751
752   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
753   int32_t rv;
754
755   // Abort |Open()|.
756   {
757     rv = pp::URLLoader(instance_).Open(request, callback.GetCallback());
758   }
759   callback.WaitForAbortResult(rv);
760   CHECK_CALLBACK_BEHAVIOR(callback);
761
762   // Abort |ReadResponseBody()|.
763   {
764     char buf[2] = { 0 };
765     {
766       pp::URLLoader loader(instance_);
767       callback.WaitForResult(loader.Open(request, callback.GetCallback()));
768       CHECK_CALLBACK_BEHAVIOR(callback);
769       ASSERT_EQ(PP_OK, callback.result());
770
771       rv = loader.ReadResponseBody(buf, sizeof(buf), callback.GetCallback());
772     }  // Destroy |loader|.
773     callback.WaitForAbortResult(rv);
774     CHECK_CALLBACK_BEHAVIOR(callback);
775     if (rv == PP_OK_COMPLETIONPENDING) {
776       if (buf[0] || buf[1]) {
777         return "URLLoader::ReadResponseBody wrote data after resource "
778                "destruction.";
779       }
780     }
781   }
782
783   // TODO(viettrungluu): More abort tests (but add basic tests first).
784   // Also test that Close() aborts properly. crbug.com/69457
785
786   PASS();
787 }
788
789 std::string TestURLLoader::TestUntendedLoad() {
790   pp::URLRequestInfo request(instance_);
791   request.SetURL("test_url_loader_data/hello.txt");
792   request.SetRecordDownloadProgress(true);
793   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
794
795   pp::URLLoader loader(instance_);
796   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
797   CHECK_CALLBACK_BEHAVIOR(callback);
798   ASSERT_EQ(PP_OK, callback.result());
799
800   // We received the response callback. Yield until the network code has called
801   // the loader's didReceiveData and didFinishLoading methods before we give it
802   // another callback function, to make sure the loader works with no callback.
803   int64_t bytes_received = 0;
804   int64_t total_bytes_to_be_received = 0;
805   while (true) {
806     loader.GetDownloadProgress(&bytes_received, &total_bytes_to_be_received);
807     if (total_bytes_to_be_received <= 0)
808       return ReportError("URLLoader::GetDownloadProgress total size",
809           total_bytes_to_be_received);
810     if (bytes_received == total_bytes_to_be_received)
811       break;
812     // Yield if we're on the main thread, so that URLLoader can receive more
813     // data.
814     if (pp::Module::Get()->core()->IsMainThread()) {
815       NestedEvent event(instance_->pp_instance());
816       event.PostSignal(10);
817       event.Wait();
818     }
819   }
820   // The loader should now have the data and have finished successfully.
821   std::string body;
822   std::string error = ReadEntireResponseBody(&loader, &body);
823   if (!error.empty())
824     return error;
825   if (body != "hello\n")
826     return ReportError("Couldn't read data", callback.result());
827
828   PASS();
829 }
830
831 int32_t TestURLLoader::OpenWithPrefetchBufferThreshold(int32_t lower,
832                                                        int32_t upper) {
833   pp::URLRequestInfo request(instance_);
834   request.SetURL("test_url_loader_data/hello.txt");
835   request.SetPrefetchBufferLowerThreshold(lower);
836   request.SetPrefetchBufferUpperThreshold(upper);
837
838   return OpenUntrusted(request);
839 }
840
841 std::string TestURLLoader::TestPrefetchBufferThreshold() {
842   int32_t rv = OpenWithPrefetchBufferThreshold(-1, 1);
843   if (rv != PP_ERROR_FAILED) {
844     return ReportError("The prefetch limits contained a negative value but "
845                        "the URLLoader did not fail.", rv);
846   }
847
848   rv = OpenWithPrefetchBufferThreshold(0, 1);
849   if (rv != PP_OK) {
850     return ReportError("The prefetch buffer limits were legal values but "
851                        "the URLLoader failed.", rv);
852   }
853
854   rv = OpenWithPrefetchBufferThreshold(1000, 1);
855   if (rv != PP_ERROR_FAILED) {
856     return ReportError("The lower buffer value was higher than the upper but "
857                        "the URLLoader did not fail.", rv);
858   }
859
860   PASS();
861 }
862
863 // TODO(viettrungluu): Add tests for  Get{Upload,Download}Progress, Close
864 // (including abort tests if applicable).