Upstream version 11.40.277.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   RUN_CALLBACK_TEST(TestURLLoader, XRequestedWithHeader, filter);
146   // These tests connect to localhost with privacy mode enabled:
147   RUN_CALLBACK_TEST(TestURLLoader, UntrustedSameOriginRestriction, filter);
148   RUN_CALLBACK_TEST(TestURLLoader, UntrustedCrossOriginRequest, filter);
149   // These tests connect to localhost with privacy mode disabled:
150   RUN_CALLBACK_TEST(TestURLLoader, TrustedSameOriginRestriction, filter);
151   RUN_CALLBACK_TEST(TestURLLoader, TrustedCrossOriginRequest, filter);
152 }
153
154 std::string TestURLLoader::ReadEntireFile(pp::FileIO* file_io,
155                                           std::string* data) {
156   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
157   char buf[256];
158   int64_t offset = 0;
159
160   for (;;) {
161     callback.WaitForResult(file_io->Read(offset, buf, sizeof(buf),
162                            callback.GetCallback()));
163     if (callback.result() < 0)
164       return ReportError("FileIO::Read", callback.result());
165     if (callback.result() == 0)
166       break;
167     offset += callback.result();
168     data->append(buf, callback.result());
169   }
170
171   PASS();
172 }
173
174 std::string TestURLLoader::ReadEntireResponseBody(pp::URLLoader* loader,
175                                                   std::string* body) {
176   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
177   char buf[2];  // Small so that multiple reads are needed.
178
179   for (;;) {
180     callback.WaitForResult(
181         loader->ReadResponseBody(buf, sizeof(buf), callback.GetCallback()));
182     if (callback.result() < 0)
183       return ReportError("URLLoader::ReadResponseBody", callback.result());
184     if (callback.result() == 0)
185       break;
186     body->append(buf, callback.result());
187   }
188
189   PASS();
190 }
191
192 std::string TestURLLoader::LoadAndCompareBody(
193     const pp::URLRequestInfo& request,
194     const std::string& expected_body) {
195   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
196
197   pp::URLLoader loader(instance_);
198   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
199   CHECK_CALLBACK_BEHAVIOR(callback);
200   ASSERT_EQ(PP_OK, callback.result());
201
202   pp::URLResponseInfo response_info(loader.GetResponseInfo());
203   if (response_info.is_null())
204     return "URLLoader::GetResponseInfo returned null";
205   int32_t status_code = response_info.GetStatusCode();
206   if (status_code != 200)
207     return "Unexpected HTTP status code";
208
209   std::string body;
210   std::string error = ReadEntireResponseBody(&loader, &body);
211   if (!error.empty())
212     return error;
213
214   if (body.size() != expected_body.size())
215     return "URLLoader::ReadResponseBody returned unexpected content length";
216   if (body != expected_body)
217     return "URLLoader::ReadResponseBody returned unexpected content";
218
219   PASS();
220 }
221
222 int32_t TestURLLoader::OpenFileSystem(pp::FileSystem* file_system,
223                                       std::string* message) {
224   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
225   callback.WaitForResult(file_system->Open(1024, callback.GetCallback()));
226   if (callback.failed()) {
227     message->assign(callback.errors());
228     return callback.result();
229   }
230   if (callback.result() != PP_OK) {
231     message->assign("FileSystem::Open");
232     return callback.result();
233   }
234   return callback.result();
235 }
236
237 int32_t TestURLLoader::PrepareFileForPost(
238       const pp::FileRef& file_ref,
239       const std::string& data,
240       std::string* message) {
241   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
242   pp::FileIO file_io(instance_);
243   callback.WaitForResult(file_io.Open(file_ref,
244                                       PP_FILEOPENFLAG_CREATE |
245                                       PP_FILEOPENFLAG_TRUNCATE |
246                                       PP_FILEOPENFLAG_WRITE,
247                                       callback.GetCallback()));
248   if (callback.failed()) {
249     message->assign(callback.errors());
250     return callback.result();
251   }
252   if (callback.result() != PP_OK) {
253     message->assign("FileIO::Open failed.");
254     return callback.result();
255   }
256
257   int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0, data,
258                                  callback_type());
259   if (rv != PP_OK) {
260     message->assign("FileIO::Write failed.");
261     return rv;
262   }
263
264   return rv;
265 }
266
267 std::string TestURLLoader::GetReachableAbsoluteURL(
268     const std::string& file_name) {
269   // Get the absolute page URL and replace the test case file name
270   // with the given one.
271   pp::Var document_url(
272       pp::PASS_REF,
273       testing_interface_->GetDocumentURL(instance_->pp_instance(),
274                                          NULL));
275   std::string url(document_url.AsString());
276   std::string old_name("test_case.html");
277   size_t index = url.find(old_name);
278   ASSERT_NE(index, std::string::npos);
279   url.replace(index, old_name.length(), file_name);
280   return url;
281 }
282
283 std::string TestURLLoader::GetReachableCrossOriginURL(
284     const std::string& file_name) {
285   // Get an absolute URL and use it to construct a URL that will be
286   // considered cross-origin by the CORS access control code, and yet be
287   // reachable by the test server.
288   std::string url = GetReachableAbsoluteURL(file_name);
289   // Replace '127.0.0.1' with 'localhost'.
290   std::string host("127.0.0.1");
291   size_t index = url.find(host);
292   ASSERT_NE(index, std::string::npos);
293   url.replace(index, host.length(), "localhost");
294   return url;
295 }
296
297 int32_t TestURLLoader::OpenUntrusted(const std::string& method,
298                                      const std::string& header) {
299   pp::URLRequestInfo request(instance_);
300   request.SetURL("/echo");
301   request.SetMethod(method);
302   request.SetHeaders(header);
303
304   return OpenUntrusted(request);
305 }
306
307 int32_t TestURLLoader::OpenTrusted(const std::string& method,
308                                    const std::string& header) {
309   pp::URLRequestInfo request(instance_);
310   request.SetURL("/echo");
311   request.SetMethod(method);
312   request.SetHeaders(header);
313
314   return OpenTrusted(request);
315 }
316
317 int32_t TestURLLoader::OpenUntrusted(const pp::URLRequestInfo& request) {
318   return Open(request, false);
319 }
320
321 int32_t TestURLLoader::OpenTrusted(const pp::URLRequestInfo& request) {
322   return Open(request, true);
323 }
324
325 int32_t TestURLLoader::Open(const pp::URLRequestInfo& request,
326                             bool trusted) {
327   pp::URLLoader loader(instance_);
328   if (trusted)
329     url_loader_trusted_interface_->GrantUniversalAccess(loader.pp_resource());
330   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
331   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
332   return callback.result();
333 }
334
335 std::string TestURLLoader::TestBasicGET() {
336   pp::URLRequestInfo request(instance_);
337   request.SetURL("test_url_loader_data/hello.txt");
338   return LoadAndCompareBody(request, "hello\n");
339 }
340
341 std::string TestURLLoader::TestBasicPOST() {
342   pp::URLRequestInfo request(instance_);
343   request.SetURL("/echo");
344   request.SetMethod("POST");
345   std::string postdata("postdata");
346   request.AppendDataToBody(postdata.data(), postdata.length());
347   return LoadAndCompareBody(request, postdata);
348 }
349
350 std::string TestURLLoader::TestBasicFilePOST() {
351   std::string message;
352
353   pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
354   int32_t rv = OpenFileSystem(&file_system, &message);
355   if (rv != PP_OK)
356     return ReportError(message.c_str(), rv);
357
358   pp::FileRef file_ref(file_system, "/file_post_test");
359   std::string postdata("postdata");
360   rv = PrepareFileForPost(file_ref, postdata, &message);
361   if (rv != PP_OK)
362     return ReportError(message.c_str(), rv);
363
364   pp::URLRequestInfo request(instance_);
365   request.SetURL("/echo");
366   request.SetMethod("POST");
367   request.AppendFileToBody(file_ref, 0);
368   return LoadAndCompareBody(request, postdata);
369 }
370
371 std::string TestURLLoader::TestBasicFileRangePOST() {
372   std::string message;
373
374   pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
375   int32_t rv = OpenFileSystem(&file_system, &message);
376   if (rv != PP_OK)
377     return ReportError(message.c_str(), rv);
378
379   pp::FileRef file_ref(file_system, "/file_range_post_test");
380   std::string postdata("postdatapostdata");
381   rv = PrepareFileForPost(file_ref, postdata, &message);
382   if (rv != PP_OK)
383     return ReportError(message.c_str(), rv);
384
385   pp::URLRequestInfo request(instance_);
386   request.SetURL("/echo");
387   request.SetMethod("POST");
388   request.AppendFileRangeToBody(file_ref, 4, 12, 0);
389   return LoadAndCompareBody(request, postdata.substr(4, 12));
390 }
391
392 std::string TestURLLoader::TestCompoundBodyPOST() {
393   pp::URLRequestInfo request(instance_);
394   request.SetURL("/echo");
395   request.SetMethod("POST");
396   std::string postdata1("post");
397   request.AppendDataToBody(postdata1.data(), postdata1.length());
398   std::string postdata2("data");
399   request.AppendDataToBody(postdata2.data(), postdata2.length());
400   return LoadAndCompareBody(request, postdata1 + postdata2);
401 }
402
403 std::string TestURLLoader::TestEmptyDataPOST() {
404   pp::URLRequestInfo request(instance_);
405   request.SetURL("/echo");
406   request.SetMethod("POST");
407   request.AppendDataToBody("", 0);
408   return LoadAndCompareBody(request, std::string());
409 }
410
411 std::string TestURLLoader::TestBinaryDataPOST() {
412   pp::URLRequestInfo request(instance_);
413   request.SetURL("/echo");
414   request.SetMethod("POST");
415   const char postdata_chars[] =
416       "\x00\x01\x02\x03\x04\x05postdata\xfa\xfb\xfc\xfd\xfe\xff";
417   std::string postdata(postdata_chars,
418                        sizeof(postdata_chars) / sizeof(postdata_chars[0]));
419   request.AppendDataToBody(postdata.data(), postdata.length());
420   return LoadAndCompareBody(request, postdata);
421 }
422
423 std::string TestURLLoader::TestCustomRequestHeader() {
424   pp::URLRequestInfo request(instance_);
425   request.SetURL("/echoheader?Foo");
426   request.SetHeaders("Foo: 1");
427   return LoadAndCompareBody(request, "1");
428 }
429
430 std::string TestURLLoader::TestFailsBogusContentLength() {
431   pp::URLRequestInfo request(instance_);
432   request.SetURL("/echo");
433   request.SetMethod("POST");
434   request.SetHeaders("Content-Length: 400");
435   std::string postdata("postdata");
436   request.AppendDataToBody(postdata.data(), postdata.length());
437
438   int32_t rv;
439   rv = OpenUntrusted(request);
440   if (rv != PP_ERROR_NOACCESS)
441     return ReportError(
442         "Untrusted request with bogus Content-Length restriction", rv);
443
444   PASS();
445 }
446
447 std::string TestURLLoader::TestStreamToFile() {
448   pp::URLRequestInfo request(instance_);
449   request.SetURL("test_url_loader_data/hello.txt");
450   request.SetStreamToFile(true);
451
452   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
453
454   pp::URLLoader loader(instance_);
455   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
456   CHECK_CALLBACK_BEHAVIOR(callback);
457   ASSERT_EQ(PP_OK, callback.result());
458
459   pp::URLResponseInfo response_info(loader.GetResponseInfo());
460   if (response_info.is_null())
461     return "URLLoader::GetResponseInfo returned null";
462   int32_t status_code = response_info.GetStatusCode();
463   if (status_code != 200)
464     return "Unexpected HTTP status code";
465
466   pp::FileRef body(response_info.GetBodyAsFileRef());
467   if (body.is_null())
468     return "URLResponseInfo::GetBody returned null";
469
470   callback.WaitForResult(loader.FinishStreamingToFile(callback.GetCallback()));
471   CHECK_CALLBACK_BEHAVIOR(callback);
472   ASSERT_EQ(PP_OK, callback.result());
473
474   pp::FileIO reader(instance_);
475   callback.WaitForResult(reader.Open(body, PP_FILEOPENFLAG_READ,
476                                      callback.GetCallback()));
477   CHECK_CALLBACK_BEHAVIOR(callback);
478   ASSERT_EQ(PP_OK, callback.result());
479
480   std::string data;
481   std::string error = ReadEntireFile(&reader, &data);
482   if (!error.empty())
483     return error;
484
485   std::string expected_body = "hello\n";
486   if (data.size() != expected_body.size())
487     return "ReadEntireFile returned unexpected content length";
488   if (data != expected_body)
489     return "ReadEntireFile returned unexpected content";
490
491   PASS();
492 }
493
494 // Untrusted, unintended cross-origin requests should fail.
495 std::string TestURLLoader::TestUntrustedSameOriginRestriction() {
496   pp::URLRequestInfo request(instance_);
497   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
498   request.SetURL(cross_origin_url);
499
500   int32_t rv = OpenUntrusted(request);
501   if (rv != PP_ERROR_NOACCESS)
502     return ReportError(
503         "Untrusted, unintended cross-origin request restriction", rv);
504
505   PASS();
506 }
507
508 // Trusted, unintended cross-origin requests should succeed.
509 std::string TestURLLoader::TestTrustedSameOriginRestriction() {
510   pp::URLRequestInfo request(instance_);
511   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
512   request.SetURL(cross_origin_url);
513
514   int32_t rv = OpenTrusted(request);
515   if (rv != PP_OK)
516     return ReportError("Trusted cross-origin request failed", rv);
517
518   PASS();
519 }
520
521 // Untrusted, intended cross-origin requests should use CORS and succeed.
522 std::string TestURLLoader::TestUntrustedCrossOriginRequest() {
523   pp::URLRequestInfo request(instance_);
524   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
525   request.SetURL(cross_origin_url);
526   request.SetAllowCrossOriginRequests(true);
527
528   int32_t rv = OpenUntrusted(request);
529   if (rv != PP_OK)
530     return ReportError(
531         "Untrusted, intended cross-origin request failed", rv);
532
533   PASS();
534 }
535
536 // Trusted, intended cross-origin requests should use CORS and succeed.
537 std::string TestURLLoader::TestTrustedCrossOriginRequest() {
538   pp::URLRequestInfo request(instance_);
539   std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
540   request.SetURL(cross_origin_url);
541   request.SetAllowCrossOriginRequests(true);
542
543   int32_t rv = OpenTrusted(request);
544   if (rv != PP_OK)
545     return ReportError("Trusted cross-origin request failed", rv);
546
547   PASS();
548 }
549
550 // Untrusted Javascript URLs requests should fail.
551 std::string TestURLLoader::TestUntrustedJavascriptURLRestriction() {
552   pp::URLRequestInfo request(instance_);
553   request.SetURL("javascript:foo = bar");
554
555   int32_t rv = OpenUntrusted(request);
556   if (rv != PP_ERROR_NOACCESS)
557     return ReportError(
558         "Untrusted Javascript URL request restriction failed", rv);
559
560   PASS();
561 }
562
563 // Trusted Javascript URLs requests should succeed.
564 std::string TestURLLoader::TestTrustedJavascriptURLRestriction() {
565   pp::URLRequestInfo request(instance_);
566   request.SetURL("javascript:foo = bar");
567
568   int32_t rv = OpenTrusted(request);
569   if (rv == PP_ERROR_NOACCESS)
570   return ReportError(
571       "Trusted Javascript URL request", rv);
572
573   PASS();
574 }
575
576 std::string TestURLLoader::TestUntrustedHttpRequests() {
577   // HTTP methods are restricted only for untrusted loaders. Forbidden
578   // methods are CONNECT, TRACE, and TRACK, and any string that is not a
579   // valid token (containing special characters like CR, LF).
580   // http://www.w3.org/TR/XMLHttpRequest/
581   {
582     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("cOnNeCt", std::string()));
583     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("tRaCk", std::string()));
584     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("tRaCe", std::string()));
585     ASSERT_EQ(PP_ERROR_NOACCESS,
586         OpenUntrusted("POST\x0d\x0ax-csrf-token:\x20test1234", std::string()));
587   }
588   // HTTP methods are restricted only for untrusted loaders. Try all headers
589   // that are forbidden by http://www.w3.org/TR/XMLHttpRequest/.
590   {
591     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Accept-Charset:\n"));
592     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Accept-Encoding:\n"));
593     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Connection:\n"));
594     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Content-Length:\n"));
595     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Cookie:\n"));
596     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Cookie2:\n"));
597     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Date:\n"));
598     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Dnt:\n"));
599     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Expect:\n"));
600     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Host:\n"));
601     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Keep-Alive:\n"));
602     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Referer:\n"));
603     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "TE:\n"));
604     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Trailer:\n"));
605     ASSERT_EQ(PP_ERROR_NOACCESS,
606               OpenUntrusted("GET", "Transfer-Encoding:\n"));
607     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Upgrade:\n"));
608     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "User-Agent:\n"));
609     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Via:\n"));
610     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted(
611         "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
612     ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Sec-foo:\n"));
613   }
614   // Untrusted requests with custom referrer should fail.
615   {
616     pp::URLRequestInfo request(instance_);
617     request.SetCustomReferrerURL("http://www.google.com/");
618
619     int32_t rv = OpenUntrusted(request);
620     if (rv != PP_ERROR_NOACCESS)
621       return ReportError(
622           "Untrusted request with custom referrer restriction", rv);
623   }
624   // Untrusted requests with custom transfer encodings should fail.
625   {
626     pp::URLRequestInfo request(instance_);
627     request.SetCustomContentTransferEncoding("foo");
628
629     int32_t rv = OpenUntrusted(request);
630     if (rv != PP_ERROR_NOACCESS)
631       return ReportError(
632           "Untrusted request with content-transfer-encoding restriction", rv);
633   }
634
635   PASS();
636 }
637
638 std::string TestURLLoader::TestTrustedHttpRequests() {
639   // Trusted requests can use restricted methods.
640   {
641     ASSERT_EQ(PP_OK, OpenTrusted("cOnNeCt", std::string()));
642     ASSERT_EQ(PP_OK, OpenTrusted("tRaCk", std::string()));
643     ASSERT_EQ(PP_OK, OpenTrusted("tRaCe", std::string()));
644   }
645   // Trusted requests can use restricted headers.
646   {
647     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Accept-Charset:\n"));
648     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Accept-Encoding:\n"));
649     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Connection:\n"));
650     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Content-Length:\n"));
651     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Cookie:\n"));
652     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Cookie2:\n"));
653     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Content-Transfer-Encoding:\n"));
654     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Date:\n"));
655     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Expect:\n"));
656     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Host:\n"));
657     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Keep-Alive:\n"));
658     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Referer:\n"));
659     ASSERT_EQ(PP_OK, OpenTrusted("GET", "TE:\n"));
660     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Trailer:\n"));
661     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Transfer-Encoding:\n"));
662     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Upgrade:\n"));
663     ASSERT_EQ(PP_OK, OpenTrusted("GET", "User-Agent:\n"));
664     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Via:\n"));
665     ASSERT_EQ(PP_OK,
666               OpenTrusted("GET",
667                   "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
668     ASSERT_EQ(PP_OK, OpenTrusted("GET", "Sec-foo:\n"));
669   }
670   // Trusted requests with custom referrer should succeed.
671   {
672     pp::URLRequestInfo request(instance_);
673     request.SetCustomReferrerURL("http://www.google.com/");
674
675     int32_t rv = OpenTrusted(request);
676     if (rv != PP_OK)
677       return ReportError("Trusted request with custom referrer", rv);
678   }
679   // Trusted requests with custom transfer encodings should succeed.
680   {
681     pp::URLRequestInfo request(instance_);
682     request.SetCustomContentTransferEncoding("foo");
683
684     int32_t rv = OpenTrusted(request);
685     if (rv != PP_OK)
686       return ReportError(
687           "Trusted request with content-transfer-encoding failed", rv);
688   }
689
690   PASS();
691 }
692
693 // This test should cause a redirect and ensure that the loader follows it.
694 std::string TestURLLoader::TestFollowURLRedirect() {
695   pp::URLRequestInfo request(instance_);
696   // This prefix causes the test server to return a 301 redirect.
697   std::string redirect_prefix("/server-redirect?");
698   // We need an absolute path for the redirect to actually work.
699   std::string redirect_url =
700       GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
701   request.SetURL(redirect_prefix.append(redirect_url));
702   return LoadAndCompareBody(request, "hello\n");
703 }
704
705 // This test should cause a redirect and ensure that the loader runs
706 // the callback, rather than following the redirect.
707 std::string TestURLLoader::TestAuditURLRedirect() {
708   pp::URLRequestInfo request(instance_);
709   // This path will cause the server to return a 301 redirect.
710   // This prefix causes the test server to return a 301 redirect.
711   std::string redirect_prefix("/server-redirect?");
712   // We need an absolute path for the redirect to actually work.
713   std::string redirect_url =
714       GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
715   request.SetURL(redirect_prefix.append(redirect_url));
716   request.SetFollowRedirects(false);
717
718   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
719
720   pp::URLLoader loader(instance_);
721   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
722   CHECK_CALLBACK_BEHAVIOR(callback);
723   ASSERT_EQ(PP_OK, callback.result());
724
725   // Checks that the response indicates a redirect, and that the URL
726   // is correct.
727   pp::URLResponseInfo response_info(loader.GetResponseInfo());
728   if (response_info.is_null())
729     return "URLLoader::GetResponseInfo returned null";
730   int32_t status_code = response_info.GetStatusCode();
731   if (status_code != 301)
732     return "Response status should be 301";
733
734   // Test that the paused loader can be resumed.
735   callback.WaitForResult(loader.FollowRedirect(callback.GetCallback()));
736   CHECK_CALLBACK_BEHAVIOR(callback);
737   ASSERT_EQ(PP_OK, callback.result());
738   std::string body;
739   std::string error = ReadEntireResponseBody(&loader, &body);
740   if (!error.empty())
741     return error;
742
743   if (body != "hello\n")
744     return "URLLoader::FollowRedirect failed";
745
746   PASS();
747 }
748
749 std::string TestURLLoader::TestAbortCalls() {
750   pp::URLRequestInfo request(instance_);
751   request.SetURL("test_url_loader_data/hello.txt");
752
753   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
754   int32_t rv;
755
756   // Abort |Open()|.
757   {
758     rv = pp::URLLoader(instance_).Open(request, callback.GetCallback());
759   }
760   callback.WaitForAbortResult(rv);
761   CHECK_CALLBACK_BEHAVIOR(callback);
762
763   // Abort |ReadResponseBody()|.
764   {
765     char buf[2] = { 0 };
766     {
767       pp::URLLoader loader(instance_);
768       callback.WaitForResult(loader.Open(request, callback.GetCallback()));
769       CHECK_CALLBACK_BEHAVIOR(callback);
770       ASSERT_EQ(PP_OK, callback.result());
771
772       rv = loader.ReadResponseBody(buf, sizeof(buf), callback.GetCallback());
773     }  // Destroy |loader|.
774     callback.WaitForAbortResult(rv);
775     CHECK_CALLBACK_BEHAVIOR(callback);
776     if (rv == PP_OK_COMPLETIONPENDING) {
777       if (buf[0] || buf[1]) {
778         return "URLLoader::ReadResponseBody wrote data after resource "
779                "destruction.";
780       }
781     }
782   }
783
784   // TODO(viettrungluu): More abort tests (but add basic tests first).
785   // Also test that Close() aborts properly. crbug.com/69457
786
787   PASS();
788 }
789
790 std::string TestURLLoader::TestUntendedLoad() {
791   pp::URLRequestInfo request(instance_);
792   request.SetURL("test_url_loader_data/hello.txt");
793   request.SetRecordDownloadProgress(true);
794   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
795
796   pp::URLLoader loader(instance_);
797   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
798   CHECK_CALLBACK_BEHAVIOR(callback);
799   ASSERT_EQ(PP_OK, callback.result());
800
801   // We received the response callback. Yield until the network code has called
802   // the loader's didReceiveData and didFinishLoading methods before we give it
803   // another callback function, to make sure the loader works with no callback.
804   int64_t bytes_received = 0;
805   int64_t total_bytes_to_be_received = 0;
806   while (true) {
807     loader.GetDownloadProgress(&bytes_received, &total_bytes_to_be_received);
808     if (total_bytes_to_be_received <= 0)
809       return ReportError("URLLoader::GetDownloadProgress total size",
810           total_bytes_to_be_received);
811     if (bytes_received == total_bytes_to_be_received)
812       break;
813     // Yield if we're on the main thread, so that URLLoader can receive more
814     // data.
815     if (pp::Module::Get()->core()->IsMainThread()) {
816       NestedEvent event(instance_->pp_instance());
817       event.PostSignal(10);
818       event.Wait();
819     }
820   }
821   // The loader should now have the data and have finished successfully.
822   std::string body;
823   std::string error = ReadEntireResponseBody(&loader, &body);
824   if (!error.empty())
825     return error;
826   if (body != "hello\n")
827     return ReportError("Couldn't read data", callback.result());
828
829   PASS();
830 }
831
832 int32_t TestURLLoader::OpenWithPrefetchBufferThreshold(int32_t lower,
833                                                        int32_t upper) {
834   pp::URLRequestInfo request(instance_);
835   request.SetURL("test_url_loader_data/hello.txt");
836   request.SetPrefetchBufferLowerThreshold(lower);
837   request.SetPrefetchBufferUpperThreshold(upper);
838
839   return OpenUntrusted(request);
840 }
841
842 std::string TestURLLoader::TestPrefetchBufferThreshold() {
843   int32_t rv = OpenWithPrefetchBufferThreshold(-1, 1);
844   if (rv != PP_ERROR_FAILED) {
845     return ReportError("The prefetch limits contained a negative value but "
846                        "the URLLoader did not fail.", rv);
847   }
848
849   rv = OpenWithPrefetchBufferThreshold(0, 1);
850   if (rv != PP_OK) {
851     return ReportError("The prefetch buffer limits were legal values but "
852                        "the URLLoader failed.", rv);
853   }
854
855   rv = OpenWithPrefetchBufferThreshold(1000, 1);
856   if (rv != PP_ERROR_FAILED) {
857     return ReportError("The lower buffer value was higher than the upper but "
858                        "the URLLoader did not fail.", rv);
859   }
860
861   PASS();
862 }
863
864 // TODO(viettrungluu): This test properly belongs elsewhere. It tests that
865 // Chrome properly tags URL requests made on behalf of Pepper plugins (with an
866 // X-Requested-With header), but this isn't, strictly speaking, a PPAPI
867 // behavior.
868 std::string TestURLLoader::TestXRequestedWithHeader() {
869   pp::URLRequestInfo request(instance_);
870   request.SetURL("/echoheader?X-Requested-With");
871   // The name and version of the plugin is set from the command-line (see
872   // chrome/test/ppapi/ppapi_test.cc.
873   return LoadAndCompareBody(request, "PPAPITests/1.2.3");
874 }
875
876 // TODO(viettrungluu): Add tests for  Get{Upload,Download}Progress, Close
877 // (including abort tests if applicable).