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 "libcef/common/response_impl.h"
6
7 #include <string>
8
9 #include "libcef/common/net/http_header_utils.h"
10 #include "libcef/common/net_service/net_service_util.h"
11
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "net/http/http_request_headers.h"
15 #include "net/http/http_response_headers.h"
16 #include "third_party/blink/public/platform/web_http_header_visitor.h"
17 #include "third_party/blink/public/platform/web_string.h"
18 #include "third_party/blink/public/platform/web_url.h"
19 #include "third_party/blink/public/platform/web_url_response.h"
20
21 #define CHECK_READONLY_RETURN_VOID() \
22 if (read_only_) { \
23 NOTREACHED() << "object is read only"; \
24 return; \
25 }
26
27 // CefResponse ----------------------------------------------------------------
28
29 // static
Create()30 CefRefPtr<CefResponse> CefResponse::Create() {
31 CefRefPtr<CefResponse> response(new CefResponseImpl());
32 return response;
33 }
34
35 // CefResponseImpl ------------------------------------------------------------
36
CefResponseImpl()37 CefResponseImpl::CefResponseImpl()
38 : error_code_(ERR_NONE), status_code_(0), read_only_(false) {}
39
IsReadOnly()40 bool CefResponseImpl::IsReadOnly() {
41 base::AutoLock lock_scope(lock_);
42 return read_only_;
43 }
44
GetError()45 cef_errorcode_t CefResponseImpl::GetError() {
46 base::AutoLock lock_scope(lock_);
47 return error_code_;
48 }
49
SetError(cef_errorcode_t error)50 void CefResponseImpl::SetError(cef_errorcode_t error) {
51 base::AutoLock lock_scope(lock_);
52 CHECK_READONLY_RETURN_VOID();
53 error_code_ = error;
54 }
55
GetStatus()56 int CefResponseImpl::GetStatus() {
57 base::AutoLock lock_scope(lock_);
58 return status_code_;
59 }
60
SetStatus(int status)61 void CefResponseImpl::SetStatus(int status) {
62 base::AutoLock lock_scope(lock_);
63 CHECK_READONLY_RETURN_VOID();
64 status_code_ = status;
65 }
66
GetStatusText()67 CefString CefResponseImpl::GetStatusText() {
68 base::AutoLock lock_scope(lock_);
69 return status_text_;
70 }
71
SetStatusText(const CefString & statusText)72 void CefResponseImpl::SetStatusText(const CefString& statusText) {
73 base::AutoLock lock_scope(lock_);
74 CHECK_READONLY_RETURN_VOID();
75 status_text_ = statusText;
76 }
77
GetMimeType()78 CefString CefResponseImpl::GetMimeType() {
79 base::AutoLock lock_scope(lock_);
80 return mime_type_;
81 }
82
SetMimeType(const CefString & mimeType)83 void CefResponseImpl::SetMimeType(const CefString& mimeType) {
84 base::AutoLock lock_scope(lock_);
85 CHECK_READONLY_RETURN_VOID();
86 mime_type_ = mimeType;
87 }
88
GetCharset()89 CefString CefResponseImpl::GetCharset() {
90 base::AutoLock lock_scope(lock_);
91 return charset_;
92 }
93
SetCharset(const CefString & charset)94 void CefResponseImpl::SetCharset(const CefString& charset) {
95 base::AutoLock lock_scope(lock_);
96 CHECK_READONLY_RETURN_VOID();
97 charset_ = charset;
98 }
99
GetHeaderByName(const CefString & name)100 CefString CefResponseImpl::GetHeaderByName(const CefString& name) {
101 base::AutoLock lock_scope(lock_);
102
103 std::string nameLower = name;
104 HttpHeaderUtils::MakeASCIILower(&nameLower);
105
106 auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, header_map_);
107 if (it != header_map_.end())
108 return it->second;
109
110 return CefString();
111 }
112
SetHeaderByName(const CefString & name,const CefString & value,bool overwrite)113 void CefResponseImpl::SetHeaderByName(const CefString& name,
114 const CefString& value,
115 bool overwrite) {
116 base::AutoLock lock_scope(lock_);
117 CHECK_READONLY_RETURN_VOID();
118
119 std::string nameLower = name;
120 HttpHeaderUtils::MakeASCIILower(&nameLower);
121
122 // There may be multiple values, so remove any first.
123 for (auto it = header_map_.begin(); it != header_map_.end();) {
124 if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) {
125 if (!overwrite)
126 return;
127 it = header_map_.erase(it);
128 } else {
129 ++it;
130 }
131 }
132
133 header_map_.insert(std::make_pair(name, value));
134 }
135
GetURL()136 CefString CefResponseImpl::GetURL() {
137 base::AutoLock lock_scope(lock_);
138 return url_;
139 }
140
SetURL(const CefString & url)141 void CefResponseImpl::SetURL(const CefString& url) {
142 base::AutoLock lock_scope(lock_);
143 CHECK_READONLY_RETURN_VOID();
144 url_ = url;
145 }
146
GetHeaderMap(HeaderMap & map)147 void CefResponseImpl::GetHeaderMap(HeaderMap& map) {
148 base::AutoLock lock_scope(lock_);
149 map = header_map_;
150 }
151
SetHeaderMap(const HeaderMap & headerMap)152 void CefResponseImpl::SetHeaderMap(const HeaderMap& headerMap) {
153 base::AutoLock lock_scope(lock_);
154 CHECK_READONLY_RETURN_VOID();
155 header_map_ = headerMap;
156 }
157
GetResponseHeaders()158 scoped_refptr<net::HttpResponseHeaders> CefResponseImpl::GetResponseHeaders() {
159 base::AutoLock lock_scope(lock_);
160
161 std::string mime_type = mime_type_;
162 if (mime_type.empty())
163 mime_type = "text/html";
164
165 std::multimap<std::string, std::string> extra_headers;
166 for (const auto& pair : header_map_)
167 extra_headers.insert(std::make_pair(pair.first, pair.second));
168
169 return net_service::MakeResponseHeaders(
170 status_code_, status_text_, mime_type, charset_, -1, extra_headers,
171 true /* allow_existing_header_override */);
172 }
173
SetResponseHeaders(const net::HttpResponseHeaders & headers)174 void CefResponseImpl::SetResponseHeaders(
175 const net::HttpResponseHeaders& headers) {
176 base::AutoLock lock_scope(lock_);
177 CHECK_READONLY_RETURN_VOID();
178
179 header_map_.clear();
180
181 size_t iter = 0;
182 std::string name, value;
183 while (headers.EnumerateHeaderLines(&iter, &name, &value))
184 header_map_.insert(std::make_pair(name, value));
185
186 status_code_ = headers.response_code();
187 status_text_ = headers.GetStatusText();
188
189 if (headers.IsRedirect(nullptr)) {
190 // Don't report Content-Type header values for redirects.
191 mime_type_.clear();
192 charset_.clear();
193 } else {
194 std::string mime_type, charset;
195 headers.GetMimeTypeAndCharset(&mime_type, &charset);
196 mime_type_ = mime_type;
197 charset_ = charset;
198 }
199 }
200
Set(const blink::WebURLResponse & response)201 void CefResponseImpl::Set(const blink::WebURLResponse& response) {
202 DCHECK(!response.IsNull());
203
204 base::AutoLock lock_scope(lock_);
205 CHECK_READONLY_RETURN_VOID();
206
207 blink::WebString str;
208 status_code_ = response.HttpStatusCode();
209 str = response.HttpStatusText();
210 status_text_ = str.Utf16();
211 str = response.MimeType();
212 mime_type_ = str.Utf16();
213 str = response.CurrentRequestUrl().GetString();
214 url_ = str.Utf16();
215
216 class HeaderVisitor : public blink::WebHTTPHeaderVisitor {
217 public:
218 explicit HeaderVisitor(HeaderMap* map) : map_(map) {}
219
220 void VisitHeader(const blink::WebString& name,
221 const blink::WebString& value) override {
222 map_->insert(std::make_pair(name.Utf16(), value.Utf16()));
223 }
224
225 private:
226 HeaderMap* map_;
227 };
228
229 HeaderVisitor visitor(&header_map_);
230 response.VisitHttpHeaderFields(&visitor);
231 }
232
SetReadOnly(bool read_only)233 void CefResponseImpl::SetReadOnly(bool read_only) {
234 base::AutoLock lock_scope(lock_);
235 read_only_ = read_only;
236 }
237