| // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights |
| // reserved. Use of this source code is governed by a BSD-style license that |
| // can be found in the LICENSE file. |
| |
| #include "libcef/common/response_impl.h" |
| |
| #include <string> |
| |
| #include "libcef/common/net/http_header_utils.h" |
| #include "libcef/common/net_service/net_service_util.h" |
| |
| #include "base/logging.h" |
| #include "base/strings/string_util.h" |
| #include "net/http/http_request_headers.h" |
| #include "net/http/http_response_headers.h" |
| #include "third_party/blink/public/platform/web_http_header_visitor.h" |
| #include "third_party/blink/public/platform/web_string.h" |
| #include "third_party/blink/public/platform/web_url.h" |
| #include "third_party/blink/public/platform/web_url_response.h" |
| |
| #define CHECK_READONLY_RETURN_VOID() \ |
| if (read_only_) { \ |
| NOTREACHED() << "object is read only"; \ |
| return; \ |
| } |
| |
| // CefResponse ---------------------------------------------------------------- |
| |
| // static |
| CefRefPtr<CefResponse> CefResponse::Create() { |
| CefRefPtr<CefResponse> response(new CefResponseImpl()); |
| return response; |
| } |
| |
| // CefResponseImpl ------------------------------------------------------------ |
| |
| CefResponseImpl::CefResponseImpl() |
| : error_code_(ERR_NONE), status_code_(0), read_only_(false) {} |
| |
| bool CefResponseImpl::IsReadOnly() { |
| base::AutoLock lock_scope(lock_); |
| return read_only_; |
| } |
| |
| cef_errorcode_t CefResponseImpl::GetError() { |
| base::AutoLock lock_scope(lock_); |
| return error_code_; |
| } |
| |
| void CefResponseImpl::SetError(cef_errorcode_t error) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| error_code_ = error; |
| } |
| |
| int CefResponseImpl::GetStatus() { |
| base::AutoLock lock_scope(lock_); |
| return status_code_; |
| } |
| |
| void CefResponseImpl::SetStatus(int status) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| status_code_ = status; |
| } |
| |
| CefString CefResponseImpl::GetStatusText() { |
| base::AutoLock lock_scope(lock_); |
| return status_text_; |
| } |
| |
| void CefResponseImpl::SetStatusText(const CefString& statusText) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| status_text_ = statusText; |
| } |
| |
| CefString CefResponseImpl::GetMimeType() { |
| base::AutoLock lock_scope(lock_); |
| return mime_type_; |
| } |
| |
| void CefResponseImpl::SetMimeType(const CefString& mimeType) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| mime_type_ = mimeType; |
| } |
| |
| CefString CefResponseImpl::GetCharset() { |
| base::AutoLock lock_scope(lock_); |
| return charset_; |
| } |
| |
| void CefResponseImpl::SetCharset(const CefString& charset) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| charset_ = charset; |
| } |
| |
| CefString CefResponseImpl::GetHeaderByName(const CefString& name) { |
| base::AutoLock lock_scope(lock_); |
| |
| std::string nameLower = name; |
| HttpHeaderUtils::MakeASCIILower(&nameLower); |
| |
| auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, header_map_); |
| if (it != header_map_.end()) |
| return it->second; |
| |
| return CefString(); |
| } |
| |
| void CefResponseImpl::SetHeaderByName(const CefString& name, |
| const CefString& value, |
| bool overwrite) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| |
| std::string nameLower = name; |
| HttpHeaderUtils::MakeASCIILower(&nameLower); |
| |
| // There may be multiple values, so remove any first. |
| for (auto it = header_map_.begin(); it != header_map_.end();) { |
| if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) { |
| if (!overwrite) |
| return; |
| it = header_map_.erase(it); |
| } else { |
| ++it; |
| } |
| } |
| |
| header_map_.insert(std::make_pair(name, value)); |
| } |
| |
| CefString CefResponseImpl::GetURL() { |
| base::AutoLock lock_scope(lock_); |
| return url_; |
| } |
| |
| void CefResponseImpl::SetURL(const CefString& url) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| url_ = url; |
| } |
| |
| void CefResponseImpl::GetHeaderMap(HeaderMap& map) { |
| base::AutoLock lock_scope(lock_); |
| map = header_map_; |
| } |
| |
| void CefResponseImpl::SetHeaderMap(const HeaderMap& headerMap) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| header_map_ = headerMap; |
| } |
| |
| scoped_refptr<net::HttpResponseHeaders> CefResponseImpl::GetResponseHeaders() { |
| base::AutoLock lock_scope(lock_); |
| |
| std::string mime_type = mime_type_; |
| if (mime_type.empty()) |
| mime_type = "text/html"; |
| |
| std::multimap<std::string, std::string> extra_headers; |
| for (const auto& pair : header_map_) |
| extra_headers.insert(std::make_pair(pair.first, pair.second)); |
| |
| return net_service::MakeResponseHeaders( |
| status_code_, status_text_, mime_type, charset_, -1, extra_headers, |
| true /* allow_existing_header_override */); |
| } |
| |
| void CefResponseImpl::SetResponseHeaders( |
| const net::HttpResponseHeaders& headers) { |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| |
| header_map_.clear(); |
| |
| size_t iter = 0; |
| std::string name, value; |
| while (headers.EnumerateHeaderLines(&iter, &name, &value)) |
| header_map_.insert(std::make_pair(name, value)); |
| |
| status_code_ = headers.response_code(); |
| status_text_ = headers.GetStatusText(); |
| |
| if (headers.IsRedirect(nullptr)) { |
| // Don't report Content-Type header values for redirects. |
| mime_type_.clear(); |
| charset_.clear(); |
| } else { |
| std::string mime_type, charset; |
| headers.GetMimeTypeAndCharset(&mime_type, &charset); |
| mime_type_ = mime_type; |
| charset_ = charset; |
| } |
| } |
| |
| void CefResponseImpl::Set(const blink::WebURLResponse& response) { |
| DCHECK(!response.IsNull()); |
| |
| base::AutoLock lock_scope(lock_); |
| CHECK_READONLY_RETURN_VOID(); |
| |
| blink::WebString str; |
| status_code_ = response.HttpStatusCode(); |
| str = response.HttpStatusText(); |
| status_text_ = str.Utf16(); |
| str = response.MimeType(); |
| mime_type_ = str.Utf16(); |
| str = response.CurrentRequestUrl().GetString(); |
| url_ = str.Utf16(); |
| |
| class HeaderVisitor : public blink::WebHTTPHeaderVisitor { |
| public: |
| explicit HeaderVisitor(HeaderMap* map) : map_(map) {} |
| |
| void VisitHeader(const blink::WebString& name, |
| const blink::WebString& value) override { |
| map_->insert(std::make_pair(name.Utf16(), value.Utf16())); |
| } |
| |
| private: |
| HeaderMap* map_; |
| }; |
| |
| HeaderVisitor visitor(&header_map_); |
| response.VisitHttpHeaderFields(&visitor); |
| } |
| |
| void CefResponseImpl::SetReadOnly(bool read_only) { |
| base::AutoLock lock_scope(lock_); |
| read_only_ = read_only; |
| } |