1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include <algorithm>
6 #include <map>
7 #include <sstream>
8
9 #include "include/base/cef_bind.h"
10 #include "include/cef_parser.h"
11 #include "include/cef_request_context_handler.h"
12 #include "include/cef_scheme.h"
13 #include "include/cef_server.h"
14 #include "include/cef_task.h"
15 #include "include/cef_urlrequest.h"
16 #include "include/cef_waitable_event.h"
17 #include "include/wrapper/cef_closure_task.h"
18 #include "include/wrapper/cef_scoped_temp_dir.h"
19 #include "tests/ceftests/test_handler.h"
20 #include "tests/ceftests/test_request.h"
21 #include "tests/ceftests/test_server.h"
22 #include "tests/ceftests/test_suite.h"
23 #include "tests/ceftests/test_util.h"
24 #include "tests/gtest/include/gtest/gtest.h"
25 #include "tests/shared/browser/client_app_browser.h"
26 #include "tests/shared/browser/file_util.h"
27 #include "tests/shared/renderer/client_app_renderer.h"
28
29 using client::ClientAppRenderer;
30
31 // How to add a new test:
32 // 1. Add a new value to the RequestTestMode enumeration.
33 // 2. Add methods to set up and run the test in RequestTestRunner.
34 // 3. Add a line for the test in the RequestTestRunner constructor.
35 // 4. Add lines for the test in the "Define the tests" section at the bottom of
36 // the file.
37
38 namespace {
39
40 // Browser-side app delegate.
41 class URLRequestBrowserTest : public client::ClientAppBrowser::Delegate {
42 public:
URLRequestBrowserTest()43 URLRequestBrowserTest() {}
44
OnBeforeCommandLineProcessing(CefRefPtr<client::ClientAppBrowser> app,CefRefPtr<CefCommandLine> command_line)45 void OnBeforeCommandLineProcessing(
46 CefRefPtr<client::ClientAppBrowser> app,
47 CefRefPtr<CefCommandLine> command_line) override {
48 // Delegate auth callbacks to GetAuthCredentials with the chrome runtime.
49 command_line->AppendSwitch("disable-chrome-login-prompt");
50
51 // Disable component extensions that require creation of a background
52 // WebContents because they slow down test runs.
53 command_line->AppendSwitch(
54 "disable-component-extensions-with-background-pages");
55 }
56
57 private:
58 IMPLEMENT_REFCOUNTING(URLRequestBrowserTest);
59 };
60
61 // Unique values for URLRequest tests.
62 const char kRequestTestMsg[] = "URLRequestTest.Test";
63 const char kIncompleteRequestTestMsg[] = "URLRequestTest.IncompleteRequestTest";
64
65 // TEST DATA
66
67 // Custom scheme handler backend.
68 const char kRequestSchemeCustom[] = "urcustom";
69 const char kRequestHostCustom[] = "test";
70
71 // Server backend.
72 const char* kRequestAddressServer = test_server::kServerAddress;
73 const uint16 kRequestPortServer = test_server::kServerPort;
74 const char* kRequestSchemeServer = test_server::kServerScheme;
75
76 const char kRequestSendCookieName[] = "urcookie_send";
77 const char kRequestSaveCookieName[] = "urcookie_save";
78
79 const char kCacheControlHeader[] = "cache-control";
80
81 // Used with incomplete tests for data that should not be sent.
82 const char kIncompleteDoNotSendData[] = "DO NOT SEND";
83
84 enum RequestTestMode {
85 REQTEST_GET = 0,
86 REQTEST_GET_NODATA,
87 REQTEST_GET_PARTIAL_CONTENT,
88 REQTEST_GET_ALLOWCOOKIES,
89 REQTEST_GET_REDIRECT,
90 REQTEST_GET_REDIRECT_STOP,
91 REQTEST_GET_REDIRECT_LOCATION,
92 REQTEST_GET_REFERRER,
93 REQTEST_GET_AUTH,
94 REQTEST_POST,
95 REQTEST_POST_FILE,
96 REQTEST_POST_WITHPROGRESS,
97 REQTEST_POST_REDIRECT,
98 REQTEST_POST_REDIRECT_TOGET,
99 REQTEST_HEAD,
100 REQTEST_CACHE_WITH_CONTROL,
101 REQTEST_CACHE_WITHOUT_CONTROL,
102 REQTEST_CACHE_SKIP_FLAG,
103 REQTEST_CACHE_SKIP_HEADER,
104 REQTEST_CACHE_ONLY_FAILURE_FLAG,
105 REQTEST_CACHE_ONLY_FAILURE_HEADER,
106 REQTEST_CACHE_ONLY_SUCCESS_FLAG,
107 REQTEST_CACHE_ONLY_SUCCESS_HEADER,
108 REQTEST_CACHE_DISABLE_FLAG,
109 REQTEST_CACHE_DISABLE_HEADER,
110 REQTEST_INCOMPLETE_PROCESS_REQUEST,
111 REQTEST_INCOMPLETE_READ_RESPONSE,
112 };
113
114 enum ContextTestMode {
115 CONTEXT_GLOBAL,
116 CONTEXT_INMEMORY,
117 CONTEXT_ONDISK,
118 };
119
120 // Defines test expectations for a request.
121 struct RequestRunSettings {
RequestRunSettings__anoncdc9e1c50111::RequestRunSettings122 RequestRunSettings() {}
123
124 // Set expectations for request failure.
SetRequestFailureExpected__anoncdc9e1c50111::RequestRunSettings125 void SetRequestFailureExpected(cef_errorcode_t error_code) {
126 expect_upload_progress = false;
127 expect_download_progress = false;
128 expect_download_data = false;
129 expected_status = UR_FAILED;
130 expected_error_code = error_code;
131 response = nullptr;
132 response_data.clear();
133 }
134
135 // Request that will be sent.
136 CefRefPtr<CefRequest> request;
137
138 // Response that will be returned by the backend.
139 CefRefPtr<CefResponse> response;
140
141 // Optional response data that will be returned by the backend.
142 std::string response_data;
143
144 // Create an incomplete request to test shutdown behavior.
145 enum IncompleteType {
146 INCOMPLETE_NONE,
147 INCOMPLETE_PROCESS_REQUEST,
148 INCOMPLETE_READ_RESPONSE,
149 };
150 IncompleteType incomplete_type = INCOMPLETE_NONE;
151
152 // If true upload progress notification will be expected.
153 bool expect_upload_progress = false;
154
155 // If true download progress notification will be expected.
156 bool expect_download_progress = true;
157
158 // If true download data will be expected.
159 bool expect_download_data = true;
160
161 // The offset from what we passed that we expect to receive.
162 size_t expected_download_offset = 0;
163
164 // Expected status value.
165 CefURLRequest::Status expected_status = UR_SUCCESS;
166
167 // Expected error code value.
168 CefURLRequest::ErrorCode expected_error_code = ERR_NONE;
169
170 // If true the request cookie should be sent to the server.
171 bool expect_send_cookie = false;
172
173 // If true the response cookie should be saved.
174 bool expect_save_cookie = false;
175
176 // If true the test will begin by requiring Basic authentication and then
177 // continue with the actual request. The UR_FLAG_ALLOW_STORED_CREDENTIALS
178 // flag must be set on the request. When using the global request context
179 // CefRequestContext::ClearHttpAuthCredentials should be called to avoid
180 // leaking state across test runs. Authentication is only supported with
181 // browser-initiated requests and the server backend.
182 bool expect_authentication = false;
183 std::string username;
184 std::string password;
185
186 // If specified the test will begin with this redirect request and response.
187 CefRefPtr<CefRequest> redirect_request;
188 CefRefPtr<CefResponse> redirect_response;
189
190 // If true the redirect is expected to be followed.
191 bool expect_follow_redirect = true;
192
193 // If true the response is expected to be served from cache.
194 bool expect_response_was_cached = false;
195
196 // The expected number of requests to send, or -1 if unspecified.
197 // Used only with the server backend.
198 int expected_send_count = -1;
199
200 // The expected number of requests to receive, or -1 if unspecified.
201 // Used only with the server backend.
202 int expected_receive_count = -1;
203
204 typedef base::Callback<void(int /* next_send_count */,
205 const base::Closure& /* complete_callback */)>
206 NextRequestCallback;
207
208 // If non-null this callback will be executed before subsequent requests are
209 // sent.
210 NextRequestCallback setup_next_request;
211 };
212
213 // Manages the map of request URL to test expectations.
214 class RequestDataMap {
215 public:
216 struct Entry {
217 enum Type {
218 TYPE_UNKNOWN,
219 TYPE_NORMAL,
220 TYPE_REDIRECT,
221 };
222
Entry__anoncdc9e1c50111::RequestDataMap::Entry223 Entry(Type entry_type) : type(entry_type), settings(nullptr) {}
224
225 Type type;
226
227 // Used with TYPE_NORMAL.
228 // |settings| is not owned by this object.
229 RequestRunSettings* settings;
230
231 // Used with TYPE_REDIRECT.
232 CefRefPtr<CefRequest> redirect_request;
233 CefRefPtr<CefResponse> redirect_response;
234 };
235
RequestDataMap()236 RequestDataMap() : owner_task_runner_(CefTaskRunner::GetForCurrentThread()) {}
237
238 // Pass ownership to the specified |task_runner| thread.
239 // If |task_runner| is nullptr the test is considered destroyed.
SetOwnerTaskRunner(CefRefPtr<CefTaskRunner> task_runner)240 void SetOwnerTaskRunner(CefRefPtr<CefTaskRunner> task_runner) {
241 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
242 owner_task_runner_ = task_runner;
243 }
244
AddSchemeHandler(RequestRunSettings * settings)245 void AddSchemeHandler(RequestRunSettings* settings) {
246 EXPECT_TRUE(settings);
247 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
248
249 const std::string& url = settings->request->GetURL();
250 data_map_.insert(std::make_pair(url, settings));
251
252 if (settings->redirect_request) {
253 const std::string& redirect_url = settings->redirect_request->GetURL();
254 redirect_data_map_.insert(std::make_pair(
255 redirect_url, std::make_pair(settings->redirect_request,
256 settings->redirect_response)));
257 }
258 }
259
Find(const std::string & url)260 Entry Find(const std::string& url) {
261 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
262
263 Entry entry(Entry::TYPE_UNKNOWN);
264
265 // Try to find a test match.
266 {
267 DataMap::const_iterator it = data_map_.find(url);
268 if (it != data_map_.end()) {
269 entry.type = Entry::TYPE_NORMAL;
270 entry.settings = it->second;
271 return entry;
272 }
273 }
274
275 // Try to find a redirect match.
276 {
277 RedirectDataMap::const_iterator it = redirect_data_map_.find(url);
278 if (it != redirect_data_map_.end()) {
279 entry.type = Entry::TYPE_REDIRECT;
280 entry.redirect_request = it->second.first;
281 entry.redirect_response = it->second.second;
282 return entry;
283 }
284 }
285
286 // Unknown test.
287 ADD_FAILURE() << "url: " << url;
288 return entry;
289 }
290
size() const291 size_t size() const { return data_map_.size() + redirect_data_map_.size(); }
292
293 private:
294 CefRefPtr<CefTaskRunner> owner_task_runner_;
295
296 // The below members are only accessed on the |owner_task_runner_| thread.
297
298 // RequestRunSettings pointer is not owned by this object.
299 typedef std::map<std::string, RequestRunSettings*> DataMap;
300 DataMap data_map_;
301
302 typedef std::map<std::string,
303 std::pair<CefRefPtr<CefRequest>, CefRefPtr<CefResponse>>>
304 RedirectDataMap;
305 RedirectDataMap redirect_data_map_;
306 };
307
308 class TestCompletionCallback : public CefCompletionCallback {
309 public:
TestCompletionCallback(const base::Closure & complete_callback)310 explicit TestCompletionCallback(const base::Closure& complete_callback)
311 : complete_callback_(complete_callback) {
312 EXPECT_FALSE(complete_callback_.is_null());
313 }
314
OnComplete()315 void OnComplete() override {
316 complete_callback_.Run();
317 complete_callback_.Reset();
318 }
319
320 private:
321 base::Closure complete_callback_;
322
323 IMPLEMENT_REFCOUNTING(TestCompletionCallback);
324 };
325
GetRequestScheme(bool server_backend)326 std::string GetRequestScheme(bool server_backend) {
327 return server_backend ? kRequestSchemeServer : kRequestSchemeCustom;
328 }
329
GetRequestHost(bool server_backend,bool with_port)330 std::string GetRequestHost(bool server_backend, bool with_port) {
331 if (server_backend) {
332 if (with_port) {
333 std::stringstream ss;
334 ss << kRequestAddressServer << ":" << kRequestPortServer;
335 return ss.str();
336 } else {
337 return kRequestAddressServer;
338 }
339 } else {
340 return kRequestHostCustom;
341 }
342 }
343
GetRequestOrigin(bool server_backend)344 std::string GetRequestOrigin(bool server_backend) {
345 return GetRequestScheme(server_backend) + "://" +
346 GetRequestHost(server_backend, true);
347 }
348
SetUploadData(CefRefPtr<CefRequest> request,const std::string & data)349 void SetUploadData(CefRefPtr<CefRequest> request, const std::string& data) {
350 CefRefPtr<CefPostData> postData = CefPostData::Create();
351 CefRefPtr<CefPostDataElement> element = CefPostDataElement::Create();
352 element->SetToBytes(data.size(), data.c_str());
353 postData->AddElement(element);
354 request->SetPostData(postData);
355 }
356
SetUploadFile(CefRefPtr<CefRequest> request,const std::string & file)357 void SetUploadFile(CefRefPtr<CefRequest> request, const std::string& file) {
358 CefRefPtr<CefPostData> postData = CefPostData::Create();
359 CefRefPtr<CefPostDataElement> element = CefPostDataElement::Create();
360 element->SetToFile(file);
361 postData->AddElement(element);
362 request->SetPostData(postData);
363 }
364
GetUploadData(CefRefPtr<CefRequest> request,std::string & data)365 void GetUploadData(CefRefPtr<CefRequest> request, std::string& data) {
366 CefRefPtr<CefPostData> postData = request->GetPostData();
367 EXPECT_TRUE(postData.get());
368 CefPostData::ElementVector elements;
369 postData->GetElements(elements);
370 EXPECT_EQ((size_t)1, elements.size());
371 CefRefPtr<CefPostDataElement> element = elements[0];
372 EXPECT_TRUE(element.get());
373
374 size_t size = element->GetBytesCount();
375
376 data.resize(size);
377 EXPECT_EQ(size, data.size());
378 EXPECT_EQ(size, element->GetBytes(size, const_cast<char*>(data.c_str())));
379 }
380
381 // Set a cookie so that we can test if it's sent with the request.
SetTestCookie(CefRefPtr<CefRequestContext> request_context,bool server_backend,const base::Closure & callback)382 void SetTestCookie(CefRefPtr<CefRequestContext> request_context,
383 bool server_backend,
384 const base::Closure& callback) {
385 class Callback : public CefSetCookieCallback {
386 public:
387 explicit Callback(const base::Closure& callback) : callback_(callback) {
388 EXPECT_FALSE(callback_.is_null());
389 }
390
391 void OnComplete(bool success) override {
392 EXPECT_TRUE(success);
393 callback_.Run();
394 callback_.Reset();
395 }
396
397 private:
398 base::Closure callback_;
399
400 IMPLEMENT_REFCOUNTING(Callback);
401 };
402
403 CefCookie cookie;
404 CefString(&cookie.name) = kRequestSendCookieName;
405 CefString(&cookie.value) = "send-cookie-value";
406 CefString(&cookie.domain) = GetRequestHost(server_backend, false);
407 CefString(&cookie.path) = "/";
408 cookie.has_expires = false;
409 EXPECT_TRUE(request_context->GetCookieManager(nullptr)->SetCookie(
410 GetRequestOrigin(server_backend), cookie, new Callback(callback)));
411 }
412
413 typedef base::Callback<void(bool /* cookie exists */)> GetTestCookieCallback;
414
415 // Tests if the save cookie has been set. If set, it will be deleted at the same
416 // time.
GetTestCookie(CefRefPtr<CefRequestContext> request_context,bool server_backend,const GetTestCookieCallback & callback)417 void GetTestCookie(CefRefPtr<CefRequestContext> request_context,
418 bool server_backend,
419 const GetTestCookieCallback& callback) {
420 class Visitor : public CefCookieVisitor {
421 public:
422 explicit Visitor(const GetTestCookieCallback& callback)
423 : callback_(callback), cookie_exists_(false) {
424 EXPECT_FALSE(callback_.is_null());
425 }
426 ~Visitor() override { callback_.Run(cookie_exists_); }
427
428 bool Visit(const CefCookie& cookie,
429 int count,
430 int total,
431 bool& deleteCookie) override {
432 std::string cookie_name = CefString(&cookie.name);
433 if (cookie_name == kRequestSaveCookieName) {
434 cookie_exists_ = true;
435 deleteCookie = true;
436 return false;
437 }
438 return true;
439 }
440
441 private:
442 GetTestCookieCallback callback_;
443 bool cookie_exists_;
444
445 IMPLEMENT_REFCOUNTING(Visitor);
446 };
447
448 CefRefPtr<CefCookieManager> cookie_manager =
449 request_context->GetCookieManager(nullptr);
450 cookie_manager->VisitUrlCookies(GetRequestOrigin(server_backend), true,
451 new Visitor(callback));
452 }
453
GetHeaderValue(const CefRequest::HeaderMap & header_map,const std::string & header_name_lower)454 std::string GetHeaderValue(const CefRequest::HeaderMap& header_map,
455 const std::string& header_name_lower) {
456 CefRequest::HeaderMap::const_iterator it = header_map.begin();
457 for (; it != header_map.end(); ++it) {
458 std::string name = it->first;
459 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
460 if (name == header_name_lower)
461 return it->second;
462 }
463 return std::string();
464 }
465
466 // Verify normal request expectations.
VerifyNormalRequest(const RequestRunSettings * settings,CefRefPtr<CefRequest> request,bool server_backend)467 void VerifyNormalRequest(const RequestRunSettings* settings,
468 CefRefPtr<CefRequest> request,
469 bool server_backend) {
470 // Shouldn't get here if we're not following redirects.
471 EXPECT_TRUE(settings->expect_follow_redirect);
472
473 // Verify that the request was sent correctly.
474 TestRequestEqual(settings->request, request, true);
475
476 CefRequest::HeaderMap headerMap;
477 request->GetHeaderMap(headerMap);
478
479 // Check if the default headers were sent.
480 EXPECT_FALSE(GetHeaderValue(headerMap, "user-agent").empty());
481
482 // CEF_SETTINGS_ACCEPT_LANGUAGE value from CefSettings.accept_language_list
483 // set in CefTestSuite::GetSettings() and expanded internally by
484 // ComputeAcceptLanguageFromPref.
485 EXPECT_STREQ("en-GB,en;q=0.9",
486 GetHeaderValue(headerMap, "accept-language").c_str());
487
488 if (server_backend) {
489 EXPECT_FALSE(GetHeaderValue(headerMap, "accept-encoding").empty());
490 EXPECT_STREQ(GetRequestHost(true, true).c_str(),
491 GetHeaderValue(headerMap, "host").c_str());
492 }
493
494 // Check if the request cookie was sent.
495 const std::string& cookie_value = GetHeaderValue(headerMap, "cookie");
496 bool has_send_cookie = false;
497 if (!cookie_value.empty() &&
498 cookie_value.find(kRequestSendCookieName) != std::string::npos) {
499 has_send_cookie = true;
500 }
501
502 EXPECT_EQ(settings->expect_send_cookie, has_send_cookie);
503 }
504
505 // Populate normal response contents.
GetNormalResponse(const RequestRunSettings * settings,CefRefPtr<CefResponse> response)506 void GetNormalResponse(const RequestRunSettings* settings,
507 CefRefPtr<CefResponse> response) {
508 EXPECT_TRUE(settings->response);
509 if (!settings->response)
510 return;
511
512 response->SetStatus(settings->response->GetStatus());
513 response->SetStatusText(settings->response->GetStatusText());
514 response->SetMimeType(settings->response->GetMimeType());
515
516 CefResponse::HeaderMap headerMap;
517 settings->response->GetHeaderMap(headerMap);
518
519 if (settings->expect_save_cookie) {
520 std::stringstream ss;
521 ss << kRequestSaveCookieName << "="
522 << "save-cookie-value";
523 headerMap.insert(std::make_pair("Set-Cookie", ss.str()));
524 }
525
526 response->SetHeaderMap(headerMap);
527 }
528
529 // Based on https://en.wikipedia.org/wiki/Basic_access_authentication#Protocol
GetAuthResponse(CefRefPtr<CefResponse> response)530 void GetAuthResponse(CefRefPtr<CefResponse> response) {
531 response->SetStatus(401);
532 response->SetStatusText("Unauthorized");
533 response->SetMimeType("text/html");
534
535 CefResponse::HeaderMap headerMap;
536 headerMap.insert(
537 std::make_pair("WWW-Authenticate", "Basic realm=\"Test Realm\""));
538 response->SetHeaderMap(headerMap);
539 }
540
IsAuthorized(CefRefPtr<CefRequest> request,const std::string & username,const std::string & password)541 bool IsAuthorized(CefRefPtr<CefRequest> request,
542 const std::string& username,
543 const std::string& password) {
544 const std::string& authHeader = request->GetHeaderByName("Authorization");
545 if (authHeader.empty())
546 return false;
547
548 if (authHeader.find("Basic ") == 0) {
549 const std::string& base64 = authHeader.substr(6);
550 CefRefPtr<CefBinaryValue> data = CefBase64Decode(base64);
551 EXPECT_TRUE(data);
552 if (!data) {
553 LOG(ERROR) << "Failed to decode Authorization value: " << base64;
554 return false;
555 }
556
557 std::string decoded;
558 decoded.resize(data->GetSize());
559 data->GetData(&decoded[0], data->GetSize(), 0);
560
561 const std::string& expected = username + ":" + password;
562 EXPECT_STREQ(expected.c_str(), decoded.c_str());
563 return decoded == expected;
564 }
565
566 LOG(ERROR) << "Unexpected Authorization value: " << authHeader;
567 return false;
568 }
569
570 // SCHEME HANDLER BACKEND
571
572 // Serves request responses.
573 class RequestSchemeHandlerOld : public CefResourceHandler {
574 public:
RequestSchemeHandlerOld(RequestRunSettings * settings,const base::Closure & destroy_callback)575 RequestSchemeHandlerOld(RequestRunSettings* settings,
576 const base::Closure& destroy_callback)
577 : settings_(settings), destroy_callback_(destroy_callback) {}
578
~RequestSchemeHandlerOld()579 ~RequestSchemeHandlerOld() override {
580 EXPECT_EQ(1, cancel_ct_);
581 destroy_callback_.Run();
582 }
583
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)584 bool ProcessRequest(CefRefPtr<CefRequest> request,
585 CefRefPtr<CefCallback> callback) override {
586 EXPECT_IO_THREAD();
587 VerifyNormalRequest(settings_, request, false);
588
589 // HEAD requests are identical to GET requests except no response data is
590 // sent.
591 if (request->GetMethod() != "HEAD")
592 response_data_ = settings_->response_data;
593
594 // Continue immediately.
595 callback->Continue();
596 return true;
597 }
598
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)599 void GetResponseHeaders(CefRefPtr<CefResponse> response,
600 int64& response_length,
601 CefString& redirectUrl) override {
602 EXPECT_IO_THREAD();
603 GetNormalResponse(settings_, response);
604 response_length = response_data_.length();
605 }
606
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)607 bool ReadResponse(void* data_out,
608 int bytes_to_read,
609 int& bytes_read,
610 CefRefPtr<CefCallback> callback) override {
611 EXPECT_IO_THREAD();
612
613 bool has_data = false;
614 bytes_read = 0;
615
616 size_t size = response_data_.length();
617 if (offset_ < size) {
618 int transfer_size =
619 std::min(bytes_to_read, static_cast<int>(size - offset_));
620 memcpy(data_out, response_data_.c_str() + offset_, transfer_size);
621 offset_ += transfer_size;
622
623 bytes_read = transfer_size;
624 has_data = true;
625 }
626
627 return has_data;
628 }
629
Cancel()630 void Cancel() override {
631 EXPECT_IO_THREAD();
632 cancel_ct_++;
633 }
634
635 private:
636 // |settings_| is not owned by this object.
637 RequestRunSettings* settings_;
638 base::Closure destroy_callback_;
639
640 std::string response_data_;
641 size_t offset_ = 0;
642
643 int cancel_ct_ = 0;
644
645 IMPLEMENT_REFCOUNTING(RequestSchemeHandlerOld);
646 DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandlerOld);
647 };
648
649 class RequestSchemeHandler : public CefResourceHandler {
650 public:
RequestSchemeHandler(RequestRunSettings * settings,const base::Closure & destroy_callback)651 RequestSchemeHandler(RequestRunSettings* settings,
652 const base::Closure& destroy_callback)
653 : settings_(settings), destroy_callback_(destroy_callback) {}
654
~RequestSchemeHandler()655 ~RequestSchemeHandler() override {
656 EXPECT_EQ(1, cancel_ct_);
657 destroy_callback_.Run();
658 }
659
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)660 bool Open(CefRefPtr<CefRequest> request,
661 bool& handle_request,
662 CefRefPtr<CefCallback> callback) override {
663 EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
664 VerifyNormalRequest(settings_, request, false);
665
666 // HEAD requests are identical to GET requests except no response data is
667 // sent.
668 if (request->GetMethod() != "HEAD")
669 response_data_ = settings_->response_data;
670
671 // Continue immediately.
672 handle_request = true;
673 return true;
674 }
675
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)676 bool ProcessRequest(CefRefPtr<CefRequest> request,
677 CefRefPtr<CefCallback> callback) override {
678 EXPECT_TRUE(false); // Not reached.
679 return false;
680 }
681
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)682 void GetResponseHeaders(CefRefPtr<CefResponse> response,
683 int64& response_length,
684 CefString& redirectUrl) override {
685 EXPECT_IO_THREAD();
686 GetNormalResponse(settings_, response);
687 response_length = response_data_.length() - offset_;
688 }
689
Skip(int64 bytes_to_skip,int64 & bytes_skipped,CefRefPtr<CefResourceSkipCallback> callback)690 bool Skip(int64 bytes_to_skip,
691 int64& bytes_skipped,
692 CefRefPtr<CefResourceSkipCallback> callback) override {
693 size_t size = response_data_.length();
694 if (offset_ < size) {
695 bytes_skipped =
696 std::min(bytes_to_skip, static_cast<int64>(size - offset_));
697 offset_ += bytes_skipped;
698 } else {
699 bytes_skipped = ERR_FAILED;
700 }
701
702 return bytes_skipped > 0;
703 }
704
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)705 bool Read(void* data_out,
706 int bytes_to_read,
707 int& bytes_read,
708 CefRefPtr<CefResourceReadCallback> callback) override {
709 EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
710
711 // Default to response complete.
712 bool has_data = false;
713 bytes_read = 0;
714
715 size_t size = response_data_.length();
716 if (offset_ < size) {
717 int transfer_size =
718 std::min(bytes_to_read, static_cast<int>(size - offset_));
719 memcpy(data_out, response_data_.c_str() + offset_, transfer_size);
720 offset_ += transfer_size;
721
722 bytes_read = transfer_size;
723 has_data = true;
724 }
725
726 return has_data;
727 }
728
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)729 bool ReadResponse(void* data_out,
730 int bytes_to_read,
731 int& bytes_read,
732 CefRefPtr<CefCallback> callback) override {
733 EXPECT_TRUE(false); // Not reached.
734 bytes_read = -2;
735 return false;
736 }
737
Cancel()738 void Cancel() override {
739 EXPECT_IO_THREAD();
740 cancel_ct_++;
741 }
742
743 private:
744 // |settings_| is not owned by this object.
745 RequestRunSettings* settings_;
746 base::Closure destroy_callback_;
747
748 std::string response_data_;
749 size_t offset_ = 0;
750
751 int cancel_ct_ = 0;
752
753 IMPLEMENT_REFCOUNTING(RequestSchemeHandler);
754 DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandler);
755 };
756
757 // Serves redirect request responses.
758 class RequestRedirectSchemeHandlerOld : public CefResourceHandler {
759 public:
RequestRedirectSchemeHandlerOld(CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response,const base::Closure & destroy_callback)760 RequestRedirectSchemeHandlerOld(CefRefPtr<CefRequest> request,
761 CefRefPtr<CefResponse> response,
762 const base::Closure& destroy_callback)
763 : request_(request),
764 response_(response),
765 destroy_callback_(destroy_callback) {}
766
~RequestRedirectSchemeHandlerOld()767 ~RequestRedirectSchemeHandlerOld() override {
768 EXPECT_EQ(1, cancel_ct_);
769 destroy_callback_.Run();
770 }
771
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)772 bool ProcessRequest(CefRefPtr<CefRequest> request,
773 CefRefPtr<CefCallback> callback) override {
774 EXPECT_IO_THREAD();
775
776 // Verify that the request was sent correctly.
777 TestRequestEqual(request_, request, true);
778
779 // Continue immediately.
780 callback->Continue();
781 return true;
782 }
783
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)784 void GetResponseHeaders(CefRefPtr<CefResponse> response,
785 int64& response_length,
786 CefString& redirectUrl) override {
787 EXPECT_IO_THREAD();
788
789 response->SetStatus(response_->GetStatus());
790 response->SetStatusText(response_->GetStatusText());
791 response->SetMimeType(response_->GetMimeType());
792
793 CefResponse::HeaderMap headerMap;
794 response_->GetHeaderMap(headerMap);
795 response->SetHeaderMap(headerMap);
796
797 response_length = 0;
798 }
799
ReadResponse(void * response_data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)800 bool ReadResponse(void* response_data_out,
801 int bytes_to_read,
802 int& bytes_read,
803 CefRefPtr<CefCallback> callback) override {
804 EXPECT_IO_THREAD();
805 NOTREACHED();
806 return false;
807 }
808
Cancel()809 void Cancel() override {
810 EXPECT_IO_THREAD();
811 cancel_ct_++;
812 }
813
814 private:
815 CefRefPtr<CefRequest> request_;
816 CefRefPtr<CefResponse> response_;
817 base::Closure destroy_callback_;
818
819 int cancel_ct_ = 0;
820
821 IMPLEMENT_REFCOUNTING(RequestRedirectSchemeHandlerOld);
822 DISALLOW_COPY_AND_ASSIGN(RequestRedirectSchemeHandlerOld);
823 };
824
825 class RequestRedirectSchemeHandler : public CefResourceHandler {
826 public:
RequestRedirectSchemeHandler(CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response,const base::Closure & destroy_callback)827 RequestRedirectSchemeHandler(CefRefPtr<CefRequest> request,
828 CefRefPtr<CefResponse> response,
829 const base::Closure& destroy_callback)
830 : request_(request),
831 response_(response),
832 destroy_callback_(destroy_callback) {}
833
~RequestRedirectSchemeHandler()834 ~RequestRedirectSchemeHandler() override {
835 EXPECT_EQ(1, cancel_ct_);
836 destroy_callback_.Run();
837 }
838
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)839 bool Open(CefRefPtr<CefRequest> request,
840 bool& handle_request,
841 CefRefPtr<CefCallback> callback) override {
842 EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
843
844 // Verify that the request was sent correctly.
845 TestRequestEqual(request_, request, true);
846
847 // Continue immediately.
848 handle_request = true;
849 return true;
850 }
851
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)852 bool ProcessRequest(CefRefPtr<CefRequest> request,
853 CefRefPtr<CefCallback> callback) override {
854 EXPECT_TRUE(false); // Not reached.
855 return false;
856 }
857
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)858 void GetResponseHeaders(CefRefPtr<CefResponse> response,
859 int64& response_length,
860 CefString& redirectUrl) override {
861 EXPECT_IO_THREAD();
862
863 response->SetStatus(response_->GetStatus());
864 response->SetStatusText(response_->GetStatusText());
865 response->SetMimeType(response_->GetMimeType());
866
867 CefResponse::HeaderMap headerMap;
868 response_->GetHeaderMap(headerMap);
869 response->SetHeaderMap(headerMap);
870
871 response_length = 0;
872 }
873
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)874 bool Read(void* data_out,
875 int bytes_to_read,
876 int& bytes_read,
877 CefRefPtr<CefResourceReadCallback> callback) override {
878 EXPECT_TRUE(false); // Not reached.
879 bytes_read = -1;
880 return false;
881 }
882
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)883 bool ReadResponse(void* data_out,
884 int bytes_to_read,
885 int& bytes_read,
886 CefRefPtr<CefCallback> callback) override {
887 EXPECT_TRUE(false); // Not reached.
888 bytes_read = -2;
889 return false;
890 }
891
Cancel()892 void Cancel() override {
893 EXPECT_IO_THREAD();
894 cancel_ct_++;
895 }
896
897 private:
898 CefRefPtr<CefRequest> request_;
899 CefRefPtr<CefResponse> response_;
900 base::Closure destroy_callback_;
901
902 int cancel_ct_ = 0;
903
904 IMPLEMENT_REFCOUNTING(RequestRedirectSchemeHandler);
905 DISALLOW_COPY_AND_ASSIGN(RequestRedirectSchemeHandler);
906 };
907
908 // Resource handler implementation that never completes. Used to test
909 // destruction handling behavior for in-progress requests.
910 class IncompleteSchemeHandlerOld : public CefResourceHandler {
911 public:
IncompleteSchemeHandlerOld(RequestRunSettings * settings,const base::Closure & destroy_callback)912 IncompleteSchemeHandlerOld(RequestRunSettings* settings,
913 const base::Closure& destroy_callback)
914 : settings_(settings), destroy_callback_(destroy_callback) {
915 EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE);
916 }
917
~IncompleteSchemeHandlerOld()918 ~IncompleteSchemeHandlerOld() override {
919 EXPECT_EQ(1, process_request_ct_);
920 EXPECT_EQ(1, cancel_ct_);
921
922 if (settings_->incomplete_type ==
923 RequestRunSettings::INCOMPLETE_READ_RESPONSE) {
924 EXPECT_EQ(1, get_response_headers_ct_);
925 EXPECT_EQ(1, read_response_ct_);
926 } else {
927 EXPECT_EQ(0, get_response_headers_ct_);
928 EXPECT_EQ(0, read_response_ct_);
929 }
930
931 destroy_callback_.Run();
932 }
933
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)934 bool ProcessRequest(CefRefPtr<CefRequest> request,
935 CefRefPtr<CefCallback> callback) override {
936 EXPECT_IO_THREAD();
937
938 process_request_ct_++;
939
940 if (settings_->incomplete_type ==
941 RequestRunSettings::INCOMPLETE_PROCESS_REQUEST) {
942 // Never release or execute this callback.
943 incomplete_callback_ = callback;
944 } else {
945 callback->Continue();
946 }
947 return true;
948 }
949
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)950 void GetResponseHeaders(CefRefPtr<CefResponse> response,
951 int64& response_length,
952 CefString& redirectUrl) override {
953 EXPECT_IO_THREAD();
954 EXPECT_EQ(settings_->incomplete_type,
955 RequestRunSettings::INCOMPLETE_READ_RESPONSE);
956
957 get_response_headers_ct_++;
958
959 response->SetStatus(settings_->response->GetStatus());
960 response->SetStatusText(settings_->response->GetStatusText());
961 response->SetMimeType(settings_->response->GetMimeType());
962
963 CefResponse::HeaderMap headerMap;
964 settings_->response->GetHeaderMap(headerMap);
965 settings_->response->SetHeaderMap(headerMap);
966
967 response_length = static_cast<int64>(settings_->response_data.size());
968 }
969
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)970 bool ReadResponse(void* data_out,
971 int bytes_to_read,
972 int& bytes_read,
973 CefRefPtr<CefCallback> callback) override {
974 EXPECT_IO_THREAD();
975 EXPECT_EQ(settings_->incomplete_type,
976 RequestRunSettings::INCOMPLETE_READ_RESPONSE);
977
978 read_response_ct_++;
979
980 // Never release or execute this callback.
981 incomplete_callback_ = callback;
982 bytes_read = 0;
983 return true;
984 }
985
Cancel()986 void Cancel() override {
987 EXPECT_IO_THREAD();
988 cancel_ct_++;
989 }
990
991 private:
992 RequestRunSettings* const settings_;
993 const base::Closure destroy_callback_;
994
995 int process_request_ct_ = 0;
996 int get_response_headers_ct_ = 0;
997 int read_response_ct_ = 0;
998 int cancel_ct_ = 0;
999
1000 CefRefPtr<CefCallback> incomplete_callback_;
1001
1002 IMPLEMENT_REFCOUNTING(IncompleteSchemeHandlerOld);
1003 DISALLOW_COPY_AND_ASSIGN(IncompleteSchemeHandlerOld);
1004 };
1005
1006 class IncompleteSchemeHandler : public CefResourceHandler {
1007 public:
IncompleteSchemeHandler(RequestRunSettings * settings,const base::Closure & destroy_callback)1008 IncompleteSchemeHandler(RequestRunSettings* settings,
1009 const base::Closure& destroy_callback)
1010 : settings_(settings), destroy_callback_(destroy_callback) {
1011 EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE);
1012 }
1013
~IncompleteSchemeHandler()1014 ~IncompleteSchemeHandler() override {
1015 EXPECT_EQ(1, open_ct_);
1016 EXPECT_EQ(1, cancel_ct_);
1017
1018 if (settings_->incomplete_type ==
1019 RequestRunSettings::INCOMPLETE_READ_RESPONSE) {
1020 EXPECT_EQ(1, get_response_headers_ct_);
1021 EXPECT_EQ(1, read_ct_);
1022 } else {
1023 EXPECT_EQ(0, get_response_headers_ct_);
1024 EXPECT_EQ(0, read_ct_);
1025 }
1026
1027 destroy_callback_.Run();
1028 }
1029
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)1030 bool Open(CefRefPtr<CefRequest> request,
1031 bool& handle_request,
1032 CefRefPtr<CefCallback> callback) override {
1033 EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
1034
1035 open_ct_++;
1036
1037 if (settings_->incomplete_type ==
1038 RequestRunSettings::INCOMPLETE_PROCESS_REQUEST) {
1039 // Never release or execute this callback.
1040 incomplete_open_callback_ = callback;
1041 } else {
1042 // Continue immediately.
1043 handle_request = true;
1044 }
1045 return true;
1046 }
1047
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)1048 bool ProcessRequest(CefRefPtr<CefRequest> request,
1049 CefRefPtr<CefCallback> callback) override {
1050 EXPECT_TRUE(false); // Not reached.
1051 return false;
1052 }
1053
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)1054 void GetResponseHeaders(CefRefPtr<CefResponse> response,
1055 int64& response_length,
1056 CefString& redirectUrl) override {
1057 EXPECT_IO_THREAD();
1058 EXPECT_EQ(settings_->incomplete_type,
1059 RequestRunSettings::INCOMPLETE_READ_RESPONSE);
1060
1061 get_response_headers_ct_++;
1062
1063 response->SetStatus(settings_->response->GetStatus());
1064 response->SetStatusText(settings_->response->GetStatusText());
1065 response->SetMimeType(settings_->response->GetMimeType());
1066
1067 CefResponse::HeaderMap headerMap;
1068 settings_->response->GetHeaderMap(headerMap);
1069 settings_->response->SetHeaderMap(headerMap);
1070
1071 response_length = static_cast<int64>(settings_->response_data.size());
1072 }
1073
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)1074 bool Read(void* data_out,
1075 int bytes_to_read,
1076 int& bytes_read,
1077 CefRefPtr<CefResourceReadCallback> callback) override {
1078 EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
1079 EXPECT_EQ(settings_->incomplete_type,
1080 RequestRunSettings::INCOMPLETE_READ_RESPONSE);
1081
1082 read_ct_++;
1083
1084 // Never release or execute this callback.
1085 incomplete_read_callback_ = callback;
1086 bytes_read = 0;
1087 return true;
1088 }
1089
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)1090 bool ReadResponse(void* data_out,
1091 int bytes_to_read,
1092 int& bytes_read,
1093 CefRefPtr<CefCallback> callback) override {
1094 EXPECT_TRUE(false); // Not reached.
1095 bytes_read = -2;
1096 return false;
1097 }
1098
Cancel()1099 void Cancel() override {
1100 EXPECT_IO_THREAD();
1101 cancel_ct_++;
1102 }
1103
1104 private:
1105 RequestRunSettings* const settings_;
1106 const base::Closure destroy_callback_;
1107
1108 int open_ct_ = 0;
1109 int get_response_headers_ct_ = 0;
1110 int read_ct_ = 0;
1111 int cancel_ct_ = 0;
1112
1113 CefRefPtr<CefCallback> incomplete_open_callback_;
1114 CefRefPtr<CefResourceReadCallback> incomplete_read_callback_;
1115
1116 IMPLEMENT_REFCOUNTING(IncompleteSchemeHandler);
1117 DISALLOW_COPY_AND_ASSIGN(IncompleteSchemeHandler);
1118 };
1119
1120 class RequestSchemeHandlerFactory : public CefSchemeHandlerFactory {
1121 public:
RequestSchemeHandlerFactory()1122 RequestSchemeHandlerFactory() {}
1123
Create(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & scheme_name,CefRefPtr<CefRequest> request)1124 CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
1125 CefRefPtr<CefFrame> frame,
1126 const CefString& scheme_name,
1127 CefRefPtr<CefRequest> request) override {
1128 EXPECT_IO_THREAD();
1129
1130 handler_create_ct_++;
1131 const base::Closure destroy_callback =
1132 base::Bind(&RequestSchemeHandlerFactory::OnHandlerDestroyed, this);
1133
1134 RequestDataMap::Entry entry = data_map_.Find(request->GetURL());
1135 if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) {
1136 if (entry.settings->incomplete_type ==
1137 RequestRunSettings::INCOMPLETE_NONE) {
1138 if (TestOldResourceAPI()) {
1139 return new RequestSchemeHandlerOld(entry.settings, destroy_callback);
1140 }
1141 return new RequestSchemeHandler(entry.settings, destroy_callback);
1142 }
1143
1144 if (TestOldResourceAPI()) {
1145 return new IncompleteSchemeHandlerOld(entry.settings, destroy_callback);
1146 }
1147 return new IncompleteSchemeHandler(entry.settings, destroy_callback);
1148 } else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) {
1149 if (TestOldResourceAPI()) {
1150 return new RequestRedirectSchemeHandlerOld(
1151 entry.redirect_request, entry.redirect_response, destroy_callback);
1152 }
1153 return new RequestRedirectSchemeHandler(
1154 entry.redirect_request, entry.redirect_response, destroy_callback);
1155 }
1156
1157 // Unknown test.
1158 ADD_FAILURE();
1159 return nullptr;
1160 }
1161
SetOwnerTaskRunner(CefRefPtr<CefTaskRunner> task_runner)1162 void SetOwnerTaskRunner(CefRefPtr<CefTaskRunner> task_runner) {
1163 data_map_.SetOwnerTaskRunner(task_runner);
1164 }
1165
AddSchemeHandler(RequestRunSettings * settings)1166 void AddSchemeHandler(RequestRunSettings* settings) {
1167 const std::string& scheme = GetRequestScheme(false);
1168
1169 // Verify that the scheme is correct.
1170 const std::string& url = settings->request->GetURL();
1171 EXPECT_EQ(0U, url.find(scheme));
1172
1173 if (settings->redirect_request) {
1174 // Verify that the scheme is correct.
1175 const std::string& redirect_url = settings->redirect_request->GetURL();
1176 EXPECT_EQ(0U, redirect_url.find(scheme));
1177 }
1178
1179 data_map_.AddSchemeHandler(settings);
1180 }
1181
OnHandlerDestroyed()1182 void OnHandlerDestroyed() {
1183 if (!CefCurrentlyOn(TID_IO)) {
1184 CefPostTask(
1185 TID_IO,
1186 base::Bind(&RequestSchemeHandlerFactory::OnHandlerDestroyed, this));
1187 return;
1188 }
1189
1190 handler_destroy_ct_++;
1191
1192 MaybeShutdown();
1193 }
1194
Shutdown(const base::Closure & complete_callback)1195 void Shutdown(const base::Closure& complete_callback) {
1196 if (!CefCurrentlyOn(TID_IO)) {
1197 CefPostTask(TID_IO, base::Bind(&RequestSchemeHandlerFactory::Shutdown,
1198 this, complete_callback));
1199 return;
1200 }
1201
1202 EXPECT_TRUE(shutdown_callback_.is_null());
1203 shutdown_callback_ = complete_callback;
1204
1205 data_map_.SetOwnerTaskRunner(nullptr);
1206
1207 MaybeShutdown();
1208 }
1209
1210 private:
MaybeShutdown()1211 void MaybeShutdown() {
1212 if (!shutdown_callback_.is_null() &&
1213 handler_create_ct_ == handler_destroy_ct_) {
1214 shutdown_callback_.Run();
1215 shutdown_callback_.Reset();
1216 }
1217 }
1218
1219 RequestDataMap data_map_;
1220
1221 int handler_create_ct_ = 0;
1222 int handler_destroy_ct_ = 0;
1223 base::Closure shutdown_callback_;
1224
1225 IMPLEMENT_REFCOUNTING(RequestSchemeHandlerFactory);
1226 DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandlerFactory);
1227 };
1228
1229 // SERVER BACKEND
1230
1231 // HTTP server handler.
1232 class RequestServerHandler : public test_server::ObserverHelper {
1233 public:
RequestServerHandler()1234 RequestServerHandler()
1235 : initialized_(false),
1236 expected_connection_ct_(-1),
1237 actual_connection_ct_(0),
1238 expected_http_request_ct_(-1),
1239 actual_http_request_ct_(0) {}
1240
~RequestServerHandler()1241 virtual ~RequestServerHandler() { RunCompleteCallback(false); }
1242
1243 // Must be called before CreateServer().
AddSchemeHandler(RequestRunSettings * settings)1244 void AddSchemeHandler(RequestRunSettings* settings) {
1245 EXPECT_FALSE(initialized_);
1246 data_map_.AddSchemeHandler(settings);
1247 }
1248
1249 // Must be called before CreateServer().
SetExpectedRequestCount(int count)1250 void SetExpectedRequestCount(int count) {
1251 EXPECT_FALSE(initialized_);
1252 expected_connection_ct_ = expected_http_request_ct_ = count;
1253 }
1254
1255 // |complete_callback| will be executed on the UI thread after the server is
1256 // started.
CreateServer(const base::Closure & complete_callback)1257 void CreateServer(const base::Closure& complete_callback) {
1258 EXPECT_UI_THREAD();
1259
1260 if (expected_connection_ct_ < 0) {
1261 // Default to the assumption of one request per registered URL.
1262 SetExpectedRequestCount(static_cast<int>(data_map_.size()));
1263 }
1264
1265 EXPECT_FALSE(initialized_);
1266 initialized_ = true;
1267
1268 EXPECT_TRUE(complete_callback_.is_null());
1269 complete_callback_ = complete_callback;
1270
1271 Initialize();
1272 }
1273
1274 // Results in a call to VerifyResults() and eventual execution of the
1275 // |complete_callback| on the UI thread via RequestServerHandler destruction.
ShutdownServer(const base::Closure & complete_callback)1276 void ShutdownServer(const base::Closure& complete_callback) {
1277 EXPECT_UI_THREAD();
1278
1279 EXPECT_TRUE(complete_callback_.is_null());
1280 complete_callback_ = complete_callback;
1281
1282 Shutdown();
1283 }
1284
OnInitialized(const std::string & server_origin)1285 void OnInitialized(const std::string& server_origin) override {
1286 EXPECT_UI_THREAD();
1287 EXPECT_STREQ(server_origin.c_str(), GetRequestOrigin(true).c_str());
1288 EXPECT_FALSE(got_initialized_);
1289 got_initialized_.yes();
1290
1291 RunCompleteCallback(true);
1292 }
1293
OnShutdown()1294 void OnShutdown() override {
1295 EXPECT_UI_THREAD();
1296 EXPECT_FALSE(got_shutdown_);
1297 got_shutdown_.yes();
1298
1299 data_map_.SetOwnerTaskRunner(nullptr);
1300
1301 VerifyResults();
1302
1303 delete this;
1304 }
1305
OnClientConnected(CefRefPtr<CefServer> server,int connection_id)1306 bool OnClientConnected(CefRefPtr<CefServer> server,
1307 int connection_id) override {
1308 EXPECT_UI_THREAD();
1309
1310 if (!IsChromeRuntimeEnabled()) {
1311 EXPECT_TRUE(connection_id_set_.find(connection_id) ==
1312 connection_id_set_.end());
1313 connection_id_set_.insert(connection_id);
1314 }
1315
1316 actual_connection_ct_++;
1317
1318 return true;
1319 }
1320
OnClientDisconnected(CefRefPtr<CefServer> server,int connection_id)1321 bool OnClientDisconnected(CefRefPtr<CefServer> server,
1322 int connection_id) override {
1323 EXPECT_UI_THREAD();
1324
1325 if (!IsChromeRuntimeEnabled()) {
1326 ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
1327 EXPECT_TRUE(it != connection_id_set_.end());
1328 connection_id_set_.erase(it);
1329 }
1330
1331 return true;
1332 }
1333
OnHttpRequest(CefRefPtr<CefServer> server,int connection_id,const CefString & client_address,CefRefPtr<CefRequest> request)1334 bool OnHttpRequest(CefRefPtr<CefServer> server,
1335 int connection_id,
1336 const CefString& client_address,
1337 CefRefPtr<CefRequest> request) override {
1338 EXPECT_UI_THREAD();
1339 if (!IsChromeRuntimeEnabled()) {
1340 EXPECT_TRUE(VerifyConnection(connection_id));
1341 }
1342 EXPECT_FALSE(client_address.empty());
1343
1344 // Log the requests for better error reporting.
1345 request_log_ += request->GetMethod().ToString() + " " +
1346 request->GetURL().ToString() + "\n";
1347
1348 // TODO(chrome-runtime): Debug why favicon requests don't always have the
1349 // correct resource type.
1350 const std::string& url = request->GetURL();
1351 if (request->GetResourceType() == RT_FAVICON ||
1352 url.find("/favicon.ico") != std::string::npos) {
1353 // We don't currently handle favicon requests.
1354 server->SendHttp404Response(connection_id);
1355 return true;
1356 }
1357
1358 HandleRequest(server, connection_id, request);
1359
1360 actual_http_request_ct_++;
1361
1362 return true;
1363 }
1364
1365 private:
VerifyConnection(int connection_id)1366 bool VerifyConnection(int connection_id) {
1367 return connection_id_set_.find(connection_id) != connection_id_set_.end();
1368 }
1369
VerifyResults()1370 void VerifyResults() {
1371 EXPECT_TRUE(got_initialized_);
1372 EXPECT_TRUE(got_shutdown_);
1373 if (!IsChromeRuntimeEnabled()) {
1374 EXPECT_TRUE(connection_id_set_.empty());
1375 EXPECT_EQ(expected_connection_ct_, actual_connection_ct_) << request_log_;
1376 EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
1377 << request_log_;
1378 }
1379 }
1380
HandleRequest(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefRequest> request)1381 void HandleRequest(CefRefPtr<CefServer> server,
1382 int connection_id,
1383 CefRefPtr<CefRequest> request) {
1384 RequestDataMap::Entry entry = data_map_.Find(request->GetURL());
1385 if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) {
1386 const bool needs_auth = entry.settings->expect_authentication &&
1387 !IsAuthorized(request, entry.settings->username,
1388 entry.settings->password);
1389 if (needs_auth) {
1390 HandleAuthRequest(server, connection_id, request);
1391 return;
1392 }
1393
1394 HandleNormalRequest(server, connection_id, request, entry.settings);
1395 } else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) {
1396 HandleRedirectRequest(server, connection_id, request,
1397 entry.redirect_request, entry.redirect_response);
1398 } else {
1399 // Unknown test.
1400 ADD_FAILURE() << "url: " << request->GetURL().ToString();
1401 server->SendHttp500Response(connection_id, "Unknown test");
1402 }
1403 }
1404
HandleAuthRequest(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefRequest> request)1405 static void HandleAuthRequest(CefRefPtr<CefServer> server,
1406 int connection_id,
1407 CefRefPtr<CefRequest> request) {
1408 CefRefPtr<CefResponse> response = CefResponse::Create();
1409 GetAuthResponse(response);
1410 SendResponse(server, connection_id, response, std::string());
1411 }
1412
HandleNormalRequest(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefRequest> request,RequestRunSettings * settings)1413 static void HandleNormalRequest(CefRefPtr<CefServer> server,
1414 int connection_id,
1415 CefRefPtr<CefRequest> request,
1416 RequestRunSettings* settings) {
1417 VerifyNormalRequest(settings, request, true);
1418
1419 CefRefPtr<CefResponse> response = CefResponse::Create();
1420 GetNormalResponse(settings, response);
1421
1422 // HEAD requests are identical to GET requests except no response data is
1423 // sent.
1424 std::string response_data;
1425 if (request->GetMethod() != "HEAD") {
1426 size_t expected_offset = settings->expected_download_offset;
1427 response_data = settings->response_data.substr(expected_offset);
1428 }
1429
1430 SendResponse(server, connection_id, response, response_data);
1431 }
1432
HandleRedirectRequest(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefRequest> request,CefRefPtr<CefRequest> redirect_request,CefRefPtr<CefResponse> redirect_response)1433 static void HandleRedirectRequest(CefRefPtr<CefServer> server,
1434 int connection_id,
1435 CefRefPtr<CefRequest> request,
1436 CefRefPtr<CefRequest> redirect_request,
1437 CefRefPtr<CefResponse> redirect_response) {
1438 if (redirect_response->GetStatus() == 302) {
1439 // Simulate wrong copying of POST-specific headers Content-Type and
1440 // Content-Length. A 302 redirect should end up in a GET request and
1441 // these headers should not propagate from a 302 POST-to-GET redirect.
1442 CefResponse::HeaderMap redirectHeaderMap;
1443 redirect_response->GetHeaderMap(redirectHeaderMap);
1444 redirectHeaderMap.insert(
1445 std::make_pair("content-type", "application/x-www-form-urlencoded"));
1446 redirectHeaderMap.insert(std::make_pair("content-length", "0"));
1447 redirect_response->SetHeaderMap(redirectHeaderMap);
1448 }
1449
1450 // Verify that the request was sent correctly.
1451 TestRequestEqual(redirect_request, request, true);
1452
1453 SendResponse(server, connection_id, redirect_response, std::string());
1454 }
1455
SendResponse(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefResponse> response,const std::string & response_data)1456 static void SendResponse(CefRefPtr<CefServer> server,
1457 int connection_id,
1458 CefRefPtr<CefResponse> response,
1459 const std::string& response_data) {
1460 // Execute on the server thread because some methods require it.
1461 CefRefPtr<CefTaskRunner> task_runner = server->GetTaskRunner();
1462 if (!task_runner->BelongsToCurrentThread()) {
1463 task_runner->PostTask(CefCreateClosureTask(
1464 base::Bind(RequestServerHandler::SendResponse, server, connection_id,
1465 response, response_data)));
1466 return;
1467 }
1468
1469 const int response_code = response->GetStatus();
1470 if (response_code <= 0) {
1471 // Intentionally not responding for incomplete request tests.
1472 return;
1473 }
1474
1475 const CefString& content_type = response->GetMimeType();
1476 int64 content_length = static_cast<int64>(response_data.size());
1477
1478 CefResponse::HeaderMap extra_headers;
1479 response->GetHeaderMap(extra_headers);
1480
1481 server->SendHttpResponse(connection_id, response_code, content_type,
1482 content_length, extra_headers);
1483
1484 if (response_data == kIncompleteDoNotSendData) {
1485 // Intentionally not sending data for incomplete request tests.
1486 return;
1487 }
1488
1489 if (content_length != 0) {
1490 server->SendRawData(connection_id, response_data.data(),
1491 response_data.size());
1492 server->CloseConnection(connection_id);
1493 }
1494
1495 // The connection should be closed.
1496 EXPECT_FALSE(server->IsValidConnection(connection_id));
1497 }
1498
RunCompleteCallback(bool startup)1499 void RunCompleteCallback(bool startup) {
1500 EXPECT_UI_THREAD();
1501
1502 if (startup) {
1503 // Transfer DataMap ownership to the UI thread.
1504 data_map_.SetOwnerTaskRunner(CefTaskRunner::GetForCurrentThread());
1505 }
1506
1507 EXPECT_FALSE(complete_callback_.is_null());
1508 complete_callback_.Run();
1509 complete_callback_.Reset();
1510 }
1511
1512 RequestDataMap data_map_;
1513
1514 bool initialized_;
1515
1516 // Only accessed on the UI thread.
1517 base::Closure complete_callback_;
1518
1519 // After initialization the below members are only accessed on the server
1520 // thread.
1521
1522 TrackCallback got_initialized_;
1523 TrackCallback got_shutdown_;
1524
1525 typedef std::set<int> ConnectionIdSet;
1526 ConnectionIdSet connection_id_set_;
1527
1528 int expected_connection_ct_;
1529 int actual_connection_ct_;
1530 int expected_http_request_ct_;
1531 int actual_http_request_ct_;
1532
1533 std::string request_log_;
1534 };
1535
1536 // SHARED TEST RUNNER
1537
1538 // Executes the tests.
1539 class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
1540 public:
1541 typedef base::Callback<void(const base::Closure&)> TestCallback;
1542
RequestTestRunner(bool is_browser_process,bool is_server_backend,bool use_frame_method,bool run_in_browser_process,const base::Closure & incomplete_request_callback)1543 RequestTestRunner(bool is_browser_process,
1544 bool is_server_backend,
1545 bool use_frame_method,
1546 bool run_in_browser_process,
1547 const base::Closure& incomplete_request_callback)
1548 : is_browser_process_(is_browser_process),
1549 is_server_backend_(is_server_backend),
1550 use_frame_method_(use_frame_method),
1551 run_in_browser_process_(run_in_browser_process),
1552 incomplete_request_callback_(incomplete_request_callback) {
1553 owner_task_runner_ = CefTaskRunner::GetForCurrentThread();
1554 EXPECT_TRUE(owner_task_runner_.get());
1555 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
1556
1557 // Helper macro for registering test callbacks.
1558 #define REGISTER_TEST(test_mode, setup_method, run_method) \
1559 RegisterTest(test_mode, base::Bind(&RequestTestRunner::setup_method, this), \
1560 base::Bind(&RequestTestRunner::run_method, this));
1561
1562 // Register the test callbacks.
1563 REGISTER_TEST(REQTEST_GET, SetupGetTest, SingleRunTest);
1564 REGISTER_TEST(REQTEST_GET_NODATA, SetupGetNoDataTest, SingleRunTest);
1565 REGISTER_TEST(REQTEST_GET_PARTIAL_CONTENT, SetupGetPartialContentTest,
1566 SingleRunTest);
1567 REGISTER_TEST(REQTEST_GET_ALLOWCOOKIES, SetupGetAllowCookiesTest,
1568 SingleRunTest);
1569 REGISTER_TEST(REQTEST_GET_REDIRECT, SetupGetRedirectTest, SingleRunTest);
1570 REGISTER_TEST(REQTEST_GET_REDIRECT_STOP, SetupGetRedirectStopTest,
1571 SingleRunTest);
1572 REGISTER_TEST(REQTEST_GET_REDIRECT_LOCATION, SetupGetRedirectLocationTest,
1573 SingleRunTest);
1574 REGISTER_TEST(REQTEST_GET_REFERRER, SetupGetReferrerTest, SingleRunTest);
1575 REGISTER_TEST(REQTEST_GET_AUTH, SetupGetAuthTest, SingleRunTest);
1576 REGISTER_TEST(REQTEST_POST, SetupPostTest, SingleRunTest);
1577 REGISTER_TEST(REQTEST_POST_FILE, SetupPostFileTest, SingleRunTest);
1578 REGISTER_TEST(REQTEST_POST_WITHPROGRESS, SetupPostWithProgressTest,
1579 SingleRunTest);
1580 REGISTER_TEST(REQTEST_POST_REDIRECT, SetupPostRedirectTest, SingleRunTest);
1581 REGISTER_TEST(REQTEST_POST_REDIRECT_TOGET, SetupPostRedirectToGetTest,
1582 SingleRunTest);
1583 REGISTER_TEST(REQTEST_HEAD, SetupHeadTest, SingleRunTest);
1584 REGISTER_TEST(REQTEST_CACHE_WITH_CONTROL, SetupCacheWithControlTest,
1585 MultipleRunTest);
1586 REGISTER_TEST(REQTEST_CACHE_WITHOUT_CONTROL, SetupCacheWithoutControlTest,
1587 MultipleRunTest);
1588 REGISTER_TEST(REQTEST_CACHE_SKIP_FLAG, SetupCacheSkipFlagTest,
1589 MultipleRunTest);
1590 REGISTER_TEST(REQTEST_CACHE_SKIP_HEADER, SetupCacheSkipHeaderTest,
1591 MultipleRunTest);
1592 REGISTER_TEST(REQTEST_CACHE_ONLY_FAILURE_FLAG,
1593 SetupCacheOnlyFailureFlagTest, MultipleRunTest);
1594 REGISTER_TEST(REQTEST_CACHE_ONLY_FAILURE_HEADER,
1595 SetupCacheOnlyFailureHeaderTest, MultipleRunTest);
1596 REGISTER_TEST(REQTEST_CACHE_ONLY_SUCCESS_FLAG,
1597 SetupCacheOnlySuccessFlagTest, MultipleRunTest);
1598 REGISTER_TEST(REQTEST_CACHE_ONLY_SUCCESS_HEADER,
1599 SetupCacheOnlySuccessHeaderTest, MultipleRunTest);
1600 REGISTER_TEST(REQTEST_CACHE_DISABLE_FLAG, SetupCacheDisableFlagTest,
1601 MultipleRunTest);
1602 REGISTER_TEST(REQTEST_CACHE_DISABLE_HEADER, SetupCacheDisableHeaderTest,
1603 MultipleRunTest);
1604 REGISTER_TEST(REQTEST_INCOMPLETE_PROCESS_REQUEST,
1605 SetupIncompleteProcessRequestTest, SingleRunTest);
1606 REGISTER_TEST(REQTEST_INCOMPLETE_READ_RESPONSE,
1607 SetupIncompleteReadResponseTest, SingleRunTest);
1608 }
1609
Destroy()1610 void Destroy() {
1611 owner_task_runner_ = nullptr;
1612 request_context_ = nullptr;
1613 incomplete_request_callback_.Reset();
1614 }
1615
1616 // Called in the browser process to set the request context that will be used
1617 // when creating the URL request.
SetRequestContext(CefRefPtr<CefRequestContext> request_context)1618 void SetRequestContext(CefRefPtr<CefRequestContext> request_context) {
1619 request_context_ = request_context;
1620 }
GetRequestContext() const1621 CefRefPtr<CefRequestContext> GetRequestContext() const {
1622 return request_context_;
1623 }
1624
1625 // Called in both the browser and render process to setup the test.
SetupTest(RequestTestMode test_mode,const base::Closure & complete_callback)1626 void SetupTest(RequestTestMode test_mode,
1627 const base::Closure& complete_callback) {
1628 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
1629
1630 const base::Closure& safe_complete_callback = base::Bind(
1631 &RequestTestRunner::CompleteOnCorrectThread, this, complete_callback);
1632
1633 TestMap::const_iterator it = test_map_.find(test_mode);
1634 if (it != test_map_.end()) {
1635 it->second.setup.Run(base::Bind(&RequestTestRunner::SetupContinue, this,
1636 safe_complete_callback));
1637 } else {
1638 // Unknown test.
1639 ADD_FAILURE();
1640 complete_callback.Run();
1641 }
1642 }
1643
1644 // Called in either the browser or render process to run the test.
RunTest(RequestTestMode test_mode,CefRefPtr<CefFrame> frame,const base::Closure & complete_callback)1645 void RunTest(RequestTestMode test_mode,
1646 CefRefPtr<CefFrame> frame,
1647 const base::Closure& complete_callback) {
1648 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
1649
1650 frame_ = frame;
1651
1652 const base::Closure& safe_complete_callback = base::Bind(
1653 &RequestTestRunner::CompleteOnCorrectThread, this, complete_callback);
1654
1655 TestMap::const_iterator it = test_map_.find(test_mode);
1656 if (it != test_map_.end()) {
1657 it->second.run.Run(safe_complete_callback);
1658 } else {
1659 // Unknown test.
1660 ADD_FAILURE();
1661 complete_callback.Run();
1662 }
1663 }
1664
1665 // Called in both the browser and render process to shut down the test.
ShutdownTest(const base::Closure & complete_callback)1666 void ShutdownTest(const base::Closure& complete_callback) {
1667 EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
1668
1669 const base::Closure& safe_complete_callback = base::Bind(
1670 &RequestTestRunner::CompleteOnCorrectThread, this, complete_callback);
1671
1672 if (!post_file_tmpdir_.IsEmpty()) {
1673 EXPECT_TRUE(is_browser_process_);
1674 CefPostTask(TID_FILE_USER_VISIBLE,
1675 base::Bind(&RequestTestRunner::RunDeleteTempDirectory, this,
1676 safe_complete_callback));
1677 return;
1678 }
1679
1680 // Continue with test shutdown.
1681 RunShutdown(safe_complete_callback);
1682 }
1683
1684 private:
1685 // Continued after |settings_| is populated for the test.
SetupContinue(const base::Closure & complete_callback)1686 void SetupContinue(const base::Closure& complete_callback) {
1687 if (!owner_task_runner_->BelongsToCurrentThread()) {
1688 owner_task_runner_->PostTask(CefCreateClosureTask(base::Bind(
1689 &RequestTestRunner::SetupContinue, this, complete_callback)));
1690 return;
1691 }
1692
1693 if (is_browser_process_) {
1694 SetupTestBackend(complete_callback);
1695 } else {
1696 complete_callback.Run();
1697 }
1698 }
1699
GetTestPath(const std::string & name)1700 std::string GetTestPath(const std::string& name) {
1701 return std::string(run_in_browser_process_ ? "/Browser" : "/Renderer") +
1702 name;
1703 }
1704
GetTestURL(const std::string & name)1705 std::string GetTestURL(const std::string& name) {
1706 // Avoid name duplication between tests running in different processes.
1707 // Otherwise we'll get unexpected state leakage (cache hits) when running
1708 // multiple tests.
1709 return GetRequestOrigin(is_server_backend_) + GetTestPath(name);
1710 }
1711
SetupGetTestShared()1712 void SetupGetTestShared() {
1713 settings_.request = CefRequest::Create();
1714 settings_.request->SetURL(GetTestURL("GetTest.html"));
1715 settings_.request->SetMethod("GET");
1716
1717 settings_.response = CefResponse::Create();
1718 settings_.response->SetMimeType("text/html");
1719 settings_.response->SetStatus(200);
1720 settings_.response->SetStatusText("OK");
1721
1722 settings_.response_data = "GET TEST SUCCESS";
1723 }
1724
SetupGetTest(const base::Closure & complete_callback)1725 void SetupGetTest(const base::Closure& complete_callback) {
1726 SetupGetTestShared();
1727 complete_callback.Run();
1728 }
1729
SetupGetNoDataTest(const base::Closure & complete_callback)1730 void SetupGetNoDataTest(const base::Closure& complete_callback) {
1731 // Start with the normal get test.
1732 SetupGetTestShared();
1733
1734 // Disable download data notifications.
1735 settings_.request->SetFlags(UR_FLAG_NO_DOWNLOAD_DATA);
1736
1737 settings_.expect_download_data = false;
1738
1739 complete_callback.Run();
1740 }
1741
SetupGetPartialContentTest(const base::Closure & complete_callback)1742 void SetupGetPartialContentTest(const base::Closure& complete_callback) {
1743 // Start with the normal get test.
1744 SetupGetTestShared();
1745
1746 // Skip first 4 bytes of content and expect to receive the rest
1747 settings_.request->SetHeaderByName("Range", "bytes=4-", true);
1748 settings_.response->SetHeaderByName("Content-Range", "bytes 4-8/8", true);
1749 settings_.response->SetStatus(206);
1750 settings_.response->SetStatusText("Partial Content");
1751 settings_.expected_download_offset = 4;
1752
1753 complete_callback.Run();
1754 }
1755
SetupGetAllowCookiesTest(const base::Closure & complete_callback)1756 void SetupGetAllowCookiesTest(const base::Closure& complete_callback) {
1757 // Start with the normal get test.
1758 SetupGetTestShared();
1759
1760 // Send cookies.
1761 settings_.request->SetFlags(UR_FLAG_ALLOW_STORED_CREDENTIALS);
1762
1763 settings_.expect_save_cookie = true;
1764 settings_.expect_send_cookie = true;
1765
1766 complete_callback.Run();
1767 }
1768
SetupGetRedirectTest(const base::Closure & complete_callback)1769 void SetupGetRedirectTest(const base::Closure& complete_callback) {
1770 // Start with the normal get test.
1771 SetupGetTestShared();
1772
1773 // Add a redirect request.
1774 settings_.redirect_request = CefRequest::Create();
1775 settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
1776 settings_.redirect_request->SetMethod("GET");
1777
1778 settings_.redirect_response = CefResponse::Create();
1779 settings_.redirect_response->SetMimeType("text/html");
1780 settings_.redirect_response->SetStatus(302);
1781 settings_.redirect_response->SetStatusText("Found");
1782
1783 CefResponse::HeaderMap headerMap;
1784 headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
1785 settings_.redirect_response->SetHeaderMap(headerMap);
1786
1787 complete_callback.Run();
1788 }
1789
SetupGetRedirectStopTest(const base::Closure & complete_callback)1790 void SetupGetRedirectStopTest(const base::Closure& complete_callback) {
1791 settings_.request = CefRequest::Create();
1792 settings_.request->SetURL(GetTestURL("GetTest.html"));
1793 settings_.request->SetMethod("GET");
1794
1795 // With the test server only the status is expected
1796 // on stop redirects.
1797 settings_.response = CefResponse::Create();
1798 settings_.response->SetStatus(302);
1799 if (is_browser_process_) {
1800 settings_.response->SetStatusText("Found");
1801 }
1802
1803 // Add a redirect request.
1804 settings_.redirect_request = CefRequest::Create();
1805 settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
1806 settings_.redirect_request->SetMethod("GET");
1807 settings_.redirect_request->SetFlags(UR_FLAG_STOP_ON_REDIRECT);
1808
1809 settings_.redirect_response = CefResponse::Create();
1810 settings_.redirect_response->SetMimeType("text/html");
1811 settings_.redirect_response->SetStatus(302);
1812 settings_.redirect_response->SetStatusText("Found");
1813
1814 CefResponse::HeaderMap headerMap;
1815 headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
1816 settings_.redirect_response->SetHeaderMap(headerMap);
1817
1818 settings_.expected_status = UR_CANCELED;
1819 settings_.expected_error_code = ERR_ABORTED;
1820 settings_.expect_download_data = false;
1821 settings_.expect_download_progress = false;
1822 settings_.expected_send_count = 1;
1823 settings_.expected_receive_count = 1;
1824
1825 complete_callback.Run();
1826 }
1827
SetupGetRedirectLocationTest(const base::Closure & complete_callback)1828 void SetupGetRedirectLocationTest(const base::Closure& complete_callback) {
1829 // Start with the normal get test.
1830 SetupGetTestShared();
1831
1832 // Add a redirect request.
1833 settings_.redirect_request = CefRequest::Create();
1834 settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
1835 settings_.redirect_request->SetMethod("GET");
1836
1837 settings_.redirect_response = CefResponse::Create();
1838 settings_.redirect_response->SetMimeType("text/html");
1839 settings_.redirect_response->SetStatus(302);
1840 settings_.redirect_response->SetStatusText("Found");
1841
1842 CefResponse::HeaderMap headerMap;
1843 headerMap.insert(std::make_pair("LoCaTioN", GetTestPath("GetTest.html")));
1844 settings_.redirect_response->SetHeaderMap(headerMap);
1845
1846 complete_callback.Run();
1847 }
1848
SetupGetReferrerTest(const base::Closure & complete_callback)1849 void SetupGetReferrerTest(const base::Closure& complete_callback) {
1850 settings_.request = CefRequest::Create();
1851 settings_.request->SetURL(GetTestURL("GetTest.html"));
1852 settings_.request->SetMethod("GET");
1853
1854 // The referrer URL must be HTTP or HTTPS. This is enforced by
1855 // GURL::GetAsReferrer() called from URLRequest::SetReferrer().
1856 settings_.request->SetReferrer("http://tests.com/referrer.html",
1857 REFERRER_POLICY_DEFAULT);
1858
1859 settings_.response = CefResponse::Create();
1860 settings_.response->SetMimeType("text/html");
1861 settings_.response->SetStatus(200);
1862 settings_.response->SetStatusText("OK");
1863
1864 settings_.response_data = "GET TEST SUCCESS";
1865
1866 complete_callback.Run();
1867 }
1868
SetupGetAuthTest(const base::Closure & complete_callback)1869 void SetupGetAuthTest(const base::Closure& complete_callback) {
1870 // Start with the normal get test.
1871 SetupGetTestShared();
1872
1873 // Require Basic authentication.
1874 settings_.expect_authentication = true;
1875 settings_.username = "user";
1876 settings_.password = "pass";
1877
1878 // This flag is required to support credentials, which means we'll also get
1879 // the cookies.
1880 settings_.request->SetFlags(UR_FLAG_ALLOW_STORED_CREDENTIALS);
1881 settings_.expect_save_cookie = true;
1882 settings_.expect_send_cookie = true;
1883
1884 // The authentication request will come first, then the actual request.
1885 settings_.expected_receive_count = 2;
1886 settings_.expected_send_count = 2;
1887
1888 complete_callback.Run();
1889 }
1890
SetupPostTestShared()1891 void SetupPostTestShared() {
1892 settings_.request = CefRequest::Create();
1893 settings_.request->SetURL(GetTestURL("PostTest.html"));
1894 settings_.request->SetMethod("POST");
1895 SetUploadData(settings_.request, "the_post_data");
1896
1897 settings_.response = CefResponse::Create();
1898 settings_.response->SetMimeType("text/html");
1899 settings_.response->SetStatus(200);
1900 settings_.response->SetStatusText("OK");
1901
1902 settings_.response_data = "POST TEST SUCCESS";
1903 }
1904
SetupPostTest(const base::Closure & complete_callback)1905 void SetupPostTest(const base::Closure& complete_callback) {
1906 SetupPostTestShared();
1907 complete_callback.Run();
1908 }
1909
SetupPostFileTest(const base::Closure & complete_callback)1910 void SetupPostFileTest(const base::Closure& complete_callback) {
1911 // This test is only supported in the browser process.
1912 EXPECT_TRUE(is_browser_process_);
1913
1914 settings_.request = CefRequest::Create();
1915 settings_.request->SetURL(GetTestURL("PostFileTest.html"));
1916 settings_.request->SetMethod("POST");
1917
1918 settings_.response = CefResponse::Create();
1919 settings_.response->SetMimeType("text/html");
1920 settings_.response->SetStatus(200);
1921 settings_.response->SetStatusText("OK");
1922
1923 settings_.response_data = "POST TEST SUCCESS";
1924
1925 CefPostTask(TID_FILE_USER_VISIBLE,
1926 base::Bind(&RequestTestRunner::SetupPostFileTestContinue, this,
1927 complete_callback));
1928 }
1929
SetupPostFileTestContinue(const base::Closure & complete_callback)1930 void SetupPostFileTestContinue(const base::Closure& complete_callback) {
1931 EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
1932
1933 EXPECT_TRUE(post_file_tmpdir_.CreateUniqueTempDir());
1934 const std::string& path =
1935 client::file_util::JoinPath(post_file_tmpdir_.GetPath(), "example.txt");
1936 const char content[] = "HELLO FRIEND!";
1937 int write_ct =
1938 client::file_util::WriteFile(path, content, sizeof(content) - 1);
1939 EXPECT_EQ(static_cast<int>(sizeof(content) - 1), write_ct);
1940 SetUploadFile(settings_.request, path);
1941
1942 complete_callback.Run();
1943 }
1944
SetupPostWithProgressTest(const base::Closure & complete_callback)1945 void SetupPostWithProgressTest(const base::Closure& complete_callback) {
1946 // Start with the normal post test.
1947 SetupPostTestShared();
1948
1949 // Enable upload progress notifications.
1950 settings_.request->SetFlags(UR_FLAG_REPORT_UPLOAD_PROGRESS);
1951
1952 settings_.expect_upload_progress = true;
1953
1954 complete_callback.Run();
1955 }
1956
SetupPostRedirectTest(const base::Closure & complete_callback)1957 void SetupPostRedirectTest(const base::Closure& complete_callback) {
1958 // Start with the normal post test.
1959 SetupPostTestShared();
1960
1961 // Add a redirect request.
1962 settings_.redirect_request = CefRequest::Create();
1963 settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
1964 settings_.redirect_request->SetMethod("POST");
1965 SetUploadData(settings_.redirect_request, "the_post_data");
1966
1967 settings_.redirect_response = CefResponse::Create();
1968 settings_.redirect_response->SetMimeType("text/html");
1969 // Only 307 is supported for redirecting the same method and post data.
1970 settings_.redirect_response->SetStatus(307);
1971 settings_.redirect_response->SetStatusText("Found");
1972
1973 CefResponse::HeaderMap headerMap;
1974 headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
1975 settings_.redirect_response->SetHeaderMap(headerMap);
1976
1977 complete_callback.Run();
1978 }
1979
SetupPostRedirectToGetTest(const base::Closure & complete_callback)1980 void SetupPostRedirectToGetTest(const base::Closure& complete_callback) {
1981 // Start with the normal post test.
1982 SetupPostTestShared();
1983
1984 // The expected result after redirect is a GET request without POST data.
1985 settings_.request = CefRequest::Create();
1986 settings_.request->SetURL(GetTestURL("PostTest.html"));
1987 settings_.request->SetMethod("GET");
1988
1989 // Add a redirect request.
1990 settings_.redirect_request = CefRequest::Create();
1991 settings_.redirect_request->SetURL(GetTestURL("redirect.html"));
1992 settings_.redirect_request->SetMethod("POST");
1993 SetUploadData(settings_.redirect_request, "the_post_data");
1994
1995 settings_.redirect_response = CefResponse::Create();
1996 settings_.redirect_response->SetMimeType("text/html");
1997 // Redirect codes other than 307 will cause conversion to GET and removal
1998 // of POST data.
1999 settings_.redirect_response->SetStatus(302);
2000 settings_.redirect_response->SetStatusText("Found");
2001
2002 CefResponse::HeaderMap headerMap;
2003 headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
2004 settings_.redirect_response->SetHeaderMap(headerMap);
2005
2006 complete_callback.Run();
2007 }
2008
SetupHeadTest(const base::Closure & complete_callback)2009 void SetupHeadTest(const base::Closure& complete_callback) {
2010 settings_.request = CefRequest::Create();
2011 settings_.request->SetURL(GetTestURL("HeadTest.html"));
2012 settings_.request->SetMethod("HEAD");
2013
2014 settings_.response = CefResponse::Create();
2015 settings_.response->SetMimeType("text/html");
2016 settings_.response->SetStatus(200);
2017 settings_.response->SetStatusText("OK");
2018
2019 // The backend will disregard this value when it returns the result.
2020 settings_.response_data = "HEAD TEST SUCCESS";
2021
2022 settings_.expect_download_progress = false;
2023 settings_.expect_download_data = false;
2024
2025 complete_callback.Run();
2026 }
2027
SetupCacheShared(const std::string & name,bool with_cache_control)2028 void SetupCacheShared(const std::string& name, bool with_cache_control) {
2029 // Start with the normal get test.
2030 SetupGetTestShared();
2031
2032 // Specify a unique URL.
2033 settings_.request->SetURL(GetTestURL(name));
2034
2035 if (with_cache_control) {
2036 // Allow the page to be cached for 10 seconds.
2037 CefResponse::HeaderMap headerMap;
2038 headerMap.insert(std::make_pair(kCacheControlHeader, "max-age=10"));
2039 settings_.response->SetHeaderMap(headerMap);
2040 }
2041 }
2042
SetupCacheWithControlTest(const base::Closure & complete_callback)2043 void SetupCacheWithControlTest(const base::Closure& complete_callback) {
2044 SetupCacheShared("CacheWithControlTest.html", true);
2045
2046 // Send multiple requests. With the Cache-Control response header the 2nd+
2047 // should receive cached data.
2048 settings_.expected_send_count = 3;
2049 settings_.expected_receive_count = 1;
2050 settings_.setup_next_request =
2051 base::Bind(&RequestTestRunner::SetupCacheWithControlTestNext, this);
2052
2053 complete_callback.Run();
2054 }
2055
SetupCacheWithControlTestNext(int next_send_count,const base::Closure & complete_callback)2056 void SetupCacheWithControlTestNext(int next_send_count,
2057 const base::Closure& complete_callback) {
2058 // Only handle from the cache.
2059 settings_.expect_response_was_cached = true;
2060
2061 // The following requests will use the same setup, so no more callbacks
2062 // are required.
2063 settings_.setup_next_request.Reset();
2064
2065 complete_callback.Run();
2066 }
2067
SetupCacheWithoutControlTest(const base::Closure & complete_callback)2068 void SetupCacheWithoutControlTest(const base::Closure& complete_callback) {
2069 SetupCacheShared("CacheWithoutControlTest.html", false);
2070
2071 // Send multiple requests. Without the Cache-Control response header all
2072 // should be received.
2073 settings_.expected_send_count = 3;
2074 settings_.expected_receive_count = 3;
2075
2076 complete_callback.Run();
2077 }
2078
SetupCacheSkipFlagTest(const base::Closure & complete_callback)2079 void SetupCacheSkipFlagTest(const base::Closure& complete_callback) {
2080 SetupCacheShared("CacheSkipFlagTest.html", true);
2081
2082 // Skip the cache despite the the Cache-Control response header.
2083 // This will not read from the cache, but still write to the cache.
2084 settings_.request->SetFlags(UR_FLAG_SKIP_CACHE);
2085
2086 // Send multiple requests. The 1st request will be handled normally,
2087 // but not result in any reads from the cache. The 2nd request will
2088 // expect a cached response and the 3nd request will skip the cache
2089 // again.
2090 settings_.expected_send_count = 3;
2091 settings_.expected_receive_count = 2;
2092 settings_.setup_next_request =
2093 base::Bind(&RequestTestRunner::SetupCacheSkipFlagTestNext, this);
2094
2095 complete_callback.Run();
2096 }
2097
SetupCacheSkipFlagTestNext(int next_send_count,const base::Closure & complete_callback)2098 void SetupCacheSkipFlagTestNext(int next_send_count,
2099 const base::Closure& complete_callback) {
2100 // Recreate the request object because the existing object will now be
2101 // read-only.
2102 EXPECT_TRUE(settings_.request->IsReadOnly());
2103 SetupCacheShared("CacheSkipFlagTest.html", true);
2104
2105 // Expect a cached response.
2106 settings_.expect_response_was_cached = true;
2107 settings_.setup_next_request =
2108 base::Bind(&RequestTestRunner::SetupCacheSkipFlagTestLast, this);
2109
2110 complete_callback.Run();
2111 }
2112
SetupCacheSkipFlagTestLast(int next_send_count,const base::Closure & complete_callback)2113 void SetupCacheSkipFlagTestLast(int next_send_count,
2114 const base::Closure& complete_callback) {
2115 // Recreate the request object because the existing object will now be
2116 // read-only.
2117 EXPECT_TRUE(settings_.request->IsReadOnly());
2118 SetupCacheShared("CacheSkipFlagTest.html", true);
2119
2120 // Skip the cache despite the the Cache-Control response header.
2121 settings_.request->SetFlags(UR_FLAG_SKIP_CACHE);
2122
2123 // Expect the cache to be skipped.
2124 settings_.expect_response_was_cached = false;
2125 settings_.setup_next_request.Reset();
2126
2127 complete_callback.Run();
2128 }
2129
SetupCacheSkipHeaderTest(const base::Closure & complete_callback)2130 void SetupCacheSkipHeaderTest(const base::Closure& complete_callback) {
2131 SetupCacheShared("CacheSkipHeaderTest.html", true);
2132
2133 // Skip the cache despite the the Cache-Control response header.
2134 // This will not read from the cache, but still write to the cache.
2135 CefRequest::HeaderMap headerMap;
2136 headerMap.insert(std::make_pair(kCacheControlHeader, "no-cache"));
2137 settings_.request->SetHeaderMap(headerMap);
2138
2139 // Send multiple requests. The 1st request will be handled normally,
2140 // but not result in any reads from the cache. The 2nd request will
2141 // expect a cached response and the 3nd request will skip the cache
2142 // again.
2143 settings_.expected_send_count = 3;
2144 settings_.expected_receive_count = 2;
2145 settings_.setup_next_request =
2146 base::Bind(&RequestTestRunner::SetupCacheSkipHeaderTestNext, this);
2147
2148 complete_callback.Run();
2149 }
2150
SetupCacheSkipHeaderTestNext(int next_send_count,const base::Closure & complete_callback)2151 void SetupCacheSkipHeaderTestNext(int next_send_count,
2152 const base::Closure& complete_callback) {
2153 // Recreate the request object because the existing object will now be
2154 // read-only.
2155 EXPECT_TRUE(settings_.request->IsReadOnly());
2156 SetupCacheShared("CacheSkipHeaderTest.html", true);
2157
2158 // Expect a cached response.
2159 settings_.expect_response_was_cached = true;
2160 settings_.setup_next_request =
2161 base::Bind(&RequestTestRunner::SetupCacheSkipHeaderTestLast, this);
2162
2163 complete_callback.Run();
2164 }
2165
SetupCacheSkipHeaderTestLast(int next_send_count,const base::Closure & complete_callback)2166 void SetupCacheSkipHeaderTestLast(int next_send_count,
2167 const base::Closure& complete_callback) {
2168 // Recreate the request object because the existing object will now be
2169 // read-only.
2170 EXPECT_TRUE(settings_.request->IsReadOnly());
2171 SetupCacheShared("CacheSkipHeaderTest.html", true);
2172
2173 // Skip the cache despite the the Cache-Control response header.
2174 settings_.request->SetFlags(UR_FLAG_SKIP_CACHE);
2175
2176 // Expect the cache to be skipped.
2177 settings_.expect_response_was_cached = false;
2178 settings_.setup_next_request.Reset();
2179
2180 complete_callback.Run();
2181 }
2182
SetupCacheOnlyFailureFlagTest(const base::Closure & complete_callback)2183 void SetupCacheOnlyFailureFlagTest(const base::Closure& complete_callback) {
2184 SetupCacheShared("CacheOnlyFailureFlagTest.html", true);
2185
2186 // Only handle from the cache.
2187 settings_.request->SetFlags(UR_FLAG_ONLY_FROM_CACHE);
2188
2189 // Send multiple requests. All should fail because there's no entry in the
2190 // cache currently.
2191 settings_.expected_send_count = 3;
2192 settings_.expected_receive_count = 0;
2193
2194 // The request is expected to fail.
2195 settings_.SetRequestFailureExpected(ERR_CACHE_MISS);
2196
2197 complete_callback.Run();
2198 }
2199
SetupCacheOnlyFailureHeaderTest(const base::Closure & complete_callback)2200 void SetupCacheOnlyFailureHeaderTest(const base::Closure& complete_callback) {
2201 SetupCacheShared("CacheOnlyFailureFlagTest.html", true);
2202
2203 // Only handle from the cache.
2204 CefRequest::HeaderMap headerMap;
2205 headerMap.insert(std::make_pair(kCacheControlHeader, "only-if-cached"));
2206 settings_.request->SetHeaderMap(headerMap);
2207
2208 // Send multiple requests. All should fail because there's no entry in the
2209 // cache currently.
2210 settings_.expected_send_count = 3;
2211 settings_.expected_receive_count = 0;
2212
2213 // The request is expected to fail.
2214 settings_.SetRequestFailureExpected(ERR_CACHE_MISS);
2215
2216 complete_callback.Run();
2217 }
2218
SetupCacheOnlySuccessFlagTest(const base::Closure & complete_callback)2219 void SetupCacheOnlySuccessFlagTest(const base::Closure& complete_callback) {
2220 SetupCacheShared("CacheOnlySuccessFlagTest.html", false);
2221
2222 // Send multiple requests. The 1st request will be handled normally. The
2223 // 2nd+ requests will be configured by SetupCacheOnlySuccessFlagNext to
2224 // require cached data.
2225 settings_.expected_send_count = 3;
2226 settings_.expected_receive_count = 1;
2227 settings_.setup_next_request =
2228 base::Bind(&RequestTestRunner::SetupCacheOnlySuccessFlagNext, this);
2229
2230 complete_callback.Run();
2231 }
2232
SetupCacheOnlySuccessFlagNext(int next_send_count,const base::Closure & complete_callback)2233 void SetupCacheOnlySuccessFlagNext(int next_send_count,
2234 const base::Closure& complete_callback) {
2235 // Recreate the request object because the existing object will now be
2236 // read-only.
2237 EXPECT_TRUE(settings_.request->IsReadOnly());
2238 SetupCacheShared("CacheOnlySuccessFlagTest.html", false);
2239
2240 // Only handle from the cache.
2241 settings_.request->SetFlags(UR_FLAG_ONLY_FROM_CACHE);
2242 settings_.expect_response_was_cached = true;
2243
2244 // The following requests will use the same setup, so no more callbacks
2245 // are required.
2246 settings_.setup_next_request.Reset();
2247
2248 complete_callback.Run();
2249 }
2250
SetupCacheOnlySuccessHeaderTest(const base::Closure & complete_callback)2251 void SetupCacheOnlySuccessHeaderTest(const base::Closure& complete_callback) {
2252 SetupCacheShared("CacheOnlySuccessHeaderTest.html", false);
2253
2254 // Send multiple requests. The 1st request will be handled normally. The
2255 // 2nd+ requests will be configured by SetupCacheOnlySuccessHeaderNext to
2256 // require cached data.
2257 settings_.expected_send_count = 3;
2258 settings_.expected_receive_count = 1;
2259 settings_.setup_next_request =
2260 base::Bind(&RequestTestRunner::SetupCacheOnlySuccessHeaderNext, this);
2261
2262 complete_callback.Run();
2263 }
2264
SetupCacheOnlySuccessHeaderNext(int next_send_count,const base::Closure & complete_callback)2265 void SetupCacheOnlySuccessHeaderNext(int next_send_count,
2266 const base::Closure& complete_callback) {
2267 // Recreate the request object because the existing object will now be
2268 // read-only.
2269 EXPECT_TRUE(settings_.request->IsReadOnly());
2270 SetupCacheShared("CacheOnlySuccessHeaderTest.html", false);
2271
2272 // Only handle from the cache.
2273 CefRequest::HeaderMap headerMap;
2274 headerMap.insert(std::make_pair(kCacheControlHeader, "only-if-cached"));
2275 settings_.request->SetHeaderMap(headerMap);
2276 settings_.expect_response_was_cached = true;
2277
2278 // The following requests will use the same setup, so no more callbacks
2279 // are required.
2280 settings_.setup_next_request.Reset();
2281
2282 complete_callback.Run();
2283 }
2284
SetupCacheDisableFlagTest(const base::Closure & complete_callback)2285 void SetupCacheDisableFlagTest(const base::Closure& complete_callback) {
2286 SetupCacheShared("CacheDisableFlagTest.html", true);
2287
2288 // Disable the cache despite the the Cache-Control response header.
2289 settings_.request->SetFlags(UR_FLAG_DISABLE_CACHE);
2290
2291 // Send multiple requests. The 1st request will be handled normally,
2292 // but not result in any reads from or writes to the cache.
2293 // Therefore all following requests that are set to be only handled
2294 // from the cache should fail.
2295 settings_.expected_send_count = 3;
2296 settings_.expected_receive_count = 1;
2297 settings_.setup_next_request =
2298 base::Bind(&RequestTestRunner::SetupCacheDisableFlagTestNext, this);
2299
2300 complete_callback.Run();
2301 }
2302
SetupCacheDisableFlagTestNext(int next_send_count,const base::Closure & complete_callback)2303 void SetupCacheDisableFlagTestNext(int next_send_count,
2304 const base::Closure& complete_callback) {
2305 // Recreate the request object because the existing object will now be
2306 // read-only.
2307 EXPECT_TRUE(settings_.request->IsReadOnly());
2308 SetupCacheShared("CacheDisableFlagTest.html", true);
2309
2310 // Only handle from the cache.
2311 settings_.request->SetFlags(UR_FLAG_ONLY_FROM_CACHE);
2312
2313 // The request is expected to fail.
2314 settings_.SetRequestFailureExpected(ERR_CACHE_MISS);
2315
2316 // The following requests will use the same setup, so no more callbacks
2317 // are required.
2318 settings_.setup_next_request.Reset();
2319
2320 complete_callback.Run();
2321 }
2322
SetupCacheDisableHeaderTest(const base::Closure & complete_callback)2323 void SetupCacheDisableHeaderTest(const base::Closure& complete_callback) {
2324 SetupCacheShared("CacheDisableHeaderTest.html", true);
2325
2326 // Disable the cache despite the the Cache-Control response header.
2327 CefRequest::HeaderMap headerMap;
2328 headerMap.insert(std::make_pair(kCacheControlHeader, "no-store"));
2329 settings_.request->SetHeaderMap(headerMap);
2330
2331 // Send multiple requests. The 1st request will be handled normally,
2332 // but not result in any reads from or writes to the cache.
2333 // Therefore all following requests that are set to be only handled
2334 // from the cache should fail.
2335 settings_.expected_send_count = 3;
2336 settings_.expected_receive_count = 1;
2337 settings_.setup_next_request =
2338 base::Bind(&RequestTestRunner::SetupCacheDisableHeaderTestNext, this);
2339
2340 complete_callback.Run();
2341 }
2342
SetupCacheDisableHeaderTestNext(int next_send_count,const base::Closure & complete_callback)2343 void SetupCacheDisableHeaderTestNext(int next_send_count,
2344 const base::Closure& complete_callback) {
2345 // Recreate the request object because the existing object will now be
2346 // read-only.
2347 EXPECT_TRUE(settings_.request->IsReadOnly());
2348 SetupCacheShared("CacheDisableHeaderTest.html", true);
2349
2350 // Only handle from the cache.
2351 CefRequest::HeaderMap headerMap;
2352 headerMap.insert(std::make_pair(kCacheControlHeader, "only-if-cached"));
2353 settings_.request->SetHeaderMap(headerMap);
2354
2355 // The request is expected to fail.
2356 settings_.SetRequestFailureExpected(ERR_CACHE_MISS);
2357
2358 // The following requests will use the same setup, so no more callbacks
2359 // are required.
2360 settings_.setup_next_request.Reset();
2361
2362 complete_callback.Run();
2363 }
2364
SetupIncompleteProcessRequestTest(const base::Closure & complete_callback)2365 void SetupIncompleteProcessRequestTest(
2366 const base::Closure& complete_callback) {
2367 // Start with the normal get test.
2368 SetupGetTestShared();
2369
2370 settings_.incomplete_type = RequestRunSettings::INCOMPLETE_PROCESS_REQUEST;
2371
2372 // There will be no response and the request will be aborted.
2373 settings_.response = CefResponse::Create();
2374 settings_.response_data.clear();
2375 settings_.expected_error_code = ERR_ABORTED;
2376 settings_.expected_status = UR_FAILED;
2377 settings_.expect_download_progress = false;
2378 settings_.expect_download_data = false;
2379
2380 complete_callback.Run();
2381 }
2382
SetupIncompleteReadResponseTest(const base::Closure & complete_callback)2383 void SetupIncompleteReadResponseTest(const base::Closure& complete_callback) {
2384 // Start with the normal get test.
2385 SetupGetTestShared();
2386
2387 settings_.incomplete_type = RequestRunSettings::INCOMPLETE_READ_RESPONSE;
2388
2389 // There will be a response but the request will be aborted without
2390 // receiving any data.
2391 settings_.response_data = kIncompleteDoNotSendData;
2392 settings_.expected_error_code = ERR_ABORTED;
2393 settings_.expected_status = UR_FAILED;
2394 // TODO(network): Download progress notifications are sent for incomplete
2395 // (with no data sent) requests in the browser process but not the renderer
2396 // process. Consider standardizing this behavior.
2397 settings_.expect_download_progress = is_browser_process_;
2398 settings_.expect_download_data = false;
2399
2400 complete_callback.Run();
2401 }
2402
2403 // Send a request. |complete_callback| will be executed on request completion.
SendRequest(const test_request::RequestDoneCallback & done_callback)2404 void SendRequest(const test_request::RequestDoneCallback& done_callback) {
2405 if (!is_browser_process_) {
2406 // Render process requests must use CefFrame::CreateURLRequest.
2407 EXPECT_TRUE(use_frame_method_);
2408 }
2409
2410 test_request::SendConfig config;
2411
2412 if (settings_.redirect_request)
2413 config.request_ = settings_.redirect_request;
2414 else
2415 config.request_ = settings_.request;
2416 EXPECT_TRUE(config.request_.get());
2417
2418 // Not delegating to CefRequestHandler::GetAuthCredentials.
2419 if (!use_frame_method_ && settings_.expect_authentication) {
2420 config.has_credentials_ = true;
2421 config.username_ = settings_.username;
2422 config.password_ = settings_.password;
2423 }
2424
2425 if (use_frame_method_) {
2426 EXPECT_TRUE(frame_);
2427 config.frame_ = frame_;
2428 } else {
2429 config.request_context_ = request_context_;
2430 }
2431
2432 test_request::Send(config, done_callback);
2433
2434 if (settings_.incomplete_type != RequestRunSettings::INCOMPLETE_NONE) {
2435 incomplete_request_callback_.Run();
2436 incomplete_request_callback_.Reset();
2437 }
2438 }
2439
2440 // Verify a response.
VerifyResponse(const test_request::State * const client)2441 void VerifyResponse(const test_request::State* const client) {
2442 CefRefPtr<CefRequest> expected_request;
2443 CefRefPtr<CefResponse> expected_response;
2444
2445 if (settings_.redirect_request)
2446 expected_request = settings_.redirect_request;
2447 else
2448 expected_request = settings_.request;
2449
2450 if (settings_.redirect_response && !settings_.expect_follow_redirect) {
2451 // A redirect response was sent but the redirect is not expected to be
2452 // followed.
2453 expected_response = settings_.redirect_response;
2454 } else {
2455 expected_response = settings_.response;
2456 }
2457
2458 TestRequestEqual(expected_request, client->request_, false);
2459
2460 EXPECT_EQ(settings_.expected_status, client->status_);
2461 EXPECT_EQ(settings_.expected_error_code, client->error_code_);
2462 if (expected_response && client->response_)
2463 TestResponseEqual(expected_response, client->response_, true);
2464
2465 EXPECT_EQ(settings_.expect_response_was_cached,
2466 client->response_was_cached_);
2467
2468 EXPECT_EQ(1, client->request_complete_ct_);
2469
2470 if (settings_.expect_upload_progress) {
2471 EXPECT_LE(1, client->upload_progress_ct_);
2472
2473 std::string upload_data;
2474 GetUploadData(expected_request, upload_data);
2475 EXPECT_EQ((int64)upload_data.size(), client->upload_total_);
2476 } else {
2477 EXPECT_EQ(0, client->upload_progress_ct_);
2478 EXPECT_EQ(0, client->upload_total_);
2479 }
2480
2481 if (settings_.expect_download_progress) {
2482 EXPECT_LE(1, client->download_progress_ct_);
2483 EXPECT_EQ((int64)(settings_.response_data.size() -
2484 settings_.expected_download_offset),
2485 client->download_total_);
2486 } else {
2487 EXPECT_EQ(0, client->download_progress_ct_);
2488 EXPECT_EQ(0, client->download_total_);
2489 }
2490
2491 if (settings_.expect_download_data) {
2492 size_t expected_offset = settings_.expected_download_offset;
2493 EXPECT_LE(1, client->download_data_ct_);
2494 EXPECT_STREQ(settings_.response_data.substr(expected_offset).c_str(),
2495 client->download_data_.c_str());
2496 } else {
2497 EXPECT_EQ(0, client->download_data_ct_);
2498 EXPECT_TRUE(client->download_data_.empty());
2499 }
2500
2501 if (settings_.expect_authentication) {
2502 EXPECT_EQ(1, client->auth_credentials_ct_);
2503 } else {
2504 EXPECT_EQ(0, client->auth_credentials_ct_);
2505 }
2506 }
2507
2508 // Run a test with a single request.
SingleRunTest(const base::Closure & complete_callback)2509 void SingleRunTest(const base::Closure& complete_callback) {
2510 SendRequest(base::Bind(&RequestTestRunner::SingleRunTestComplete, this,
2511 complete_callback));
2512 }
2513
SingleRunTestComplete(const base::Closure & complete_callback,const test_request::State & completed_client)2514 void SingleRunTestComplete(const base::Closure& complete_callback,
2515 const test_request::State& completed_client) {
2516 VerifyResponse(&completed_client);
2517 complete_callback.Run();
2518 }
2519
2520 // Run a test with multiple requests.
MultipleRunTest(const base::Closure & complete_callback)2521 void MultipleRunTest(const base::Closure& complete_callback) {
2522 EXPECT_GT(settings_.expected_send_count, 0);
2523 EXPECT_GE(settings_.expected_receive_count, 0);
2524 MultipleRunTestContinue(complete_callback, 1);
2525 }
2526
MultipleRunTestContinue(const base::Closure & complete_callback,int send_count)2527 void MultipleRunTestContinue(const base::Closure& complete_callback,
2528 int send_count) {
2529 // Send the next request.
2530 SendRequest(base::Bind(&RequestTestRunner::MultipleRunTestNext, this,
2531 complete_callback, send_count));
2532 }
2533
MultipleRunTestNext(const base::Closure & complete_callback,int send_count,const test_request::State & completed_client)2534 void MultipleRunTestNext(const base::Closure& complete_callback,
2535 int send_count,
2536 const test_request::State& completed_client) {
2537 // Verify the completed request.
2538 VerifyResponse(&completed_client);
2539
2540 if (send_count == settings_.expected_send_count) {
2541 // All requests complete.
2542 complete_callback.Run();
2543 return;
2544 }
2545
2546 const int next_send_count = send_count + 1;
2547 const base::Closure& continue_callback =
2548 base::Bind(&RequestTestRunner::MultipleRunTestContinue, this,
2549 complete_callback, next_send_count);
2550
2551 if (!settings_.setup_next_request.is_null()) {
2552 // Provide an opportunity to modify expectations before the next request.
2553 // Copy the callback object in case |settings_.setup_next_request| is
2554 // modified as a result of the call.
2555 RequestRunSettings::NextRequestCallback next_callback =
2556 settings_.setup_next_request;
2557 next_callback.Run(next_send_count, continue_callback);
2558 } else {
2559 continue_callback.Run();
2560 }
2561 }
2562
2563 // Register a test. Called in the constructor.
RegisterTest(RequestTestMode test_mode,TestCallback setup,TestCallback run)2564 void RegisterTest(RequestTestMode test_mode,
2565 TestCallback setup,
2566 TestCallback run) {
2567 TestEntry entry = {setup, run};
2568 test_map_.insert(std::make_pair(test_mode, entry));
2569 }
2570
CompleteOnCorrectThread(const base::Closure & complete_callback)2571 void CompleteOnCorrectThread(const base::Closure& complete_callback) {
2572 if (!owner_task_runner_->BelongsToCurrentThread()) {
2573 owner_task_runner_->PostTask(CefCreateClosureTask(
2574 base::Bind(&RequestTestRunner::CompleteOnCorrectThread, this,
2575 complete_callback)));
2576 return;
2577 }
2578
2579 complete_callback.Run();
2580 }
2581
RunDeleteTempDirectory(const base::Closure & complete_callback)2582 void RunDeleteTempDirectory(const base::Closure& complete_callback) {
2583 EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
2584
2585 EXPECT_TRUE(post_file_tmpdir_.Delete());
2586 EXPECT_TRUE(post_file_tmpdir_.IsEmpty());
2587
2588 // Continue with test shutdown.
2589 RunShutdown(complete_callback);
2590 }
2591
RunShutdown(const base::Closure & complete_callback)2592 void RunShutdown(const base::Closure& complete_callback) {
2593 if (!owner_task_runner_->BelongsToCurrentThread()) {
2594 owner_task_runner_->PostTask(CefCreateClosureTask(base::Bind(
2595 &RequestTestRunner::RunShutdown, this, complete_callback)));
2596 return;
2597 }
2598
2599 if (is_browser_process_) {
2600 ShutdownTestBackend(complete_callback);
2601 } else {
2602 complete_callback.Run();
2603 }
2604 }
2605
2606 // Create the backend for the current test. Called during test setup.
SetupTestBackend(const base::Closure & complete_callback)2607 void SetupTestBackend(const base::Closure& complete_callback) {
2608 // Backends are only created in the browser process.
2609 EXPECT_TRUE(is_browser_process_);
2610
2611 EXPECT_TRUE(settings_.request.get());
2612 EXPECT_TRUE(settings_.response.get() ||
2613 settings_.expected_status == UR_FAILED);
2614
2615 if (is_server_backend_)
2616 StartServer(complete_callback);
2617 else
2618 AddSchemeHandler(complete_callback);
2619 }
2620
StartServer(const base::Closure & complete_callback)2621 void StartServer(const base::Closure& complete_callback) {
2622 EXPECT_FALSE(server_handler_);
2623
2624 server_handler_ = new RequestServerHandler();
2625
2626 server_handler_->AddSchemeHandler(&settings_);
2627 if (settings_.expected_receive_count >= 0) {
2628 server_handler_->SetExpectedRequestCount(
2629 settings_.expected_receive_count);
2630 }
2631
2632 server_handler_->CreateServer(complete_callback);
2633 }
2634
AddSchemeHandler(const base::Closure & complete_callback)2635 void AddSchemeHandler(const base::Closure& complete_callback) {
2636 EXPECT_FALSE(scheme_factory_);
2637
2638 // Add the factory registration.
2639 scheme_factory_ = new RequestSchemeHandlerFactory();
2640 request_context_->RegisterSchemeHandlerFactory(GetRequestScheme(false),
2641 GetRequestHost(false, false),
2642 scheme_factory_.get());
2643
2644 scheme_factory_->AddSchemeHandler(&settings_);
2645
2646 // Any further calls will come from the IO thread.
2647 scheme_factory_->SetOwnerTaskRunner(CefTaskRunner::GetForThread(TID_IO));
2648
2649 complete_callback.Run();
2650 }
2651
2652 // Shutdown the backend for the current test. Called during test shutdown.
ShutdownTestBackend(const base::Closure & complete_callback)2653 void ShutdownTestBackend(const base::Closure& complete_callback) {
2654 // Backends are only created in the browser process.
2655 EXPECT_TRUE(is_browser_process_);
2656 if (is_server_backend_)
2657 ShutdownServer(complete_callback);
2658 else
2659 RemoveSchemeHandler(complete_callback);
2660 }
2661
ShutdownServer(const base::Closure & complete_callback)2662 void ShutdownServer(const base::Closure& complete_callback) {
2663 EXPECT_TRUE(server_handler_);
2664
2665 // |server_handler_| will delete itself after shutdown.
2666 server_handler_->ShutdownServer(complete_callback);
2667 server_handler_ = nullptr;
2668 }
2669
RemoveSchemeHandler(const base::Closure & complete_callback)2670 void RemoveSchemeHandler(const base::Closure& complete_callback) {
2671 EXPECT_TRUE(scheme_factory_);
2672
2673 // Remove the factory registration.
2674 request_context_->RegisterSchemeHandlerFactory(
2675 GetRequestScheme(false), GetRequestHost(false, false), nullptr);
2676 scheme_factory_->Shutdown(complete_callback);
2677 scheme_factory_ = nullptr;
2678 }
2679
2680 const bool is_browser_process_;
2681 const bool is_server_backend_;
2682 const bool use_frame_method_;
2683 const bool run_in_browser_process_;
2684
2685 // Used with incomplete request tests.
2686 base::Closure incomplete_request_callback_;
2687
2688 // Primary thread runner for the object that owns us. In the browser process
2689 // this will be the UI thread and in the renderer process this will be the
2690 // RENDERER thread.
2691 CefRefPtr<CefTaskRunner> owner_task_runner_;
2692
2693 CefRefPtr<CefRequestContext> request_context_;
2694
2695 // Frame that originates the request. May be nullptr.
2696 CefRefPtr<CefFrame> frame_;
2697
2698 struct TestEntry {
2699 TestCallback setup;
2700 TestCallback run;
2701 };
2702 typedef std::map<RequestTestMode, TestEntry> TestMap;
2703 TestMap test_map_;
2704
2705 // Server backend.
2706 RequestServerHandler* server_handler_ = nullptr;
2707
2708 // Scheme handler backend.
2709 std::string scheme_name_;
2710 CefRefPtr<RequestSchemeHandlerFactory> scheme_factory_;
2711
2712 CefScopedTempDir post_file_tmpdir_;
2713
2714 public:
2715 RequestRunSettings settings_;
2716 };
2717
2718 // RENDERER-SIDE TEST HARNESS
2719
2720 class RequestRendererTest : public ClientAppRenderer::Delegate {
2721 public:
RequestRendererTest()2722 RequestRendererTest() {}
2723
OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)2724 bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
2725 CefRefPtr<CefBrowser> browser,
2726 CefRefPtr<CefFrame> frame,
2727 CefProcessId source_process,
2728 CefRefPtr<CefProcessMessage> message) override {
2729 if (message->GetName() == kRequestTestMsg) {
2730 EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
2731 EXPECT_TRUE(frame->IsMain());
2732
2733 app_ = app;
2734 browser_ = browser;
2735 frame_ = nullptr;
2736
2737 CefRefPtr<CefListValue> args = message->GetArgumentList();
2738
2739 const bool use_frame_method = args->GetBool(2);
2740 if (use_frame_method)
2741 frame_ = frame;
2742
2743 test_mode_ = static_cast<RequestTestMode>(args->GetInt(0));
2744 test_runner_ = new RequestTestRunner(
2745 false, args->GetBool(1), use_frame_method, false,
2746 base::Bind(&RequestRendererTest::OnIncompleteRequest, this));
2747
2748 // Setup the test. This will create the objects that we test against but
2749 // not register any backend (because we're in the render process).
2750 test_runner_->SetupTest(
2751 test_mode_, base::Bind(&RequestRendererTest::OnSetupComplete, this));
2752
2753 return true;
2754 }
2755
2756 // Message not handled.
2757 return false;
2758 }
2759
2760 private:
OnSetupComplete()2761 void OnSetupComplete() {
2762 EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
2763
2764 // Run the test.
2765 test_runner_->RunTest(
2766 test_mode_, frame_,
2767 base::Bind(&RequestRendererTest::OnRunComplete, this));
2768 }
2769
OnRunComplete()2770 void OnRunComplete() {
2771 EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
2772
2773 // Shutdown the test.
2774 test_runner_->ShutdownTest(
2775 base::Bind(&RequestRendererTest::OnShutdownComplete, this));
2776 }
2777
OnIncompleteRequest()2778 void OnIncompleteRequest() {
2779 EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
2780
2781 // This method will only be called for incomplete requests.
2782 EXPECT_NE(test_runner_->settings_.incomplete_type,
2783 RequestRunSettings::INCOMPLETE_NONE);
2784
2785 // Check if the test has failed.
2786 bool result = !TestFailed();
2787
2788 // The browser will be closed to abort in-progress requests.
2789 CefRefPtr<CefProcessMessage> return_msg =
2790 CefProcessMessage::Create(kIncompleteRequestTestMsg);
2791 EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result));
2792 browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg);
2793 }
2794
OnShutdownComplete()2795 void OnShutdownComplete() {
2796 EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
2797
2798 if (test_runner_->settings_.incomplete_type !=
2799 RequestRunSettings::INCOMPLETE_NONE) {
2800 // For incomplete tests there's a race between process destruction due to
2801 // the browser closing, and the test possibly completing due to request
2802 // cancellation. We therefore ignore test completion in this case.
2803 return;
2804 }
2805
2806 // Check if the test has failed.
2807 bool result = !TestFailed();
2808
2809 // Return the result to the browser process.
2810 CefRefPtr<CefProcessMessage> return_msg =
2811 CefProcessMessage::Create(kRequestTestMsg);
2812 EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result));
2813 browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg);
2814
2815 app_ = nullptr;
2816 browser_ = nullptr;
2817 }
2818
2819 CefRefPtr<ClientAppRenderer> app_;
2820 CefRefPtr<CefBrowser> browser_;
2821 CefRefPtr<CefFrame> frame_;
2822 RequestTestMode test_mode_;
2823
2824 scoped_refptr<RequestTestRunner> test_runner_;
2825
2826 IMPLEMENT_REFCOUNTING(RequestRendererTest);
2827 };
2828
2829 // BROWSER-SIDE TEST HARNESS
2830
2831 class RequestTestHandler : public TestHandler {
2832 public:
RequestTestHandler(RequestTestMode test_mode,ContextTestMode context_mode,bool test_in_browser,bool test_server_backend,bool test_frame_method)2833 RequestTestHandler(RequestTestMode test_mode,
2834 ContextTestMode context_mode,
2835 bool test_in_browser,
2836 bool test_server_backend,
2837 bool test_frame_method)
2838 : test_mode_(test_mode),
2839 context_mode_(context_mode),
2840 test_in_browser_(test_in_browser),
2841 test_server_backend_(test_server_backend),
2842 test_frame_method_(test_frame_method),
2843 // Must use the request origin to avoid failures in
2844 // CorsURLLoaderFactory::IsSane for requests originating from the
2845 // renderer process.
2846 test_url_(GetRequestOrigin(test_server_backend) +
2847 "/URLRequestTest.Test") {}
2848
RunTest()2849 void RunTest() override {
2850 // Time out the test after a reasonable period of time.
2851 SetTestTimeout(IsChromeRuntimeEnabled() ? 10000 : 5000);
2852
2853 // Start pre-setup actions.
2854 PreSetupStart();
2855 }
2856
PreSetupStart()2857 void PreSetupStart() {
2858 CefPostTask(TID_FILE_USER_VISIBLE,
2859 base::Bind(&RequestTestHandler::PreSetupFileTasks, this));
2860 }
2861
PreSetupFileTasks()2862 void PreSetupFileTasks() {
2863 EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
2864
2865 if (context_mode_ == CONTEXT_ONDISK) {
2866 EXPECT_TRUE(context_tmpdir_.CreateUniqueTempDirUnderPath(
2867 CefTestSuite::GetInstance()->root_cache_path()));
2868 context_tmpdir_path_ = context_tmpdir_.GetPath();
2869 EXPECT_FALSE(context_tmpdir_path_.empty());
2870 }
2871
2872 CefPostTask(TID_UI,
2873 base::Bind(&RequestTestHandler::PreSetupContinue, this));
2874 }
2875
PreSetupContinue()2876 void PreSetupContinue() {
2877 EXPECT_TRUE(CefCurrentlyOn(TID_UI));
2878
2879 test_runner_ = new RequestTestRunner(
2880 true, test_server_backend_, test_frame_method_, test_in_browser_,
2881 base::Bind(&RequestTestHandler::OnIncompleteRequest, this));
2882
2883 // Get or create the request context.
2884 if (context_mode_ == CONTEXT_GLOBAL) {
2885 CefRefPtr<CefRequestContext> request_context =
2886 CefRequestContext::GetGlobalContext();
2887 EXPECT_TRUE(request_context.get());
2888 test_runner_->SetRequestContext(request_context);
2889
2890 PreSetupComplete();
2891 } else {
2892 // Don't end the test until the temporary request context has been
2893 // destroyed.
2894 SetSignalCompletionWhenAllBrowsersClose(false);
2895
2896 CefRequestContextSettings settings;
2897
2898 if (context_mode_ == CONTEXT_ONDISK) {
2899 EXPECT_FALSE(context_tmpdir_.IsEmpty());
2900 CefString(&settings.cache_path) = context_tmpdir_path_;
2901 }
2902
2903 if (!test_server_backend_) {
2904 // Set the schemes that are allowed to store cookies.
2905 CefString(&settings.cookieable_schemes_list) = GetRequestScheme(false);
2906 }
2907
2908 // Create a new temporary request context. Calls OnContextInitialized.
2909 CefRequestContext::CreateContext(settings,
2910 new RequestContextHandler(this));
2911 }
2912 }
2913
OnContextInitialized(CefRefPtr<CefRequestContext> request_context)2914 void OnContextInitialized(CefRefPtr<CefRequestContext> request_context) {
2915 EXPECT_TRUE(CefCurrentlyOn(TID_UI));
2916 EXPECT_TRUE(request_context.get());
2917 test_runner_->SetRequestContext(request_context);
2918 PreSetupComplete();
2919 }
2920
PreSetupComplete()2921 void PreSetupComplete() {
2922 if (!CefCurrentlyOn(TID_UI)) {
2923 CefPostTask(TID_UI,
2924 base::Bind(&RequestTestHandler::PreSetupComplete, this));
2925 return;
2926 }
2927
2928 // Setup the test. This will create the objects that we test against and
2929 // register the backend.
2930 test_runner_->SetupTest(
2931 test_mode_, base::Bind(&RequestTestHandler::OnSetupComplete, this));
2932 }
2933
2934 // Browser process setup is complete.
OnSetupComplete()2935 void OnSetupComplete() {
2936 // Start post-setup actions.
2937 SetTestCookie(test_runner_->GetRequestContext(), test_server_backend_,
2938 base::Bind(&RequestTestHandler::PostSetupComplete, this));
2939 }
2940
PostSetupComplete()2941 void PostSetupComplete() {
2942 if (!CefCurrentlyOn(TID_UI)) {
2943 CefPostTask(TID_UI,
2944 base::Bind(&RequestTestHandler::PostSetupComplete, this));
2945 return;
2946 }
2947
2948 if (test_in_browser_) {
2949 if (test_frame_method_) {
2950 AddResource(test_url_, "<html><body>TEST</body></html>", "text/html");
2951
2952 // Create the browser who's main frame will be the initiator for the
2953 // request.
2954 CreateBrowser(test_url_, test_runner_->GetRequestContext());
2955 } else {
2956 // Run the test now.
2957 test_running_ = true;
2958 test_runner_->RunTest(
2959 test_mode_, nullptr /* frame */,
2960 base::Bind(&RequestTestHandler::OnRunComplete, this));
2961 }
2962 } else {
2963 AddResource(test_url_, "<html><body>TEST</body></html>", "text/html");
2964
2965 // Create a browser to run the test in the renderer process.
2966 CreateBrowser(test_url_, test_runner_->GetRequestContext());
2967 }
2968 }
2969
OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefRequestCallback> callback)2970 ReturnValue OnBeforeResourceLoad(
2971 CefRefPtr<CefBrowser> browser,
2972 CefRefPtr<CefFrame> frame,
2973 CefRefPtr<CefRequest> request,
2974 CefRefPtr<CefRequestCallback> callback) override {
2975 if (test_running_ && test_frame_method_) {
2976 EXPECT_TRUE(frame);
2977 EXPECT_EQ(test_frame_->GetIdentifier(), frame->GetIdentifier());
2978 test_frame_resource_load_ct_++;
2979 }
2980
2981 return TestHandler::OnBeforeResourceLoad(browser, frame, request, callback);
2982 }
2983
GetAuthCredentials(CefRefPtr<CefBrowser> browser,const CefString & origin_url,bool isProxy,const CefString & host,int port,const CefString & realm,const CefString & scheme,CefRefPtr<CefAuthCallback> callback)2984 bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
2985 const CefString& origin_url,
2986 bool isProxy,
2987 const CefString& host,
2988 int port,
2989 const CefString& realm,
2990 const CefString& scheme,
2991 CefRefPtr<CefAuthCallback> callback) override {
2992 EXPECT_TRUE(test_in_browser_);
2993 EXPECT_TRUE(test_frame_method_);
2994 auth_credentials_ct_++;
2995 if (test_runner_->settings_.expect_authentication) {
2996 callback->Continue(test_runner_->settings_.username,
2997 test_runner_->settings_.password);
2998 return true;
2999 }
3000 return false;
3001 }
3002
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)3003 void OnLoadEnd(CefRefPtr<CefBrowser> browser,
3004 CefRefPtr<CefFrame> frame,
3005 int httpStatusCode) override {
3006 if (test_in_browser_ && test_frame_method_) {
3007 // Run the test now.
3008 test_frame_ = frame;
3009 test_running_ = true;
3010 test_runner_->RunTest(
3011 test_mode_, frame,
3012 base::Bind(&RequestTestHandler::OnRunComplete, this));
3013 return;
3014 }
3015
3016 EXPECT_FALSE(test_in_browser_);
3017 if (frame->IsMain()) {
3018 CefRefPtr<CefProcessMessage> test_message =
3019 CefProcessMessage::Create(kRequestTestMsg);
3020 CefRefPtr<CefListValue> args = test_message->GetArgumentList();
3021 EXPECT_TRUE(args->SetInt(0, test_mode_));
3022 EXPECT_TRUE(args->SetBool(1, test_server_backend_));
3023 EXPECT_TRUE(args->SetBool(2, test_frame_method_));
3024
3025 if (test_frame_method_)
3026 test_frame_ = frame;
3027 test_running_ = true;
3028
3029 // Send a message to the renderer process to run the test.
3030 frame->SendProcessMessage(PID_RENDERER, test_message);
3031 }
3032 }
3033
OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)3034 bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
3035 CefRefPtr<CefFrame> frame,
3036 CefProcessId source_process,
3037 CefRefPtr<CefProcessMessage> message) override {
3038 EXPECT_TRUE(browser.get());
3039 EXPECT_TRUE(frame.get());
3040 EXPECT_EQ(PID_RENDERER, source_process);
3041 EXPECT_TRUE(message.get());
3042 EXPECT_TRUE(message->IsReadOnly());
3043 EXPECT_FALSE(test_in_browser_);
3044
3045 EXPECT_FALSE(got_message_);
3046 got_message_.yes();
3047
3048 if (message->GetArgumentList()->GetBool(0))
3049 got_success_.yes();
3050
3051 const std::string& message_name = message->GetName();
3052 if (message_name == kRequestTestMsg) {
3053 // Renderer process test is complete.
3054 OnRunComplete();
3055 } else if (message_name == kIncompleteRequestTestMsg) {
3056 // Incomplete renderer tests will not complete normally. Instead, trigger
3057 // browser close and then signal completion from OnBeforeClose.
3058 OnIncompleteRequest();
3059 }
3060
3061 return true;
3062 }
3063
OnBeforeClose(CefRefPtr<CefBrowser> browser)3064 void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
3065 if (!test_in_browser_ && test_runner_->settings_.incomplete_type !=
3066 RequestRunSettings::INCOMPLETE_NONE) {
3067 // Incomplete tests running in the renderer process will never recieve the
3068 // test complete process message, so call the method here.
3069 OnRunComplete();
3070 }
3071
3072 TestHandler::OnBeforeClose(browser);
3073 }
3074
3075 // Incomplete tests will not complete normally. Instead, we trigger a browser
3076 // close to abort in-progress requests.
OnIncompleteRequest()3077 void OnIncompleteRequest() {
3078 if (!CefCurrentlyOn(TID_UI)) {
3079 CefPostTask(TID_UI,
3080 base::Bind(&RequestTestHandler::OnIncompleteRequest, this));
3081 return;
3082 }
3083
3084 EXPECT_TRUE(test_frame_method_);
3085 EXPECT_NE(RequestRunSettings::INCOMPLETE_NONE,
3086 test_runner_->settings_.incomplete_type);
3087
3088 // TestComplete will eventually be called from DestroyTest instead of being
3089 // triggered by browser destruction.
3090 SetSignalCompletionWhenAllBrowsersClose(false);
3091 CefPostDelayedTask(
3092 TID_UI, base::Bind(&TestHandler::CloseBrowser, GetBrowser(), false),
3093 1000);
3094 }
3095
3096 // Test run is complete. It ran in either the browser or render process.
OnRunComplete()3097 void OnRunComplete() {
3098 GetTestCookie(test_runner_->GetRequestContext(), test_server_backend_,
3099 base::Bind(&RequestTestHandler::PostRunComplete, this));
3100 }
3101
PostRunComplete(bool has_save_cookie)3102 void PostRunComplete(bool has_save_cookie) {
3103 if (!CefCurrentlyOn(TID_UI)) {
3104 CefPostTask(TID_UI, base::Bind(&RequestTestHandler::PostRunComplete, this,
3105 has_save_cookie));
3106 return;
3107 }
3108
3109 EXPECT_EQ(test_runner_->settings_.expect_save_cookie, has_save_cookie);
3110
3111 // Shut down the browser side of the test.
3112 test_runner_->ShutdownTest(
3113 base::Bind(&RequestTestHandler::MaybeClearAuthCredentials, this));
3114 }
3115
MaybeClearAuthCredentials()3116 void MaybeClearAuthCredentials() {
3117 if (test_runner_->settings_.expect_authentication &&
3118 context_mode_ == CONTEXT_GLOBAL) {
3119 // Clear the HTTP authentication cache to avoid leaking state between
3120 // test runs when using the global request context.
3121 test_runner_->GetRequestContext()->ClearHttpAuthCredentials(
3122 new TestCompletionCallback(
3123 base::Bind(&RequestTestHandler::DestroyTest, this)));
3124 return;
3125 }
3126
3127 DestroyTest();
3128 }
3129
DestroyTest()3130 void DestroyTest() override {
3131 if (!test_in_browser_) {
3132 EXPECT_TRUE(got_message_);
3133 EXPECT_TRUE(got_success_);
3134 }
3135
3136 if (test_frame_method_) {
3137 // Expect at least 1 call to OnBeforeResourceLoad for every test.
3138 // Redirect tests may get multiple calls.
3139 EXPECT_LE(1, test_frame_resource_load_ct_);
3140 }
3141
3142 // CefRequestHandler::GetAuthCredentials should be called after
3143 // CefURLRequestClient::GetAuthCredentials when the request has an
3144 // associated frame.
3145 if (test_in_browser_ && test_frame_method_ &&
3146 test_runner_->settings_.expect_authentication) {
3147 EXPECT_EQ(1, auth_credentials_ct_);
3148 } else {
3149 EXPECT_EQ(0, auth_credentials_ct_);
3150 }
3151
3152 TestHandler::DestroyTest();
3153
3154 // For non-global contexts OnTestComplete() will be called when the
3155 // RequestContextHandler is destroyed.
3156 bool call_test_complete = false;
3157 if (context_mode_ == CONTEXT_GLOBAL) {
3158 if (test_in_browser_ && !test_frame_method_) {
3159 // These tests don't create a browser that would signal implicitly.
3160 call_test_complete = true;
3161 } else if (!SignalCompletionWhenAllBrowsersClose()) {
3162 // These tests close the browser to terminate in-progress requests
3163 // before test completion.
3164 call_test_complete = true;
3165 }
3166 }
3167
3168 // Release references to the context and handler.
3169 test_runner_->Destroy();
3170
3171 if (call_test_complete)
3172 OnTestComplete();
3173 }
3174
OnTestComplete()3175 void OnTestComplete() {
3176 if (!CefCurrentlyOn(TID_UI)) {
3177 CefPostTask(TID_UI,
3178 base::Bind(&RequestTestHandler::OnTestComplete, this));
3179 return;
3180 }
3181
3182 EXPECT_FALSE(got_on_test_complete_);
3183 got_on_test_complete_.yes();
3184
3185 if (!context_tmpdir_.IsEmpty()) {
3186 // Temp directory will be deleted on application shutdown.
3187 context_tmpdir_.Take();
3188 }
3189
3190 TestComplete();
3191 }
3192
3193 private:
3194 // Used with temporary request contexts to signal test completion once the
3195 // temporary context has been destroyed.
3196 class RequestContextHandler : public CefRequestContextHandler {
3197 public:
RequestContextHandler(CefRefPtr<RequestTestHandler> test_handler)3198 explicit RequestContextHandler(CefRefPtr<RequestTestHandler> test_handler)
3199 : test_handler_(test_handler) {}
~RequestContextHandler()3200 ~RequestContextHandler() override { test_handler_->OnTestComplete(); }
3201
OnRequestContextInitialized(CefRefPtr<CefRequestContext> request_context)3202 void OnRequestContextInitialized(
3203 CefRefPtr<CefRequestContext> request_context) override {
3204 test_handler_->OnContextInitialized(request_context);
3205 }
3206
3207 private:
3208 CefRefPtr<RequestTestHandler> test_handler_;
3209
3210 IMPLEMENT_REFCOUNTING(RequestContextHandler);
3211 };
3212
3213 const RequestTestMode test_mode_;
3214 const ContextTestMode context_mode_;
3215 const bool test_in_browser_;
3216 const bool test_server_backend_;
3217 const bool test_frame_method_;
3218 const std::string test_url_;
3219
3220 scoped_refptr<RequestTestRunner> test_runner_;
3221
3222 bool test_running_ = false;
3223
3224 CefRefPtr<CefFrame> test_frame_;
3225 int test_frame_resource_load_ct_ = 0;
3226
3227 CefScopedTempDir context_tmpdir_;
3228 CefString context_tmpdir_path_;
3229
3230 public:
3231 // Only used when the test runs in the render process.
3232 TrackCallback got_message_;
3233 TrackCallback got_success_;
3234
3235 int auth_credentials_ct_ = 0;
3236 TrackCallback got_on_test_complete_;
3237
3238 IMPLEMENT_REFCOUNTING(RequestTestHandler);
3239 };
3240
IsTestSupported(RequestTestMode test_mode,ContextTestMode context_mode,bool test_in_browser,bool test_server_backend,bool test_frame_method)3241 bool IsTestSupported(RequestTestMode test_mode,
3242 ContextTestMode context_mode,
3243 bool test_in_browser,
3244 bool test_server_backend,
3245 bool test_frame_method) {
3246 if (!test_in_browser && !test_frame_method) {
3247 // Render process requests must use CefFrame::CreateURLRequest.
3248 return false;
3249 }
3250
3251 return true;
3252 }
3253
3254 } // namespace
3255
3256 // Entry point for creating URLRequest renderer test objects.
3257 // Called from client_app_delegates.cc.
CreateURLRequestRendererTests(ClientAppRenderer::DelegateSet & delegates)3258 void CreateURLRequestRendererTests(ClientAppRenderer::DelegateSet& delegates) {
3259 delegates.insert(new RequestRendererTest);
3260 }
3261
3262 // Entry point for registering custom schemes.
3263 // Called from client_app_delegates.cc.
RegisterURLRequestCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar)3264 void RegisterURLRequestCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
3265 const std::string& scheme = GetRequestScheme(false);
3266 registrar->AddCustomScheme(
3267 scheme, CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
3268 }
3269
3270 // Entry point for registering cookieable schemes.
3271 // Called from client_app_delegates.cc.
RegisterURLRequestCookieableSchemes(std::vector<std::string> & cookieable_schemes)3272 void RegisterURLRequestCookieableSchemes(
3273 std::vector<std::string>& cookieable_schemes) {
3274 const std::string& scheme = GetRequestScheme(false);
3275 cookieable_schemes.push_back(scheme);
3276 }
3277
3278 // Helpers for defining URLRequest tests.
3279 #define REQ_TEST_EX(name, test_mode, context_mode, test_in_browser, \
3280 test_server_backend, test_frame_method) \
3281 TEST(URLRequestTest, name) { \
3282 if (!IsTestSupported(test_mode, context_mode, test_in_browser, \
3283 test_server_backend, test_frame_method)) { \
3284 return; \
3285 } \
3286 CefRefPtr<RequestTestHandler> handler = \
3287 new RequestTestHandler(test_mode, context_mode, test_in_browser, \
3288 test_server_backend, test_frame_method); \
3289 handler->ExecuteTest(); \
3290 ReleaseAndWaitForDestructor(handler); \
3291 }
3292
3293 #define REQ_TEST(name, test_mode, context_mode, test_in_browser, \
3294 test_server_backend, test_frame_method) \
3295 REQ_TEST_EX(name, test_mode, context_mode, test_in_browser, \
3296 test_server_backend, test_frame_method)
3297
3298 // Define the tests.
3299 #define REQ_TEST_SET_EX(suffix, context_mode, test_server_backend, \
3300 test_frame_method) \
3301 REQ_TEST(BrowserGET##suffix, REQTEST_GET, context_mode, true, \
3302 test_server_backend, test_frame_method) \
3303 REQ_TEST(BrowserGETNoData##suffix, REQTEST_GET_NODATA, context_mode, true, \
3304 test_server_backend, test_frame_method) \
3305 REQ_TEST(BrowserGETPartialContent##suffix, REQTEST_GET_PARTIAL_CONTENT, \
3306 context_mode, true, test_server_backend, test_frame_method) \
3307 REQ_TEST(BrowserGETAllowCookies##suffix, REQTEST_GET_ALLOWCOOKIES, \
3308 context_mode, true, test_server_backend, test_frame_method) \
3309 REQ_TEST(BrowserGETRedirect##suffix, REQTEST_GET_REDIRECT, context_mode, \
3310 true, test_server_backend, test_frame_method) \
3311 REQ_TEST(BrowserGETRedirectStop##suffix, REQTEST_GET_REDIRECT_STOP, \
3312 context_mode, true, test_server_backend, test_frame_method) \
3313 REQ_TEST(BrowserGETRedirectLocation##suffix, REQTEST_GET_REDIRECT_LOCATION, \
3314 context_mode, true, test_server_backend, test_frame_method) \
3315 REQ_TEST(BrowserGETReferrer##suffix, REQTEST_GET_REFERRER, context_mode, \
3316 true, test_server_backend, test_frame_method) \
3317 REQ_TEST(BrowserPOST##suffix, REQTEST_POST, context_mode, true, \
3318 test_server_backend, test_frame_method) \
3319 REQ_TEST(BrowserPOSTFile##suffix, REQTEST_POST_FILE, context_mode, true, \
3320 test_server_backend, test_frame_method) \
3321 REQ_TEST(BrowserPOSTWithProgress##suffix, REQTEST_POST_WITHPROGRESS, \
3322 context_mode, true, test_server_backend, test_frame_method) \
3323 REQ_TEST(BrowserPOSTRedirect##suffix, REQTEST_POST_REDIRECT, context_mode, \
3324 true, test_server_backend, test_frame_method) \
3325 REQ_TEST(BrowserPOSTRedirectToGET##suffix, REQTEST_POST_REDIRECT_TOGET, \
3326 context_mode, true, test_server_backend, test_frame_method) \
3327 REQ_TEST(BrowserHEAD##suffix, REQTEST_HEAD, context_mode, true, \
3328 test_server_backend, test_frame_method) \
3329 REQ_TEST(RendererGET##suffix, REQTEST_GET, context_mode, false, \
3330 test_server_backend, test_frame_method) \
3331 REQ_TEST(RendererGETNoData##suffix, REQTEST_GET_NODATA, context_mode, false, \
3332 test_server_backend, test_frame_method) \
3333 REQ_TEST(RendererGETAllowCookies##suffix, REQTEST_GET_ALLOWCOOKIES, \
3334 context_mode, false, test_server_backend, test_frame_method) \
3335 REQ_TEST(RendererGETRedirect##suffix, REQTEST_GET_REDIRECT, context_mode, \
3336 false, test_server_backend, test_frame_method) \
3337 REQ_TEST(RendererGETRedirectStop##suffix, REQTEST_GET_REDIRECT_STOP, \
3338 context_mode, false, test_server_backend, test_frame_method) \
3339 REQ_TEST(RendererGETRedirectLocation##suffix, REQTEST_GET_REDIRECT_LOCATION, \
3340 context_mode, false, test_server_backend, test_frame_method) \
3341 REQ_TEST(RendererGETReferrer##suffix, REQTEST_GET_REFERRER, context_mode, \
3342 false, test_server_backend, test_frame_method) \
3343 REQ_TEST(RendererPOST##suffix, REQTEST_POST, context_mode, false, \
3344 test_server_backend, test_frame_method) \
3345 REQ_TEST(RendererPOSTWithProgress##suffix, REQTEST_POST_WITHPROGRESS, \
3346 context_mode, false, test_server_backend, test_frame_method) \
3347 REQ_TEST(RendererPOSTRedirect##suffix, REQTEST_POST_REDIRECT, context_mode, \
3348 false, test_server_backend, test_frame_method) \
3349 REQ_TEST(RendererPOSTRedirectToGET##suffix, REQTEST_POST_REDIRECT_TOGET, \
3350 context_mode, false, test_server_backend, test_frame_method) \
3351 REQ_TEST(RendererHEAD##suffix, REQTEST_HEAD, context_mode, false, \
3352 test_server_backend, test_frame_method)
3353
3354 #define REQ_TEST_SET(suffix, test_frame_method) \
3355 REQ_TEST_SET_EX(ContextGlobalCustom##suffix, CONTEXT_GLOBAL, false, \
3356 test_frame_method) \
3357 REQ_TEST_SET_EX(ContextInMemoryCustom##suffix, CONTEXT_INMEMORY, false, \
3358 test_frame_method) \
3359 REQ_TEST_SET_EX(ContextOnDiskCustom##suffix, CONTEXT_ONDISK, false, \
3360 test_frame_method) \
3361 REQ_TEST_SET_EX(ContextGlobalServer##suffix, CONTEXT_GLOBAL, true, \
3362 test_frame_method) \
3363 REQ_TEST_SET_EX(ContextInMemoryServer##suffix, CONTEXT_INMEMORY, true, \
3364 test_frame_method) \
3365 REQ_TEST_SET_EX(ContextOnDiskServer##suffix, CONTEXT_ONDISK, true, \
3366 test_frame_method)
3367
3368 REQ_TEST_SET(WithoutFrame, false)
3369 REQ_TEST_SET(WithFrame, true)
3370
3371 // Define tests that can only run with a frame.
3372 #define REQ_TEST_FRAME_SET_EX(suffix, context_mode, test_server_backend) \
3373 REQ_TEST(BrowserIncompleteProcessRequest##suffix, \
3374 REQTEST_INCOMPLETE_PROCESS_REQUEST, context_mode, true, \
3375 test_server_backend, true) \
3376 REQ_TEST(BrowserIncompleteReadResponse##suffix, \
3377 REQTEST_INCOMPLETE_READ_RESPONSE, context_mode, true, \
3378 test_server_backend, true) \
3379 REQ_TEST(RendererIncompleteProcessRequest##suffix, \
3380 REQTEST_INCOMPLETE_PROCESS_REQUEST, context_mode, false, \
3381 test_server_backend, true) \
3382 REQ_TEST(RendererIncompleteReadResponse##suffix, \
3383 REQTEST_INCOMPLETE_READ_RESPONSE, context_mode, false, \
3384 test_server_backend, true)
3385
3386 #define REQ_TEST_FRAME_SET() \
3387 REQ_TEST_FRAME_SET_EX(ContextGlobalCustomWithFrame, CONTEXT_GLOBAL, false) \
3388 REQ_TEST_FRAME_SET_EX(ContextInMemoryCustomWithFrame, CONTEXT_INMEMORY, \
3389 false) \
3390 REQ_TEST_FRAME_SET_EX(ContextOnDiskCustomWithFrame, CONTEXT_ONDISK, false) \
3391 REQ_TEST_FRAME_SET_EX(ContextGlobalServerWithFrame, CONTEXT_GLOBAL, true) \
3392 REQ_TEST_FRAME_SET_EX(ContextInMemoryServerWithFrame, CONTEXT_INMEMORY, \
3393 true) \
3394 REQ_TEST_FRAME_SET_EX(ContextOnDiskServerWithFrame, CONTEXT_ONDISK, true)
3395
3396 REQ_TEST_FRAME_SET()
3397
3398 // Cache and authentication tests can only be run with the server backend.
3399 #define REQ_TEST_CACHE_SET_EX(suffix, context_mode, test_frame_method) \
3400 REQ_TEST(BrowserGETCacheWithControl##suffix, REQTEST_CACHE_WITH_CONTROL, \
3401 context_mode, true, true, test_frame_method) \
3402 REQ_TEST(BrowserGETCacheWithoutControl##suffix, \
3403 REQTEST_CACHE_WITHOUT_CONTROL, context_mode, true, true, \
3404 test_frame_method) \
3405 REQ_TEST(BrowserGETCacheSkipFlag##suffix, REQTEST_CACHE_SKIP_FLAG, \
3406 context_mode, true, true, test_frame_method) \
3407 REQ_TEST(BrowserGETCacheSkipHeader##suffix, REQTEST_CACHE_SKIP_HEADER, \
3408 context_mode, true, true, test_frame_method) \
3409 REQ_TEST(BrowserGETCacheOnlyFailureFlag##suffix, \
3410 REQTEST_CACHE_ONLY_FAILURE_FLAG, context_mode, true, true, \
3411 test_frame_method) \
3412 REQ_TEST(BrowserGETCacheOnlyFailureHeader##suffix, \
3413 REQTEST_CACHE_ONLY_FAILURE_HEADER, context_mode, true, true, \
3414 test_frame_method) \
3415 REQ_TEST(BrowserGETCacheOnlySuccessFlag##suffix, \
3416 REQTEST_CACHE_ONLY_SUCCESS_FLAG, context_mode, true, true, \
3417 test_frame_method) \
3418 REQ_TEST(BrowserGETCacheOnlySuccessHeader##suffix, \
3419 REQTEST_CACHE_ONLY_SUCCESS_HEADER, context_mode, true, true, \
3420 test_frame_method) \
3421 REQ_TEST(BrowserGETCacheDisableFlag##suffix, REQTEST_CACHE_DISABLE_FLAG, \
3422 context_mode, true, true, test_frame_method) \
3423 REQ_TEST(BrowserGETCacheDisableHeader##suffix, REQTEST_CACHE_DISABLE_HEADER, \
3424 context_mode, true, true, test_frame_method) \
3425 REQ_TEST(RendererGETCacheWithControl##suffix, REQTEST_CACHE_WITH_CONTROL, \
3426 context_mode, false, true, test_frame_method) \
3427 REQ_TEST(RendererGETCacheWithoutControl##suffix, \
3428 REQTEST_CACHE_WITHOUT_CONTROL, context_mode, false, true, \
3429 test_frame_method) \
3430 REQ_TEST(BrowserGETAuth##suffix, REQTEST_GET_AUTH, context_mode, true, true, \
3431 test_frame_method) \
3432 REQ_TEST(RendererGETCacheSkipFlag##suffix, REQTEST_CACHE_SKIP_FLAG, \
3433 context_mode, false, true, test_frame_method) \
3434 REQ_TEST(RendererGETCacheSkipHeader##suffix, REQTEST_CACHE_SKIP_HEADER, \
3435 context_mode, false, true, test_frame_method) \
3436 REQ_TEST(RendererGETCacheOnlyFailureFlag##suffix, \
3437 REQTEST_CACHE_ONLY_FAILURE_FLAG, context_mode, false, true, \
3438 test_frame_method) \
3439 REQ_TEST(RendererGETCacheOnlyFailureHeader##suffix, \
3440 REQTEST_CACHE_ONLY_FAILURE_HEADER, context_mode, false, true, \
3441 test_frame_method) \
3442 REQ_TEST(RendererGETCacheOnlySuccessFlag##suffix, \
3443 REQTEST_CACHE_ONLY_SUCCESS_FLAG, context_mode, false, true, \
3444 test_frame_method) \
3445 REQ_TEST(RendererGETCacheOnlySuccessHeader##suffix, \
3446 REQTEST_CACHE_ONLY_SUCCESS_HEADER, context_mode, false, true, \
3447 test_frame_method) \
3448 REQ_TEST(RendererGETCacheDisableFlag##suffix, REQTEST_CACHE_DISABLE_FLAG, \
3449 context_mode, false, true, test_frame_method) \
3450 REQ_TEST(RendererGETCacheDisableHeader##suffix, \
3451 REQTEST_CACHE_DISABLE_HEADER, context_mode, false, true, \
3452 test_frame_method)
3453
3454 #define REQ_TEST_CACHE_SET(suffix, test_frame_method) \
3455 REQ_TEST_CACHE_SET_EX(ContextGlobalServer##suffix, CONTEXT_GLOBAL, \
3456 test_frame_method) \
3457 REQ_TEST_CACHE_SET_EX(ContextInMemoryServer##suffix, CONTEXT_INMEMORY, \
3458 test_frame_method) \
3459 REQ_TEST_CACHE_SET_EX(ContextOnDiskServer##suffix, CONTEXT_ONDISK, \
3460 test_frame_method)
3461
3462 REQ_TEST_CACHE_SET(WithoutFrame, false)
3463 REQ_TEST_CACHE_SET(WithFrame, true)
3464
3465 namespace {
3466
3467 class InvalidURLTestClient : public CefURLRequestClient {
3468 public:
InvalidURLTestClient()3469 InvalidURLTestClient() {
3470 event_ = CefWaitableEvent::CreateWaitableEvent(true, false);
3471 }
3472
RunTest()3473 void RunTest() {
3474 CefPostTask(TID_UI, base::Bind(&InvalidURLTestClient::RunOnUIThread, this));
3475
3476 // Wait for the test to complete.
3477 event_->Wait();
3478 }
3479
OnRequestComplete(CefRefPtr<CefURLRequest> client)3480 void OnRequestComplete(CefRefPtr<CefURLRequest> client) override {
3481 EXPECT_EQ(UR_FAILED, client->GetRequestStatus());
3482 EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, client->GetRequestError());
3483
3484 // Let the call stack unwind before signaling completion.
3485 CefPostTask(TID_UI,
3486 base::Bind(&InvalidURLTestClient::CompleteOnUIThread, this));
3487 }
3488
OnUploadProgress(CefRefPtr<CefURLRequest> request,int64 current,int64 total)3489 void OnUploadProgress(CefRefPtr<CefURLRequest> request,
3490 int64 current,
3491 int64 total) override {
3492 EXPECT_TRUE(false); // Not reached.
3493 }
3494
OnDownloadProgress(CefRefPtr<CefURLRequest> request,int64 current,int64 total)3495 void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
3496 int64 current,
3497 int64 total) override {
3498 EXPECT_TRUE(false); // Not reached.
3499 }
3500
OnDownloadData(CefRefPtr<CefURLRequest> request,const void * data,size_t data_length)3501 void OnDownloadData(CefRefPtr<CefURLRequest> request,
3502 const void* data,
3503 size_t data_length) override {
3504 EXPECT_TRUE(false); // Not reached.
3505 }
3506
GetAuthCredentials(bool isProxy,const CefString & host,int port,const CefString & realm,const CefString & scheme,CefRefPtr<CefAuthCallback> callback)3507 bool GetAuthCredentials(bool isProxy,
3508 const CefString& host,
3509 int port,
3510 const CefString& realm,
3511 const CefString& scheme,
3512 CefRefPtr<CefAuthCallback> callback) override {
3513 EXPECT_TRUE(false); // Not reached.
3514 return false;
3515 }
3516
3517 private:
RunOnUIThread()3518 void RunOnUIThread() {
3519 EXPECT_UI_THREAD();
3520 CefRefPtr<CefRequest> request = CefRequest::Create();
3521 request->SetMethod("GET");
3522 request->SetURL("foo://invalidurl");
3523
3524 CefURLRequest::Create(request, this, nullptr);
3525 }
3526
CompleteOnUIThread()3527 void CompleteOnUIThread() {
3528 EXPECT_UI_THREAD();
3529 // Signal that the test is complete.
3530 event_->Signal();
3531 }
3532
3533 CefRefPtr<CefWaitableEvent> event_;
3534
3535 IMPLEMENT_REFCOUNTING(InvalidURLTestClient);
3536 };
3537
3538 } // namespace
3539
3540 // Verify that failed requests do not leak references.
TEST(URLRequestTest,BrowserInvalidURL)3541 TEST(URLRequestTest, BrowserInvalidURL) {
3542 CefRefPtr<InvalidURLTestClient> client = new InvalidURLTestClient();
3543 client->RunTest();
3544 }
3545
3546 // Entry point for creating plugin browser test objects.
3547 // Called from client_app_delegates.cc.
CreateURLRequestBrowserTests(client::ClientAppBrowser::DelegateSet & delegates)3548 void CreateURLRequestBrowserTests(
3549 client::ClientAppBrowser::DelegateSet& delegates) {
3550 delegates.insert(new URLRequestBrowserTest);
3551 }
3552