Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ppapi / tests / test_url_loader.cc
blobd3a210e3bc177c4809631ba8745b6a2cb886d9f8
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.
5 #include "ppapi/tests/test_url_loader.h"
7 #include <stdio.h>
8 #include <string.h>
9 #include <string>
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"
28 REGISTER_TEST_CASE(URLLoader);
30 namespace {
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 = static_cast<int32_t>(data.size());
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();
54 return PP_OK;
57 } // namespace
59 TestURLLoader::TestURLLoader(TestingInstance* instance)
60 : TestCase(instance),
61 file_io_private_interface_(NULL),
62 url_loader_trusted_interface_(NULL) {
65 bool TestURLLoader::Init() {
66 if (!CheckTestingInterface()) {
67 instance_->AppendError("Testing interface not available");
68 return false;
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");
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
92 return EnsureRunningOverHTTP();
96 * The test order is important here, as running tests out of order may cause
97 * test timeout.
99 * Here is the environment:
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.
109 * Here is the problem:
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).
116 * Because of this the test run was taking around 45 seconds, and test was
117 * reported as 'timed out' by trybot.
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.
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);
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;
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());
171 PASS();
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.
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());
189 PASS();
192 std::string TestURLLoader::LoadAndCompareBody(
193 const pp::URLRequestInfo& request,
194 const std::string& expected_body) {
195 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
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());
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";
209 std::string body;
210 std::string error = ReadEntireResponseBody(&loader, &body);
211 if (!error.empty())
212 return error;
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";
219 PASS();
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();
230 if (callback.result() != PP_OK) {
231 message->assign("FileSystem::Open");
232 return callback.result();
234 return callback.result();
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();
252 if (callback.result() != PP_OK) {
253 message->assign("FileIO::Open failed.");
254 return callback.result();
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;
264 return rv;
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;
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;
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);
304 return OpenUntrusted(request);
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);
314 return OpenTrusted(request);
317 int32_t TestURLLoader::OpenUntrusted(const pp::URLRequestInfo& request) {
318 return Open(request, false);
321 int32_t TestURLLoader::OpenTrusted(const pp::URLRequestInfo& request) {
322 return Open(request, true);
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();
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");
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(),
347 static_cast<uint32_t>(postdata.length()));
348 return LoadAndCompareBody(request, postdata);
351 std::string TestURLLoader::TestBasicFilePOST() {
352 std::string message;
354 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
355 int32_t rv = OpenFileSystem(&file_system, &message);
356 if (rv != PP_OK)
357 return ReportError(message.c_str(), rv);
359 pp::FileRef file_ref(file_system, "/file_post_test");
360 std::string postdata("postdata");
361 rv = PrepareFileForPost(file_ref, postdata, &message);
362 if (rv != PP_OK)
363 return ReportError(message.c_str(), rv);
365 pp::URLRequestInfo request(instance_);
366 request.SetURL("/echo");
367 request.SetMethod("POST");
368 request.AppendFileToBody(file_ref, 0);
369 return LoadAndCompareBody(request, postdata);
372 std::string TestURLLoader::TestBasicFileRangePOST() {
373 std::string message;
375 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
376 int32_t rv = OpenFileSystem(&file_system, &message);
377 if (rv != PP_OK)
378 return ReportError(message.c_str(), rv);
380 pp::FileRef file_ref(file_system, "/file_range_post_test");
381 std::string postdata("postdatapostdata");
382 rv = PrepareFileForPost(file_ref, postdata, &message);
383 if (rv != PP_OK)
384 return ReportError(message.c_str(), rv);
386 pp::URLRequestInfo request(instance_);
387 request.SetURL("/echo");
388 request.SetMethod("POST");
389 request.AppendFileRangeToBody(file_ref, 4, 12, 0);
390 return LoadAndCompareBody(request, postdata.substr(4, 12));
393 std::string TestURLLoader::TestCompoundBodyPOST() {
394 pp::URLRequestInfo request(instance_);
395 request.SetURL("/echo");
396 request.SetMethod("POST");
397 std::string postdata1("post");
398 request.AppendDataToBody(postdata1.data(),
399 static_cast<uint32_t>(postdata1.length()));
400 std::string postdata2("data");
401 request.AppendDataToBody(postdata2.data(),
402 static_cast<uint32_t>(postdata2.length()));
403 return LoadAndCompareBody(request, postdata1 + postdata2);
406 std::string TestURLLoader::TestEmptyDataPOST() {
407 pp::URLRequestInfo request(instance_);
408 request.SetURL("/echo");
409 request.SetMethod("POST");
410 request.AppendDataToBody("", 0);
411 return LoadAndCompareBody(request, std::string());
414 std::string TestURLLoader::TestBinaryDataPOST() {
415 pp::URLRequestInfo request(instance_);
416 request.SetURL("/echo");
417 request.SetMethod("POST");
418 const char postdata_chars[] =
419 "\x00\x01\x02\x03\x04\x05postdata\xfa\xfb\xfc\xfd\xfe\xff";
420 std::string postdata(postdata_chars,
421 sizeof(postdata_chars) / sizeof(postdata_chars[0]));
422 request.AppendDataToBody(postdata.data(),
423 static_cast<uint32_t>(postdata.length()));
424 return LoadAndCompareBody(request, postdata);
427 std::string TestURLLoader::TestCustomRequestHeader() {
428 pp::URLRequestInfo request(instance_);
429 request.SetURL("/echoheader?Foo");
430 request.SetHeaders("Foo: 1");
431 return LoadAndCompareBody(request, "1");
434 std::string TestURLLoader::TestFailsBogusContentLength() {
435 pp::URLRequestInfo request(instance_);
436 request.SetURL("/echo");
437 request.SetMethod("POST");
438 request.SetHeaders("Content-Length: 400");
439 std::string postdata("postdata");
440 request.AppendDataToBody(postdata.data(),
441 static_cast<uint32_t>(postdata.length()));
443 int32_t rv;
444 rv = OpenUntrusted(request);
445 if (rv != PP_ERROR_NOACCESS)
446 return ReportError(
447 "Untrusted request with bogus Content-Length restriction", rv);
449 PASS();
452 std::string TestURLLoader::TestStreamToFile() {
453 pp::URLRequestInfo request(instance_);
454 request.SetURL("test_url_loader_data/hello.txt");
455 request.SetStreamToFile(true);
457 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
459 pp::URLLoader loader(instance_);
460 callback.WaitForResult(loader.Open(request, callback.GetCallback()));
461 CHECK_CALLBACK_BEHAVIOR(callback);
462 ASSERT_EQ(PP_OK, callback.result());
464 pp::URLResponseInfo response_info(loader.GetResponseInfo());
465 if (response_info.is_null())
466 return "URLLoader::GetResponseInfo returned null";
467 int32_t status_code = response_info.GetStatusCode();
468 if (status_code != 200)
469 return "Unexpected HTTP status code";
471 pp::FileRef body(response_info.GetBodyAsFileRef());
472 if (body.is_null())
473 return "URLResponseInfo::GetBody returned null";
475 callback.WaitForResult(loader.FinishStreamingToFile(callback.GetCallback()));
476 CHECK_CALLBACK_BEHAVIOR(callback);
477 ASSERT_EQ(PP_OK, callback.result());
479 pp::FileIO reader(instance_);
480 callback.WaitForResult(reader.Open(body, PP_FILEOPENFLAG_READ,
481 callback.GetCallback()));
482 CHECK_CALLBACK_BEHAVIOR(callback);
483 ASSERT_EQ(PP_OK, callback.result());
485 std::string data;
486 std::string error = ReadEntireFile(&reader, &data);
487 if (!error.empty())
488 return error;
490 std::string expected_body = "hello\n";
491 if (data.size() != expected_body.size())
492 return "ReadEntireFile returned unexpected content length";
493 if (data != expected_body)
494 return "ReadEntireFile returned unexpected content";
496 PASS();
499 // Untrusted, unintended cross-origin requests should fail.
500 std::string TestURLLoader::TestUntrustedSameOriginRestriction() {
501 pp::URLRequestInfo request(instance_);
502 std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
503 request.SetURL(cross_origin_url);
505 int32_t rv = OpenUntrusted(request);
506 if (rv != PP_ERROR_NOACCESS)
507 return ReportError(
508 "Untrusted, unintended cross-origin request restriction", rv);
510 PASS();
513 // Trusted, unintended cross-origin requests should succeed.
514 std::string TestURLLoader::TestTrustedSameOriginRestriction() {
515 pp::URLRequestInfo request(instance_);
516 std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
517 request.SetURL(cross_origin_url);
519 int32_t rv = OpenTrusted(request);
520 if (rv != PP_OK)
521 return ReportError("Trusted cross-origin request failed", rv);
523 PASS();
526 // Untrusted, intended cross-origin requests should use CORS and succeed.
527 std::string TestURLLoader::TestUntrustedCrossOriginRequest() {
528 pp::URLRequestInfo request(instance_);
529 std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
530 request.SetURL(cross_origin_url);
531 request.SetAllowCrossOriginRequests(true);
533 int32_t rv = OpenUntrusted(request);
534 if (rv != PP_OK)
535 return ReportError(
536 "Untrusted, intended cross-origin request failed", rv);
538 PASS();
541 // Trusted, intended cross-origin requests should use CORS and succeed.
542 std::string TestURLLoader::TestTrustedCrossOriginRequest() {
543 pp::URLRequestInfo request(instance_);
544 std::string cross_origin_url = GetReachableCrossOriginURL("test_case.html");
545 request.SetURL(cross_origin_url);
546 request.SetAllowCrossOriginRequests(true);
548 int32_t rv = OpenTrusted(request);
549 if (rv != PP_OK)
550 return ReportError("Trusted cross-origin request failed", rv);
552 PASS();
555 // Untrusted Javascript URLs requests should fail.
556 std::string TestURLLoader::TestUntrustedJavascriptURLRestriction() {
557 pp::URLRequestInfo request(instance_);
558 request.SetURL("javascript:foo = bar");
560 int32_t rv = OpenUntrusted(request);
561 if (rv != PP_ERROR_NOACCESS)
562 return ReportError(
563 "Untrusted Javascript URL request restriction failed", rv);
565 PASS();
568 // Trusted Javascript URLs requests should succeed.
569 std::string TestURLLoader::TestTrustedJavascriptURLRestriction() {
570 pp::URLRequestInfo request(instance_);
571 request.SetURL("javascript:foo = bar");
573 int32_t rv = OpenTrusted(request);
574 if (rv == PP_ERROR_NOACCESS)
575 return ReportError(
576 "Trusted Javascript URL request", rv);
578 PASS();
581 std::string TestURLLoader::TestUntrustedHttpRequests() {
582 // HTTP methods are restricted only for untrusted loaders. Forbidden
583 // methods are CONNECT, TRACE, and TRACK, and any string that is not a
584 // valid token (containing special characters like CR, LF).
585 // http://www.w3.org/TR/XMLHttpRequest/
587 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("cOnNeCt", std::string()));
588 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("tRaCk", std::string()));
589 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("tRaCe", std::string()));
590 ASSERT_EQ(PP_ERROR_NOACCESS,
591 OpenUntrusted("POST\x0d\x0ax-csrf-token:\x20test1234", std::string()));
593 // HTTP methods are restricted only for untrusted loaders. Try all headers
594 // that are forbidden by http://www.w3.org/TR/XMLHttpRequest/.
596 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Accept-Charset:\n"));
597 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Accept-Encoding:\n"));
598 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Connection:\n"));
599 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Content-Length:\n"));
600 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Cookie:\n"));
601 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Cookie2:\n"));
602 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Date:\n"));
603 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Dnt:\n"));
604 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Expect:\n"));
605 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Host:\n"));
606 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Keep-Alive:\n"));
607 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Referer:\n"));
608 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "TE:\n"));
609 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Trailer:\n"));
610 ASSERT_EQ(PP_ERROR_NOACCESS,
611 OpenUntrusted("GET", "Transfer-Encoding:\n"));
612 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Upgrade:\n"));
613 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "User-Agent:\n"));
614 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Via:\n"));
615 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted(
616 "GET", "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
617 ASSERT_EQ(PP_ERROR_NOACCESS, OpenUntrusted("GET", "Sec-foo:\n"));
619 // Untrusted requests with custom referrer should fail.
621 pp::URLRequestInfo request(instance_);
622 request.SetCustomReferrerURL("http://www.google.com/");
624 int32_t rv = OpenUntrusted(request);
625 if (rv != PP_ERROR_NOACCESS)
626 return ReportError(
627 "Untrusted request with custom referrer restriction", rv);
629 // Untrusted requests with custom transfer encodings should fail.
631 pp::URLRequestInfo request(instance_);
632 request.SetCustomContentTransferEncoding("foo");
634 int32_t rv = OpenUntrusted(request);
635 if (rv != PP_ERROR_NOACCESS)
636 return ReportError(
637 "Untrusted request with content-transfer-encoding restriction", rv);
640 PASS();
643 std::string TestURLLoader::TestTrustedHttpRequests() {
644 // Trusted requests can use restricted methods.
646 ASSERT_EQ(PP_OK, OpenTrusted("cOnNeCt", std::string()));
647 ASSERT_EQ(PP_OK, OpenTrusted("tRaCk", std::string()));
648 ASSERT_EQ(PP_OK, OpenTrusted("tRaCe", std::string()));
650 // Trusted requests can use restricted headers.
652 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Accept-Charset:\n"));
653 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Accept-Encoding:\n"));
654 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Connection:\n"));
655 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Content-Length:\n"));
656 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Cookie:\n"));
657 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Cookie2:\n"));
658 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Content-Transfer-Encoding:\n"));
659 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Date:\n"));
660 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Expect:\n"));
661 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Host:\n"));
662 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Keep-Alive:\n"));
663 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Referer:\n"));
664 ASSERT_EQ(PP_OK, OpenTrusted("GET", "TE:\n"));
665 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Trailer:\n"));
666 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Transfer-Encoding:\n"));
667 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Upgrade:\n"));
668 ASSERT_EQ(PP_OK, OpenTrusted("GET", "User-Agent:\n"));
669 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Via:\n"));
670 ASSERT_EQ(PP_OK,
671 OpenTrusted("GET",
672 "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==:\n"));
673 ASSERT_EQ(PP_OK, OpenTrusted("GET", "Sec-foo:\n"));
675 // Trusted requests with custom referrer should succeed.
677 pp::URLRequestInfo request(instance_);
678 request.SetCustomReferrerURL("http://www.google.com/");
680 int32_t rv = OpenTrusted(request);
681 if (rv != PP_OK)
682 return ReportError("Trusted request with custom referrer", rv);
684 // Trusted requests with custom transfer encodings should succeed.
686 pp::URLRequestInfo request(instance_);
687 request.SetCustomContentTransferEncoding("foo");
689 int32_t rv = OpenTrusted(request);
690 if (rv != PP_OK)
691 return ReportError(
692 "Trusted request with content-transfer-encoding failed", rv);
695 PASS();
698 // This test should cause a redirect and ensure that the loader follows it.
699 std::string TestURLLoader::TestFollowURLRedirect() {
700 pp::URLRequestInfo request(instance_);
701 // This prefix causes the test server to return a 301 redirect.
702 std::string redirect_prefix("/server-redirect?");
703 // We need an absolute path for the redirect to actually work.
704 std::string redirect_url =
705 GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
706 request.SetURL(redirect_prefix.append(redirect_url));
707 return LoadAndCompareBody(request, "hello\n");
710 // This test should cause a redirect and ensure that the loader runs
711 // the callback, rather than following the redirect.
712 std::string TestURLLoader::TestAuditURLRedirect() {
713 pp::URLRequestInfo request(instance_);
714 // This path will cause the server to return a 301 redirect.
715 // This prefix causes the test server to return a 301 redirect.
716 std::string redirect_prefix("/server-redirect?");
717 // We need an absolute path for the redirect to actually work.
718 std::string redirect_url =
719 GetReachableAbsoluteURL("test_url_loader_data/hello.txt");
720 request.SetURL(redirect_prefix.append(redirect_url));
721 request.SetFollowRedirects(false);
723 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
725 pp::URLLoader loader(instance_);
726 callback.WaitForResult(loader.Open(request, callback.GetCallback()));
727 CHECK_CALLBACK_BEHAVIOR(callback);
728 ASSERT_EQ(PP_OK, callback.result());
730 // Checks that the response indicates a redirect, and that the URL
731 // is correct.
732 pp::URLResponseInfo response_info(loader.GetResponseInfo());
733 if (response_info.is_null())
734 return "URLLoader::GetResponseInfo returned null";
735 int32_t status_code = response_info.GetStatusCode();
736 if (status_code != 301)
737 return "Response status should be 301";
739 // Test that the paused loader can be resumed.
740 callback.WaitForResult(loader.FollowRedirect(callback.GetCallback()));
741 CHECK_CALLBACK_BEHAVIOR(callback);
742 ASSERT_EQ(PP_OK, callback.result());
743 std::string body;
744 std::string error = ReadEntireResponseBody(&loader, &body);
745 if (!error.empty())
746 return error;
748 if (body != "hello\n")
749 return "URLLoader::FollowRedirect failed";
751 PASS();
754 std::string TestURLLoader::TestAbortCalls() {
755 pp::URLRequestInfo request(instance_);
756 request.SetURL("test_url_loader_data/hello.txt");
758 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
759 int32_t rv;
761 // Abort |Open()|.
763 rv = pp::URLLoader(instance_).Open(request, callback.GetCallback());
765 callback.WaitForAbortResult(rv);
766 CHECK_CALLBACK_BEHAVIOR(callback);
768 // Abort |ReadResponseBody()|.
770 char buf[2] = { 0 };
772 pp::URLLoader loader(instance_);
773 callback.WaitForResult(loader.Open(request, callback.GetCallback()));
774 CHECK_CALLBACK_BEHAVIOR(callback);
775 ASSERT_EQ(PP_OK, callback.result());
777 rv = loader.ReadResponseBody(buf, sizeof(buf), callback.GetCallback());
778 } // Destroy |loader|.
779 callback.WaitForAbortResult(rv);
780 CHECK_CALLBACK_BEHAVIOR(callback);
781 if (rv == PP_OK_COMPLETIONPENDING) {
782 if (buf[0] || buf[1]) {
783 return "URLLoader::ReadResponseBody wrote data after resource "
784 "destruction.";
789 // TODO(viettrungluu): More abort tests (but add basic tests first).
790 // Also test that Close() aborts properly. crbug.com/69457
792 PASS();
795 std::string TestURLLoader::TestUntendedLoad() {
796 pp::URLRequestInfo request(instance_);
797 request.SetURL("test_url_loader_data/hello.txt");
798 request.SetRecordDownloadProgress(true);
799 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
801 pp::URLLoader loader(instance_);
802 callback.WaitForResult(loader.Open(request, callback.GetCallback()));
803 CHECK_CALLBACK_BEHAVIOR(callback);
804 ASSERT_EQ(PP_OK, callback.result());
806 // We received the response callback. Yield until the network code has called
807 // the loader's didReceiveData and didFinishLoading methods before we give it
808 // another callback function, to make sure the loader works with no callback.
809 int64_t bytes_received = 0;
810 int64_t total_bytes_to_be_received = 0;
811 while (true) {
812 loader.GetDownloadProgress(&bytes_received, &total_bytes_to_be_received);
813 if (total_bytes_to_be_received <= 0)
814 return ReportError("URLLoader::GetDownloadProgress total size",
815 total_bytes_to_be_received);
816 if (bytes_received == total_bytes_to_be_received)
817 break;
818 // Yield if we're on the main thread, so that URLLoader can receive more
819 // data.
820 if (pp::Module::Get()->core()->IsMainThread()) {
821 NestedEvent event(instance_->pp_instance());
822 event.PostSignal(10);
823 event.Wait();
826 // The loader should now have the data and have finished successfully.
827 std::string body;
828 std::string error = ReadEntireResponseBody(&loader, &body);
829 if (!error.empty())
830 return error;
831 if (body != "hello\n")
832 return ReportError("Couldn't read data", callback.result());
834 PASS();
837 int32_t TestURLLoader::OpenWithPrefetchBufferThreshold(int32_t lower,
838 int32_t upper) {
839 pp::URLRequestInfo request(instance_);
840 request.SetURL("test_url_loader_data/hello.txt");
841 request.SetPrefetchBufferLowerThreshold(lower);
842 request.SetPrefetchBufferUpperThreshold(upper);
844 return OpenUntrusted(request);
847 std::string TestURLLoader::TestPrefetchBufferThreshold() {
848 int32_t rv = OpenWithPrefetchBufferThreshold(-1, 1);
849 if (rv != PP_ERROR_FAILED) {
850 return ReportError("The prefetch limits contained a negative value but "
851 "the URLLoader did not fail.", rv);
854 rv = OpenWithPrefetchBufferThreshold(0, 1);
855 if (rv != PP_OK) {
856 return ReportError("The prefetch buffer limits were legal values but "
857 "the URLLoader failed.", rv);
860 rv = OpenWithPrefetchBufferThreshold(1000, 1);
861 if (rv != PP_ERROR_FAILED) {
862 return ReportError("The lower buffer value was higher than the upper but "
863 "the URLLoader did not fail.", rv);
866 PASS();
869 // TODO(viettrungluu): This test properly belongs elsewhere. It tests that
870 // Chrome properly tags URL requests made on behalf of Pepper plugins (with an
871 // X-Requested-With header), but this isn't, strictly speaking, a PPAPI
872 // behavior.
873 std::string TestURLLoader::TestXRequestedWithHeader() {
874 pp::URLRequestInfo request(instance_);
875 request.SetURL("/echoheader?X-Requested-With");
876 // The name and version of the plugin is set from the command-line (see
877 // chrome/test/ppapi/ppapi_test.cc.
878 return LoadAndCompareBody(request, "PPAPITests/1.2.3");
881 // TODO(viettrungluu): Add tests for Get{Upload,Download}Progress, Close
882 // (including abort tests if applicable).