1 // Copyright (c) 2020 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 "tests/ceftests/test_request.h"
6
7 #include <algorithm>
8
9 #include "include/cef_stream.h"
10 #include "include/cef_urlrequest.h"
11 #include "include/wrapper/cef_closure_task.h"
12 #include "include/wrapper/cef_helpers.h"
13 #include "include/wrapper/cef_stream_resource_handler.h"
14
15 namespace test_request {
16
17 namespace {
18
19 // Implementation of CefURLRequestClient that stores response information.
20 class RequestClient : public CefURLRequestClient, public State {
21 public:
RequestClient(const bool has_credentials,const std::string & username,const std::string & password,const RequestDoneCallback & done_callback)22 RequestClient(const bool has_credentials,
23 const std::string& username,
24 const std::string& password,
25 const RequestDoneCallback& done_callback)
26 : has_credentials_(has_credentials),
27 username_(username),
28 password_(password),
29 done_callback_(done_callback) {
30 DCHECK(!done_callback_.is_null());
31 }
32
OnUploadProgress(CefRefPtr<CefURLRequest> request,int64 current,int64 total)33 void OnUploadProgress(CefRefPtr<CefURLRequest> request,
34 int64 current,
35 int64 total) override {
36 upload_progress_ct_++;
37 upload_total_ = total;
38 }
39
OnDownloadProgress(CefRefPtr<CefURLRequest> request,int64 current,int64 total)40 void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
41 int64 current,
42 int64 total) override {
43 response_ = request->GetResponse();
44 DCHECK(response_.get());
45 DCHECK(response_->IsReadOnly());
46 download_progress_ct_++;
47 download_total_ = total;
48 }
49
OnDownloadData(CefRefPtr<CefURLRequest> request,const void * data,size_t data_length)50 void OnDownloadData(CefRefPtr<CefURLRequest> request,
51 const void* data,
52 size_t data_length) override {
53 response_ = request->GetResponse();
54 DCHECK(response_.get());
55 DCHECK(response_->IsReadOnly());
56 download_data_ct_++;
57 download_data_ += std::string(static_cast<const char*>(data), data_length);
58 }
59
GetAuthCredentials(bool isProxy,const CefString & host,int port,const CefString & realm,const CefString & scheme,CefRefPtr<CefAuthCallback> callback)60 bool GetAuthCredentials(bool isProxy,
61 const CefString& host,
62 int port,
63 const CefString& realm,
64 const CefString& scheme,
65 CefRefPtr<CefAuthCallback> callback) override {
66 auth_credentials_ct_++;
67 if (has_credentials_) {
68 callback->Continue(username_, password_);
69 return true;
70 }
71 return false;
72 }
73
OnRequestComplete(CefRefPtr<CefURLRequest> request)74 void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
75 request_complete_ct_++;
76
77 request_ = request->GetRequest();
78 DCHECK(request_->IsReadOnly());
79 status_ = request->GetRequestStatus();
80 error_code_ = request->GetRequestError();
81 response_was_cached_ = request->ResponseWasCached();
82 response_ = request->GetResponse();
83 if (response_) {
84 DCHECK(response_->IsReadOnly());
85 }
86
87 done_callback_.Run(*this);
88 }
89
90 private:
91 const bool has_credentials_;
92 const std::string username_;
93 const std::string password_;
94 const RequestDoneCallback done_callback_;
95
96 IMPLEMENT_REFCOUNTING(RequestClient);
97 DISALLOW_COPY_AND_ASSIGN(RequestClient);
98 };
99
100 // Implementation that collects all cookies, and optionally deletes them.
101 class CookieVisitor : public CefCookieVisitor {
102 public:
CookieVisitor(bool deleteCookies,const CookieDoneCallback & callback)103 CookieVisitor(bool deleteCookies, const CookieDoneCallback& callback)
104 : delete_cookies_(deleteCookies), callback_(callback) {
105 DCHECK(!callback_.is_null());
106 }
107
~CookieVisitor()108 ~CookieVisitor() override {
109 CEF_REQUIRE_UI_THREAD();
110 callback_.Run(cookies_);
111 }
112
Visit(const CefCookie & cookie,int count,int total,bool & deleteCookie)113 bool Visit(const CefCookie& cookie,
114 int count,
115 int total,
116 bool& deleteCookie) override {
117 CEF_REQUIRE_UI_THREAD();
118 cookies_.push_back(cookie);
119 if (delete_cookies_)
120 deleteCookie = true;
121 return true;
122 }
123
124 private:
125 CookieVector cookies_;
126 bool delete_cookies_;
127 CookieDoneCallback callback_;
128
129 IMPLEMENT_REFCOUNTING(CookieVisitor);
130 DISALLOW_COPY_AND_ASSIGN(CookieVisitor);
131 };
132
133 } // namespace
134
Send(const SendConfig & config,const RequestDoneCallback & callback)135 void Send(const SendConfig& config, const RequestDoneCallback& callback) {
136 DCHECK(config.request_);
137 CefRefPtr<RequestClient> client = new RequestClient(
138 config.has_credentials_, config.username_, config.password_, callback);
139 if (config.frame_) {
140 config.frame_->CreateURLRequest(config.request_, client.get());
141 } else {
142 CefURLRequest::Create(config.request_, client.get(),
143 config.request_context_);
144 }
145 }
146
GetPathURL(const std::string & url)147 std::string GetPathURL(const std::string& url) {
148 const size_t index1 = url.find('?');
149 const size_t index2 = url.find('#');
150 size_t index = std::string::npos;
151 if (index1 != std::string::npos && index2 != std::string::npos) {
152 index = std::min(index1, index2);
153 } else if (index1 != std::string::npos) {
154 index = index1;
155 } else if (index2 != std::string::npos) {
156 index = index2;
157 }
158 if (index != std::string::npos) {
159 return url.substr(0, index);
160 }
161 return url;
162 }
163
CreateResourceHandler(CefRefPtr<CefResponse> response,const std::string & response_data)164 CefRefPtr<CefResourceHandler> CreateResourceHandler(
165 CefRefPtr<CefResponse> response,
166 const std::string& response_data) {
167 CefRefPtr<CefStreamReader> stream;
168 if (!response_data.empty()) {
169 stream = CefStreamReader::CreateForData(
170 static_cast<void*>(const_cast<char*>(response_data.c_str())),
171 response_data.length());
172 }
173
174 CefResponse::HeaderMap headerMap;
175 response->GetHeaderMap(headerMap);
176
177 return new CefStreamResourceHandler(
178 response->GetStatus(), response->GetStatusText(), response->GetMimeType(),
179 headerMap, stream);
180 }
181
GetAllCookies(CefRefPtr<CefCookieManager> manager,bool deleteCookies,const CookieDoneCallback & callback)182 void GetAllCookies(CefRefPtr<CefCookieManager> manager,
183 bool deleteCookies,
184 const CookieDoneCallback& callback) {
185 bool result =
186 manager->VisitAllCookies(new CookieVisitor(deleteCookies, callback));
187 DCHECK(result);
188 }
189
190 // Retrieves URL cookies from |manager| and executes |callback| upon completion.
191 // If |deleteCookies| is true the cookies will also be deleted.
GetUrlCookies(CefRefPtr<CefCookieManager> manager,const CefString & url,bool includeHttpOnly,bool deleteCookies,const CookieDoneCallback & callback)192 void GetUrlCookies(CefRefPtr<CefCookieManager> manager,
193 const CefString& url,
194 bool includeHttpOnly,
195 bool deleteCookies,
196 const CookieDoneCallback& callback) {
197 bool result = manager->VisitUrlCookies(
198 url, includeHttpOnly, new CookieVisitor(deleteCookies, callback));
199 DCHECK(result);
200 }
201
202 } // namespace test_request
203