• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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