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