Home | History | Annotate | Download | only in tests
      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(OpenUntrusted("cOnNeCt", std::string()), PP_ERROR_NOACCESS);
    582     ASSERT_EQ(OpenUntrusted("tRaCk", std::string()), PP_ERROR_NOACCESS);
    583     ASSERT_EQ(OpenUntrusted("tRaCe", std::string()), PP_ERROR_NOACCESS);
    584     ASSERT_EQ(
    585         OpenUntrusted("POST\x0d\x0ax-csrf-token:\x20test1234", std::string()),
    586         PP_ERROR_NOACCESS);
    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(OpenUntrusted("GET", "Accept-Charset:\n"), PP_ERROR_NOACCESS);
    592     ASSERT_EQ(OpenUntrusted("GET", "Accept-Encoding:\n"), PP_ERROR_NOACCESS);
    593     ASSERT_EQ(OpenUntrusted("GET", "Connection:\n"), PP_ERROR_NOACCESS);
    594     ASSERT_EQ(OpenUntrusted("GET", "Content-Length:\n"), PP_ERROR_NOACCESS);
    595     ASSERT_EQ(OpenUntrusted("GET", "Cookie:\n"), PP_ERROR_NOACCESS);
    596     ASSERT_EQ(OpenUntrusted("GET", "Cookie2:\n"), PP_ERROR_NOACCESS);
    597     ASSERT_EQ(OpenUntrusted(
    598         "GET", "Content-Transfer-Encoding:\n"), PP_ERROR_NOACCESS);
    599     ASSERT_EQ(OpenUntrusted("GET", "Date:\n"), PP_ERROR_NOACCESS);
    600     ASSERT_EQ(OpenUntrusted("GET", "Expect:\n"), PP_ERROR_NOACCESS);
    601     ASSERT_EQ(OpenUntrusted("GET", "Host:\n"), PP_ERROR_NOACCESS);
    602     ASSERT_EQ(OpenUntrusted("GET", "Keep-Alive:\n"), PP_ERROR_NOACCESS);
    603     ASSERT_EQ(OpenUntrusted("GET", "Referer:\n"), PP_ERROR_NOACCESS);
    604     ASSERT_EQ(OpenUntrusted("GET", "TE:\n"), PP_ERROR_NOACCESS);
    605     ASSERT_EQ(OpenUntrusted("GET", "Trailer:\n"), PP_ERROR_NOACCESS);
    606     ASSERT_EQ(OpenUntrusted(
    607         "GET", "Transfer-Encoding:\n"), PP_ERROR_NOACCESS);
    608     ASSERT_EQ(OpenUntrusted("GET", "Upgrade:\n"), PP_ERROR_NOACCESS);
    609     ASSERT_EQ(OpenUntrusted("GET", "User-Agent:\n"), PP_ERROR_NOACCESS);
    610     ASSERT_EQ(OpenUntrusted("GET", "Via:\n"), PP_ERROR_NOACCESS);
    611     ASSERT_EQ(OpenUntrusted(
    612         "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"),
    613             PP_ERROR_NOACCESS);
    614     ASSERT_EQ(OpenUntrusted("GET", "Sec-foo:\n"), PP_ERROR_NOACCESS);
    615   }
    616   // Untrusted requests with custom referrer should fail.
    617   {
    618     pp::URLRequestInfo request(instance_);
    619     request.SetCustomReferrerURL("http://www.google.com/");
    620 
    621     int32_t rv = OpenUntrusted(request);
    622     if (rv != PP_ERROR_NOACCESS)
    623       return ReportError(
    624           "Untrusted request with custom referrer restriction", rv);
    625   }
    626   // Untrusted requests with custom transfer encodings should fail.
    627   {
    628     pp::URLRequestInfo request(instance_);
    629     request.SetCustomContentTransferEncoding("foo");
    630 
    631     int32_t rv = OpenUntrusted(request);
    632     if (rv != PP_ERROR_NOACCESS)
    633       return ReportError(
    634           "Untrusted request with content-transfer-encoding restriction", rv);
    635   }
    636 
    637   PASS();
    638 }
    639 
    640 std::string TestURLLoader::TestTrustedHttpRequests() {
    641   // Trusted requests can use restricted methods.
    642   {
    643     ASSERT_EQ(OpenTrusted("cOnNeCt", std::string()), PP_OK);
    644     ASSERT_EQ(OpenTrusted("tRaCk", std::string()), PP_OK);
    645     ASSERT_EQ(OpenTrusted("tRaCe", std::string()), PP_OK);
    646   }
    647   // Trusted requests can use restricted headers.
    648   {
    649     ASSERT_EQ(OpenTrusted("GET", "Accept-Charset:\n"), PP_OK);
    650     ASSERT_EQ(OpenTrusted("GET", "Accept-Encoding:\n"), PP_OK);
    651     ASSERT_EQ(OpenTrusted("GET", "Connection:\n"), PP_OK);
    652     ASSERT_EQ(OpenTrusted("GET", "Content-Length:\n"), PP_OK);
    653     ASSERT_EQ(OpenTrusted("GET", "Cookie:\n"), PP_OK);
    654     ASSERT_EQ(OpenTrusted("GET", "Cookie2:\n"), PP_OK);
    655     ASSERT_EQ(OpenTrusted(
    656         "GET", "Content-Transfer-Encoding:\n"), PP_OK);
    657     ASSERT_EQ(OpenTrusted("GET", "Date:\n"), PP_OK);
    658     ASSERT_EQ(OpenTrusted("GET", "Expect:\n"), PP_OK);
    659     ASSERT_EQ(OpenTrusted("GET", "Host:\n"), PP_OK);
    660     ASSERT_EQ(OpenTrusted("GET", "Keep-Alive:\n"), PP_OK);
    661     ASSERT_EQ(OpenTrusted("GET", "Referer:\n"), PP_OK);
    662     ASSERT_EQ(OpenTrusted("GET", "TE:\n"), PP_OK);
    663     ASSERT_EQ(OpenTrusted("GET", "Trailer:\n"), PP_OK);
    664     ASSERT_EQ(OpenTrusted("GET", "Transfer-Encoding:\n"), PP_OK);
    665     ASSERT_EQ(OpenTrusted("GET", "Upgrade:\n"), PP_OK);
    666     ASSERT_EQ(OpenTrusted("GET", "User-Agent:\n"), PP_OK);
    667     ASSERT_EQ(OpenTrusted("GET", "Via:\n"), PP_OK);
    668     ASSERT_EQ(OpenTrusted(
    669         "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"), PP_OK);
    670     ASSERT_EQ(OpenTrusted("GET", "Sec-foo:\n"), PP_OK);
    671   }
    672   // Trusted requests with custom referrer should succeed.
    673   {
    674     pp::URLRequestInfo request(instance_);
    675     request.SetCustomReferrerURL("http://www.google.com/");
    676 
    677     int32_t rv = OpenTrusted(request);
    678     if (rv != PP_OK)
    679       return ReportError("Trusted request with custom referrer", rv);
    680   }
    681   // Trusted requests with custom transfer encodings should succeed.
    682   {
    683     pp::URLRequestInfo request(instance_);
    684     request.SetCustomContentTransferEncoding("foo");
    685 
    686     int32_t rv = OpenTrusted(request);
    687     if (rv != PP_OK)
    688       return ReportError(
    689           "Trusted request with content-transfer-encoding failed", rv);
    690   }
    691 
    692   PASS();
    693 }
    694 
    695 // This test should cause a redirect and ensure that the loader follows it.
    696 std::string TestURLLoader::TestFollowURLRedirect() {
    697   pp::URLRequestInfo request(instance_);
    698   // This prefix causes the test server to return a 301 redirect.
    699   std::string redirect_prefix("/server-redirect?");
    700   // We need an absolute path for the redirect to actually work.
    701   std::string redirect_url =
    702       GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
    703   request.SetURL(redirect_prefix.append(redirect_url));
    704   return LoadAndCompareBody(request, "hello\n");
    705 }
    706 
    707 // This test should cause a redirect and ensure that the loader runs
    708 // the callback, rather than following the redirect.
    709 std::string TestURLLoader::TestAuditURLRedirect() {
    710   pp::URLRequestInfo request(instance_);
    711   // This path will cause the server to return a 301 redirect.
    712   // This prefix causes the test server to return a 301 redirect.
    713   std::string redirect_prefix("/server-redirect?");
    714   // We need an absolute path for the redirect to actually work.
    715   std::string redirect_url =
    716       GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
    717   request.SetURL(redirect_prefix.append(redirect_url));
    718   request.SetFollowRedirects(false);
    719 
    720   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    721 
    722   pp::URLLoader loader(instance_);
    723   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
    724   CHECK_CALLBACK_BEHAVIOR(callback);
    725   ASSERT_EQ(PP_OK, callback.result());
    726 
    727   // Checks that the response indicates a redirect, and that the URL
    728   // is correct.
    729   pp::URLResponseInfo response_info(loader.GetResponseInfo());
    730   if (response_info.is_null())
    731     return "URLLoader::GetResponseInfo returned null";
    732   int32_t status_code = response_info.GetStatusCode();
    733   if (status_code != 301)
    734     return "Response status should be 301";
    735 
    736   // Test that the paused loader can be resumed.
    737   callback.WaitForResult(loader.FollowRedirect(callback.GetCallback()));
    738   CHECK_CALLBACK_BEHAVIOR(callback);
    739   ASSERT_EQ(PP_OK, callback.result());
    740   std::string body;
    741   std::string error = ReadEntireResponseBody(&loader, &body);
    742   if (!error.empty())
    743     return error;
    744 
    745   if (body != "hello\n")
    746     return "URLLoader::FollowRedirect failed";
    747 
    748   PASS();
    749 }
    750 
    751 std::string TestURLLoader::TestAbortCalls() {
    752   pp::URLRequestInfo request(instance_);
    753   request.SetURL("test_url_loader_data/hello.txt");
    754 
    755   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    756   int32_t rv;
    757 
    758   // Abort |Open()|.
    759   {
    760     rv = pp::URLLoader(instance_).Open(request, callback.GetCallback());
    761   }
    762   callback.WaitForAbortResult(rv);
    763   CHECK_CALLBACK_BEHAVIOR(callback);
    764 
    765   // Abort |ReadResponseBody()|.
    766   {
    767     char buf[2] = { 0 };
    768     {
    769       pp::URLLoader loader(instance_);
    770       callback.WaitForResult(loader.Open(request, callback.GetCallback()));
    771       CHECK_CALLBACK_BEHAVIOR(callback);
    772       ASSERT_EQ(PP_OK, callback.result());
    773 
    774       rv = loader.ReadResponseBody(buf, sizeof(buf), callback.GetCallback());
    775     }  // Destroy |loader|.
    776     callback.WaitForAbortResult(rv);
    777     CHECK_CALLBACK_BEHAVIOR(callback);
    778     if (rv == PP_OK_COMPLETIONPENDING) {
    779       if (buf[0] || buf[1]) {
    780         return "URLLoader::ReadResponseBody wrote data after resource "
    781                "destruction.";
    782       }
    783     }
    784   }
    785 
    786   // TODO(viettrungluu): More abort tests (but add basic tests first).
    787   // Also test that Close() aborts properly. crbug.com/69457
    788 
    789   PASS();
    790 }
    791 
    792 std::string TestURLLoader::TestUntendedLoad() {
    793   pp::URLRequestInfo request(instance_);
    794   request.SetURL("test_url_loader_data/hello.txt");
    795   request.SetRecordDownloadProgress(true);
    796   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    797 
    798   pp::URLLoader loader(instance_);
    799   callback.WaitForResult(loader.Open(request, callback.GetCallback()));
    800   CHECK_CALLBACK_BEHAVIOR(callback);
    801   ASSERT_EQ(PP_OK, callback.result());
    802 
    803   // We received the response callback. Yield until the network code has called
    804   // the loader's didReceiveData and didFinishLoading methods before we give it
    805   // another callback function, to make sure the loader works with no callback.
    806   int64_t bytes_received = 0;
    807   int64_t total_bytes_to_be_received = 0;
    808   while (true) {
    809     loader.GetDownloadProgress(&bytes_received, &total_bytes_to_be_received);
    810     if (total_bytes_to_be_received <= 0)
    811       return ReportError("URLLoader::GetDownloadProgress total size",
    812           total_bytes_to_be_received);
    813     if (bytes_received == total_bytes_to_be_received)
    814       break;
    815     // Yield if we're on the main thread, so that URLLoader can receive more
    816     // data.
    817     if (pp::Module::Get()->core()->IsMainThread()) {
    818       NestedEvent event(instance_->pp_instance());
    819       event.PostSignal(10);
    820       event.Wait();
    821     }
    822   }
    823   // The loader should now have the data and have finished successfully.
    824   std::string body;
    825   std::string error = ReadEntireResponseBody(&loader, &body);
    826   if (!error.empty())
    827     return error;
    828   if (body != "hello\n")
    829     return ReportError("Couldn't read data", callback.result());
    830 
    831   PASS();
    832 }
    833 
    834 int32_t TestURLLoader::OpenWithPrefetchBufferThreshold(int32_t lower,
    835                                                        int32_t upper) {
    836   pp::URLRequestInfo request(instance_);
    837   request.SetURL("test_url_loader_data/hello.txt");
    838   request.SetPrefetchBufferLowerThreshold(lower);
    839   request.SetPrefetchBufferUpperThreshold(upper);
    840 
    841   return OpenUntrusted(request);
    842 }
    843 
    844 std::string TestURLLoader::TestPrefetchBufferThreshold() {
    845   int32_t rv = OpenWithPrefetchBufferThreshold(-1, 1);
    846   if (rv != PP_ERROR_FAILED) {
    847     return ReportError("The prefetch limits contained a negative value but "
    848                        "the URLLoader did not fail.", rv);
    849   }
    850 
    851   rv = OpenWithPrefetchBufferThreshold(0, 1);
    852   if (rv != PP_OK) {
    853     return ReportError("The prefetch buffer limits were legal values but "
    854                        "the URLLoader failed.", rv);
    855   }
    856 
    857   rv = OpenWithPrefetchBufferThreshold(1000, 1);
    858   if (rv != PP_ERROR_FAILED) {
    859     return ReportError("The lower buffer value was higher than the upper but "
    860                        "the URLLoader did not fail.", rv);
    861   }
    862 
    863   PASS();
    864 }
    865 
    866 // TODO(viettrungluu): Add tests for  Get{Upload,Download}Progress, Close
    867 // (including abort tests if applicable).
    868