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