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