mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-24 07:58:11 +01:00
- Add cache awareness to CefURLRequest (issue #2283)
- Properly set referer values on server requests (issue #2278)
This commit is contained in:
parent
7e783d6a37
commit
facee1f750
@ -1222,15 +1222,26 @@ typedef enum {
|
|||||||
UR_FLAG_NONE = 0,
|
UR_FLAG_NONE = 0,
|
||||||
|
|
||||||
///
|
///
|
||||||
// If set the cache will be skipped when handling the request.
|
// If set the cache will be skipped when handling the request. Setting this
|
||||||
|
// value is equivalent to specifying the "Cache-Control: no-cache" request
|
||||||
|
// header. Setting this value in combination with UR_FLAG_ONLY_FROM_CACHE will
|
||||||
|
// cause the request to fail.
|
||||||
///
|
///
|
||||||
UR_FLAG_SKIP_CACHE = 1 << 0,
|
UR_FLAG_SKIP_CACHE = 1 << 0,
|
||||||
|
|
||||||
|
///
|
||||||
|
// If set the request will fail if it cannot be served from the cache (or some
|
||||||
|
// equivalent local store). Setting this value is equivalent to specifying the
|
||||||
|
// "Cache-Control: only-if-cached" request header. Setting this value in
|
||||||
|
// combination with UR_FLAG_SKIP_CACHE will cause the request to fail.
|
||||||
|
///
|
||||||
|
UR_FLAG_ONLY_FROM_CACHE = 1 << 1,
|
||||||
|
|
||||||
///
|
///
|
||||||
// If set user name, password, and cookies may be sent with the request, and
|
// If set user name, password, and cookies may be sent with the request, and
|
||||||
// cookies may be saved from the response.
|
// cookies may be saved from the response.
|
||||||
///
|
///
|
||||||
UR_FLAG_ALLOW_CACHED_CREDENTIALS = 1 << 1,
|
UR_FLAG_ALLOW_STORED_CREDENTIALS = 1 << 2,
|
||||||
|
|
||||||
///
|
///
|
||||||
// If set upload progress events will be generated when a request has a body.
|
// If set upload progress events will be generated when a request has a body.
|
||||||
@ -1240,14 +1251,14 @@ typedef enum {
|
|||||||
///
|
///
|
||||||
// If set the CefURLRequestClient::OnDownloadData method will not be called.
|
// If set the CefURLRequestClient::OnDownloadData method will not be called.
|
||||||
///
|
///
|
||||||
UR_FLAG_NO_DOWNLOAD_DATA = 1 << 6,
|
UR_FLAG_NO_DOWNLOAD_DATA = 1 << 4,
|
||||||
|
|
||||||
///
|
///
|
||||||
// If set 5XX redirect errors will be propagated to the observer instead of
|
// If set 5XX redirect errors will be propagated to the observer instead of
|
||||||
// automatically re-tried. This currently only applies for requests
|
// automatically re-tried. This currently only applies for requests
|
||||||
// originated in the browser process.
|
// originated in the browser process.
|
||||||
///
|
///
|
||||||
UR_FLAG_NO_RETRY_ON_5XX = 1 << 7,
|
UR_FLAG_NO_RETRY_ON_5XX = 1 << 5,
|
||||||
} cef_urlrequest_flags_t;
|
} cef_urlrequest_flags_t;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const char kReferrerLowerCase[] = "referer";
|
||||||
|
|
||||||
// Wrap a string in a unique_ptr to avoid extra copies.
|
// Wrap a string in a unique_ptr to avoid extra copies.
|
||||||
std::unique_ptr<std::string> CreateUniqueString(const void* data,
|
std::unique_ptr<std::string> CreateUniqueString(const void* data,
|
||||||
size_t data_size) {
|
size_t data_size) {
|
||||||
@ -67,18 +69,27 @@ CefRefPtr<CefRequest> CreateRequest(const std::string& address,
|
|||||||
post_data->AddElement(post_element);
|
post_data->AddElement(post_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string referer;
|
||||||
|
|
||||||
CefRequest::HeaderMap header_map;
|
CefRequest::HeaderMap header_map;
|
||||||
if (!info.headers.empty()) {
|
if (!info.headers.empty()) {
|
||||||
net::HttpServerRequestInfo::HeadersMap::const_iterator it =
|
net::HttpServerRequestInfo::HeadersMap::const_iterator it =
|
||||||
info.headers.begin();
|
info.headers.begin();
|
||||||
for (; it != info.headers.end(); ++it) {
|
for (; it != info.headers.end(); ++it) {
|
||||||
header_map.insert(std::make_pair(it->first, it->second));
|
// Don't include Referer in the header map.
|
||||||
|
if (base::LowerCaseEqualsASCII(it->first, kReferrerLowerCase)) {
|
||||||
|
referer = it->second;
|
||||||
|
} else {
|
||||||
|
header_map.insert(std::make_pair(it->first, it->second));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
|
CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
|
||||||
request->Set((is_websocket ? "ws://" : "http://") + address + info.path,
|
request->Set((is_websocket ? "ws://" : "http://") + address + info.path,
|
||||||
info.method, post_data, header_map);
|
info.method, post_data, header_map);
|
||||||
|
if (!referer.empty())
|
||||||
|
request->SetReferrer(referer, REFERRER_POLICY_DEFAULT);
|
||||||
request->SetReadOnly(true);
|
request->SetReadOnly(true);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// reserved. Use of this source code is governed by a BSD-style license that
|
// reserved. Use of this source code is governed by a BSD-style license that
|
||||||
// can be found in the LICENSE file.
|
// can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -44,8 +45,14 @@ namespace {
|
|||||||
|
|
||||||
const char kReferrerLowerCase[] = "referer";
|
const char kReferrerLowerCase[] = "referer";
|
||||||
const char kContentTypeLowerCase[] = "content-type";
|
const char kContentTypeLowerCase[] = "content-type";
|
||||||
|
const char kCacheControlLowerCase[] = "cache-control";
|
||||||
|
const char kCacheControlDirectiveNoCacheLowerCase[] = "no-cache";
|
||||||
|
const char kCacheControlDirectiveOnlyIfCachedLowerCase[] = "only-if-cached";
|
||||||
const char kApplicationFormURLEncoded[] = "application/x-www-form-urlencoded";
|
const char kApplicationFormURLEncoded[] = "application/x-www-form-urlencoded";
|
||||||
|
|
||||||
|
// Mask of values that configure the cache policy.
|
||||||
|
const int kURCachePolicyMask = (UR_FLAG_SKIP_CACHE | UR_FLAG_ONLY_FROM_CACHE);
|
||||||
|
|
||||||
// A subclass of net::UploadBytesElementReader that keeps the associated
|
// A subclass of net::UploadBytesElementReader that keeps the associated
|
||||||
// UploadElement alive until the request completes.
|
// UploadElement alive until the request completes.
|
||||||
class BytesElementReader : public net::UploadBytesElementReader {
|
class BytesElementReader : public net::UploadBytesElementReader {
|
||||||
@ -100,6 +107,71 @@ std::string GetURLRequestReferrer(const GURL& referrer_url) {
|
|||||||
return referrer_url.spec();
|
return referrer_url.spec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the cef_urlrequest_flags_t policy specified by the Cache-Control
|
||||||
|
// request header directives, if any. The directives are case-insensitive and
|
||||||
|
// some have an optional argument. Multiple directives are comma-separated.
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
||||||
|
// for details.
|
||||||
|
int GetCacheControlHeaderPolicy(CefRequest::HeaderMap headerMap) {
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
// Extract the Cache-Control header line.
|
||||||
|
{
|
||||||
|
CefRequest::HeaderMap::const_iterator it = headerMap.begin();
|
||||||
|
for (; it != headerMap.end(); ++it) {
|
||||||
|
if (base::LowerCaseEqualsASCII(it->first.ToString(),
|
||||||
|
kCacheControlLowerCase)) {
|
||||||
|
line = it->second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (!line.empty()) {
|
||||||
|
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
|
||||||
|
|
||||||
|
std::vector<base::StringPiece> pieces = base::SplitStringPiece(
|
||||||
|
line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||||
|
for (const auto& piece : pieces) {
|
||||||
|
if (base::LowerCaseEqualsASCII(piece,
|
||||||
|
kCacheControlDirectiveNoCacheLowerCase)) {
|
||||||
|
flags |= UR_FLAG_SKIP_CACHE;
|
||||||
|
} else if (base::LowerCaseEqualsASCII(
|
||||||
|
piece, kCacheControlDirectiveOnlyIfCachedLowerCase)) {
|
||||||
|
flags |= UR_FLAG_ONLY_FROM_CACHE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert cef_urlrequest_flags_t to blink::WebCachePolicy.
|
||||||
|
blink::WebCachePolicy GetWebCachePolicy(int ur_flags) {
|
||||||
|
if ((ur_flags & kURCachePolicyMask) == kURCachePolicyMask) {
|
||||||
|
return blink::WebCachePolicy::kBypassCacheLoadOnlyFromCache;
|
||||||
|
} else if (ur_flags & UR_FLAG_SKIP_CACHE) {
|
||||||
|
return blink::WebCachePolicy::kBypassingCache;
|
||||||
|
} else if (ur_flags & UR_FLAG_ONLY_FROM_CACHE) {
|
||||||
|
return blink::WebCachePolicy::kReturnCacheDataDontLoad;
|
||||||
|
}
|
||||||
|
return blink::WebCachePolicy::kUseProtocolCachePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert blink::WebCachePolicy to cef_urlrequest_flags_t.
|
||||||
|
int GetURCachePolicy(blink::WebCachePolicy web_policy) {
|
||||||
|
if (web_policy == blink::WebCachePolicy::kBypassCacheLoadOnlyFromCache) {
|
||||||
|
return kURCachePolicyMask;
|
||||||
|
} else if (web_policy == blink::WebCachePolicy::kBypassingCache) {
|
||||||
|
return UR_FLAG_SKIP_CACHE;
|
||||||
|
} else if (web_policy == blink::WebCachePolicy::kReturnCacheDataDontLoad) {
|
||||||
|
return UR_FLAG_ONLY_FROM_CACHE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
blink::WebString FilePathStringToWebString(
|
blink::WebString FilePathStringToWebString(
|
||||||
const base::FilePath::StringType& str) {
|
const base::FilePath::StringType& str) {
|
||||||
#if defined(OS_POSIX)
|
#if defined(OS_POSIX)
|
||||||
@ -216,10 +288,9 @@ CefRefPtr<CefRequest> CefRequest::Create() {
|
|||||||
|
|
||||||
CefRequestImpl::CefRequestImpl() : read_only_(false), track_changes_(false) {
|
CefRequestImpl::CefRequestImpl() : read_only_(false), track_changes_(false) {
|
||||||
// Verify that our enum matches Chromium's values.
|
// Verify that our enum matches Chromium's values.
|
||||||
static_assert(
|
static_assert(static_cast<int>(REFERRER_POLICY_LAST_VALUE) ==
|
||||||
static_cast<int>(REFERRER_POLICY_LAST_VALUE) ==
|
static_cast<int>(net::URLRequest::MAX_REFERRER_POLICY),
|
||||||
static_cast<int>(net::URLRequest::MAX_REFERRER_POLICY),
|
"enum mismatch");
|
||||||
"enum mismatch");
|
|
||||||
|
|
||||||
base::AutoLock lock_scope(lock_);
|
base::AutoLock lock_scope(lock_);
|
||||||
Reset();
|
Reset();
|
||||||
@ -495,10 +566,9 @@ void CefRequestImpl::Set(const blink::WebURLRequest& request) {
|
|||||||
|
|
||||||
site_for_cookies_ = request.SiteForCookies();
|
site_for_cookies_ = request.SiteForCookies();
|
||||||
|
|
||||||
if (request.GetCachePolicy() == blink::WebCachePolicy::kBypassingCache)
|
flags_ |= GetURCachePolicy(request.GetCachePolicy());
|
||||||
flags_ |= UR_FLAG_SKIP_CACHE;
|
|
||||||
if (request.AllowStoredCredentials())
|
if (request.AllowStoredCredentials())
|
||||||
flags_ |= UR_FLAG_ALLOW_CACHED_CREDENTIALS;
|
flags_ |= UR_FLAG_ALLOW_STORED_CREDENTIALS;
|
||||||
if (request.ReportUploadProgress())
|
if (request.ReportUploadProgress())
|
||||||
flags_ |= UR_FLAG_REPORT_UPLOAD_PROGRESS;
|
flags_ |= UR_FLAG_REPORT_UPLOAD_PROGRESS;
|
||||||
}
|
}
|
||||||
@ -545,12 +615,16 @@ void CefRequestImpl::Get(blink::WebURLRequest& request,
|
|||||||
if (!site_for_cookies_.is_empty())
|
if (!site_for_cookies_.is_empty())
|
||||||
request.SetSiteForCookies(site_for_cookies_);
|
request.SetSiteForCookies(site_for_cookies_);
|
||||||
|
|
||||||
request.SetCachePolicy((flags_ & UR_FLAG_SKIP_CACHE)
|
int flags = flags_;
|
||||||
? blink::WebCachePolicy::kBypassingCache
|
if (!(flags & kURCachePolicyMask)) {
|
||||||
: blink::WebCachePolicy::kUseProtocolCachePolicy);
|
// Only consider the Cache-Control directives when a cache policy is not
|
||||||
|
// explicitly set on the request.
|
||||||
|
flags |= GetCacheControlHeaderPolicy(headermap_);
|
||||||
|
}
|
||||||
|
request.SetCachePolicy(GetWebCachePolicy(flags));
|
||||||
|
|
||||||
SETBOOLFLAG(request, flags_, SetAllowStoredCredentials,
|
SETBOOLFLAG(request, flags_, SetAllowStoredCredentials,
|
||||||
UR_FLAG_ALLOW_CACHED_CREDENTIALS);
|
UR_FLAG_ALLOW_STORED_CREDENTIALS);
|
||||||
SETBOOLFLAG(request, flags_, SetReportUploadProgress,
|
SETBOOLFLAG(request, flags_, SetReportUploadProgress,
|
||||||
UR_FLAG_REPORT_UPLOAD_PROGRESS);
|
UR_FLAG_REPORT_UPLOAD_PROGRESS);
|
||||||
}
|
}
|
||||||
@ -576,12 +650,14 @@ void CefRequestImpl::Get(const CefMsg_LoadRequest_Params& params,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CefRequest::HeaderMap headerMap;
|
||||||
if (!params.headers.empty()) {
|
if (!params.headers.empty()) {
|
||||||
for (net::HttpUtil::HeadersIterator i(params.headers.begin(),
|
for (net::HttpUtil::HeadersIterator i(params.headers.begin(),
|
||||||
params.headers.end(), "\n");
|
params.headers.end(), "\n");
|
||||||
i.GetNext();) {
|
i.GetNext();) {
|
||||||
request.AddHTTPHeaderField(blink::WebString::FromUTF8(i.name()),
|
request.AddHTTPHeaderField(blink::WebString::FromUTF8(i.name()),
|
||||||
blink::WebString::FromUTF8(i.values()));
|
blink::WebString::FromUTF8(i.values()));
|
||||||
|
headerMap.insert(std::make_pair(i.name(), i.values()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,12 +700,16 @@ void CefRequestImpl::Get(const CefMsg_LoadRequest_Params& params,
|
|||||||
if (params.site_for_cookies.is_valid())
|
if (params.site_for_cookies.is_valid())
|
||||||
request.SetSiteForCookies(params.site_for_cookies);
|
request.SetSiteForCookies(params.site_for_cookies);
|
||||||
|
|
||||||
request.SetCachePolicy((params.load_flags & UR_FLAG_SKIP_CACHE)
|
int flags = params.load_flags;
|
||||||
? blink::WebCachePolicy::kBypassingCache
|
if (!(flags & kURCachePolicyMask)) {
|
||||||
: blink::WebCachePolicy::kUseProtocolCachePolicy);
|
// Only consider the Cache-Control directives when a cache policy is not
|
||||||
|
// explicitly set on the request.
|
||||||
|
flags |= GetCacheControlHeaderPolicy(headerMap);
|
||||||
|
}
|
||||||
|
request.SetCachePolicy(GetWebCachePolicy(flags));
|
||||||
|
|
||||||
SETBOOLFLAG(request, params.load_flags, SetAllowStoredCredentials,
|
SETBOOLFLAG(request, params.load_flags, SetAllowStoredCredentials,
|
||||||
UR_FLAG_ALLOW_CACHED_CREDENTIALS);
|
UR_FLAG_ALLOW_STORED_CREDENTIALS);
|
||||||
SETBOOLFLAG(request, params.load_flags, SetReportUploadProgress,
|
SETBOOLFLAG(request, params.load_flags, SetReportUploadProgress,
|
||||||
UR_FLAG_REPORT_UPLOAD_PROGRESS);
|
UR_FLAG_REPORT_UPLOAD_PROGRESS);
|
||||||
}
|
}
|
||||||
@ -726,21 +806,31 @@ void CefRequestImpl::Get(net::URLFetcher& fetcher,
|
|||||||
if (!site_for_cookies_.is_empty())
|
if (!site_for_cookies_.is_empty())
|
||||||
fetcher.SetInitiator(url::Origin(site_for_cookies_));
|
fetcher.SetInitiator(url::Origin(site_for_cookies_));
|
||||||
|
|
||||||
if (flags_ & UR_FLAG_NO_RETRY_ON_5XX)
|
int flags = flags_;
|
||||||
fetcher.SetAutomaticallyRetryOn5xx(false);
|
if (!(flags & kURCachePolicyMask)) {
|
||||||
|
// Only consider the Cache-Control directives when a cache policy is not
|
||||||
int load_flags = 0;
|
// explicitly set on the request.
|
||||||
|
flags |= GetCacheControlHeaderPolicy(headerMap);
|
||||||
if (flags_ & UR_FLAG_SKIP_CACHE)
|
|
||||||
load_flags |= net::LOAD_BYPASS_CACHE;
|
|
||||||
|
|
||||||
if (!(flags_ & UR_FLAG_ALLOW_CACHED_CREDENTIALS)) {
|
|
||||||
load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
|
|
||||||
load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
|
|
||||||
load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fetcher.SetLoadFlags(load_flags);
|
if (flags & UR_FLAG_NO_RETRY_ON_5XX)
|
||||||
|
fetcher.SetAutomaticallyRetryOn5xx(false);
|
||||||
|
|
||||||
|
int net_flags = 0;
|
||||||
|
|
||||||
|
if (flags & UR_FLAG_SKIP_CACHE) {
|
||||||
|
net_flags |= net::LOAD_BYPASS_CACHE;
|
||||||
|
}
|
||||||
|
if (flags & UR_FLAG_ONLY_FROM_CACHE) {
|
||||||
|
net_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & UR_FLAG_ALLOW_STORED_CREDENTIALS)) {
|
||||||
|
net_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA |
|
||||||
|
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetcher.SetLoadFlags(net_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefRequestImpl::SetReadOnly(bool read_only) {
|
void CefRequestImpl::SetReadOnly(bool read_only) {
|
||||||
|
@ -966,6 +966,7 @@ class StaticHttpRequestRunner : public HttpTestRunner::RequestRunner {
|
|||||||
CefRefPtr<CefRequest> request = CreateTestServerRequest(
|
CefRefPtr<CefRequest> request = CreateTestServerRequest(
|
||||||
path, "POST", "foo=bar&choo=too", "application/x-www-form-urlencoded",
|
path, "POST", "foo=bar&choo=too", "application/x-www-form-urlencoded",
|
||||||
request_headers);
|
request_headers);
|
||||||
|
request->SetReferrer("http://tests/referer.html", REFERRER_POLICY_DEFAULT);
|
||||||
|
|
||||||
HttpServerResponse response(HttpServerResponse::TYPE_CUSTOM);
|
HttpServerResponse response(HttpServerResponse::TYPE_CUSTOM);
|
||||||
response.response_code = 202;
|
response.response_code = 202;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user