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   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).
    878