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