diff --git a/include/capi/cef_urlrequest_capi.h b/include/capi/cef_urlrequest_capi.h index 12a8380ac..7d25fcfa9 100644 --- a/include/capi/cef_urlrequest_capi.h +++ b/include/capi/cef_urlrequest_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=71979633d571d03ae236d52b09c4bb63bfa01b45$ +// $hash=f877ff032d10d23cb5f71e01a8770347c1e66335$ // #ifndef CEF_INCLUDE_CAPI_CEF_URLREQUEST_CAPI_H_ @@ -99,6 +99,12 @@ typedef struct _cef_urlrequest_t { struct _cef_response_t*(CEF_CALLBACK* get_response)( struct _cef_urlrequest_t* self); + /// + // Returns true (1) if the response body was served from the cache. This + // includes responses for which revalidation was required. + /// + int(CEF_CALLBACK* response_was_cached)(struct _cef_urlrequest_t* self); + /// // Cancel the request. /// diff --git a/include/cef_urlrequest.h b/include/cef_urlrequest.h index a8e15ed96..889386ad1 100644 --- a/include/cef_urlrequest.h +++ b/include/cef_urlrequest.h @@ -114,6 +114,13 @@ class CefURLRequest : public virtual CefBaseRefCounted { /*--cef()--*/ virtual CefRefPtr GetResponse() = 0; + /// + // Returns true if the response body was served from the cache. This includes + // responses for which revalidation was required. + /// + /*--cef()--*/ + virtual bool ResponseWasCached() = 0; + /// // Cancel the request. /// diff --git a/libcef/browser/browser_urlrequest_impl.cc b/libcef/browser/browser_urlrequest_impl.cc index 785f90b2c..5124993ff 100644 --- a/libcef/browser/browser_urlrequest_impl.cc +++ b/libcef/browser/browser_urlrequest_impl.cc @@ -139,6 +139,7 @@ class CefBrowserURLRequest::Context task_runner_(CefTaskRunnerImpl::GetCurrentTaskRunner()), status_(UR_IO_PENDING), error_code_(ERR_NONE), + response_was_cached_(false), upload_data_size_(0), got_upload_progress_complete_(false) { // Mark the request as read-only. @@ -320,11 +321,12 @@ class CefBrowserURLRequest::Context client_->OnUploadProgress(url_request_.get(), current, total); } - CefRefPtr request() { return request_; } - CefRefPtr client() { return client_; } - CefURLRequest::Status status() { return status_; } - CefURLRequest::ErrorCode error_code() { return error_code_; } - CefRefPtr response() { return response_; } + CefRefPtr request() const { return request_; } + CefRefPtr client() const { return client_; } + CefURLRequest::Status status() const { return status_; } + CefURLRequest::ErrorCode error_code() const { return error_code_; } + CefRefPtr response() const { return response_; } + bool response_was_cached() const { return response_was_cached_; } private: friend class base::RefCountedThreadSafe; @@ -349,6 +351,7 @@ class CefBrowserURLRequest::Context void OnResponse() { if (fetcher_.get()) { + response_was_cached_ = fetcher_->WasCached(); response_ = new CefResponseImpl(); CefResponseImpl* responseImpl = static_cast(response_.get()); @@ -372,6 +375,7 @@ class CefBrowserURLRequest::Context CefURLRequest::Status status_; CefURLRequest::ErrorCode error_code_; CefRefPtr response_; + bool response_was_cached_; int64 upload_data_size_; bool got_upload_progress_complete_; @@ -462,6 +466,12 @@ CefRefPtr CefBrowserURLRequest::GetResponse() { return context_->response(); } +bool CefBrowserURLRequest::ResponseWasCached() { + if (!VerifyContext()) + return false; + return context_->response_was_cached(); +} + void CefBrowserURLRequest::Cancel() { if (!VerifyContext()) return; diff --git a/libcef/browser/browser_urlrequest_impl.h b/libcef/browser/browser_urlrequest_impl.h index 6b465d16e..b34e584b5 100644 --- a/libcef/browser/browser_urlrequest_impl.h +++ b/libcef/browser/browser_urlrequest_impl.h @@ -26,6 +26,7 @@ class CefBrowserURLRequest : public CefURLRequest { Status GetRequestStatus() override; ErrorCode GetRequestError() override; CefRefPtr GetResponse() override; + bool ResponseWasCached() override; void Cancel() override; private: diff --git a/libcef/renderer/render_urlrequest_impl.cc b/libcef/renderer/render_urlrequest_impl.cc index d9fc440d8..7bfe0a4ed 100644 --- a/libcef/renderer/render_urlrequest_impl.cc +++ b/libcef/renderer/render_urlrequest_impl.cc @@ -10,6 +10,7 @@ #include "libcef/common/response_impl.h" #include "libcef/common/task_runner_impl.h" #include "libcef/renderer/content_renderer_client.h" +#include "libcef/renderer/webkit_glue.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" @@ -73,6 +74,7 @@ class CefRenderURLRequest::Context task_runner_(CefTaskRunnerImpl::GetCurrentTaskRunner()), status_(UR_IO_PENDING), error_code_(ERR_NONE), + response_was_cached_(false), upload_data_size_(0), got_upload_progress_complete_(false), download_data_received_(0), @@ -127,6 +129,7 @@ class CefRenderURLRequest::Context void OnResponse(const WebURLResponse& response) { DCHECK(CalledOnValidThread()); + response_was_cached_ = webkit_glue::ResponseWasCached(response); response_ = CefResponse::Create(); CefResponseImpl* responseImpl = static_cast(response_.get()); @@ -190,11 +193,12 @@ class CefRenderURLRequest::Context client_->OnUploadProgress(url_request_.get(), current, total); } - CefRefPtr request() { return request_; } - CefRefPtr client() { return client_; } - CefURLRequest::Status status() { return status_; } - CefURLRequest::ErrorCode error_code() { return error_code_; } - CefRefPtr response() { return response_; } + CefRefPtr request() const { return request_; } + CefRefPtr client() const { return client_; } + CefURLRequest::Status status() const { return status_; } + CefURLRequest::ErrorCode error_code() const { return error_code_; } + CefRefPtr response() const { return response_; } + bool response_was_cached() const { return response_was_cached_; } private: friend class base::RefCountedThreadSafe; @@ -220,6 +224,7 @@ class CefRenderURLRequest::Context CefURLRequest::Status status_; CefURLRequest::ErrorCode error_code_; CefRefPtr response_; + bool response_was_cached_; std::unique_ptr loader_; std::unique_ptr url_client_; int64_t upload_data_size_; @@ -319,6 +324,12 @@ CefRefPtr CefRenderURLRequest::GetResponse() { return context_->response(); } +bool CefRenderURLRequest::ResponseWasCached() { + if (!VerifyContext()) + return false; + return context_->response_was_cached(); +} + void CefRenderURLRequest::Cancel() { if (!VerifyContext()) return; diff --git a/libcef/renderer/render_urlrequest_impl.h b/libcef/renderer/render_urlrequest_impl.h index fb8b8b009..905b1f6f9 100644 --- a/libcef/renderer/render_urlrequest_impl.h +++ b/libcef/renderer/render_urlrequest_impl.h @@ -25,6 +25,7 @@ class CefRenderURLRequest : public CefURLRequest { Status GetRequestStatus() override; ErrorCode GetRequestError() override; CefRefPtr GetResponse() override; + bool ResponseWasCached() override; void Cancel() override; private: diff --git a/libcef/renderer/webkit_glue.cc b/libcef/renderer/webkit_glue.cc index 18943ae56..3070a2b77 100644 --- a/libcef/renderer/webkit_glue.cc +++ b/libcef/renderer/webkit_glue.cc @@ -207,4 +207,8 @@ CefScriptForbiddenScope::CefScriptForbiddenScope() : impl_(new Impl()) {} CefScriptForbiddenScope::~CefScriptForbiddenScope() {} +bool ResponseWasCached(const blink::WebURLResponse& response) { + return response.ToResourceResponse().WasCached(); +} + } // namespace webkit_glue diff --git a/libcef/renderer/webkit_glue.h b/libcef/renderer/webkit_glue.h index 3f1b3c350..8b4a12fff 100644 --- a/libcef/renderer/webkit_glue.h +++ b/libcef/renderer/webkit_glue.h @@ -22,6 +22,7 @@ class WebElement; class WebLocalFrame; class WebNode; class WebString; +class WebURLResponse; class WebView; } // namespace blink @@ -81,6 +82,8 @@ class BLINK_EXPORT CefScriptForbiddenScope final { DISALLOW_COPY_AND_ASSIGN(CefScriptForbiddenScope); }; +BLINK_EXPORT bool ResponseWasCached(const blink::WebURLResponse& response); + } // namespace webkit_glue #endif // CEF_LIBCEF_RENDERER_WEBKIT_GLUE_H_ diff --git a/libcef_dll/cpptoc/urlrequest_cpptoc.cc b/libcef_dll/cpptoc/urlrequest_cpptoc.cc index 097c2c73d..1f4c6656b 100644 --- a/libcef_dll/cpptoc/urlrequest_cpptoc.cc +++ b/libcef_dll/cpptoc/urlrequest_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=f7018df83933208988d855d87dbb9e153a8983b4$ +// $hash=07e19d965f0eaea30c4fe94f76fbb4571568b8b3$ // #include "libcef_dll/cpptoc/urlrequest_cpptoc.h" @@ -128,6 +128,21 @@ urlrequest_get_response(struct _cef_urlrequest_t* self) { return CefResponseCppToC::Wrap(_retval); } +int CEF_CALLBACK +urlrequest_response_was_cached(struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefURLRequestCppToC::Get(self)->ResponseWasCached(); + + // Return type: bool + return _retval; +} + void CEF_CALLBACK urlrequest_cancel(struct _cef_urlrequest_t* self) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -149,6 +164,7 @@ CefURLRequestCppToC::CefURLRequestCppToC() { GetStruct()->get_request_status = urlrequest_get_request_status; GetStruct()->get_request_error = urlrequest_get_request_error; GetStruct()->get_response = urlrequest_get_response; + GetStruct()->response_was_cached = urlrequest_response_was_cached; GetStruct()->cancel = urlrequest_cancel; } diff --git a/libcef_dll/ctocpp/urlrequest_ctocpp.cc b/libcef_dll/ctocpp/urlrequest_ctocpp.cc index cfb7e6d74..07bfbc335 100644 --- a/libcef_dll/ctocpp/urlrequest_ctocpp.cc +++ b/libcef_dll/ctocpp/urlrequest_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=78d98006142b5694aaf16320761f55ad19104c40$ +// $hash=f4e93b00934fd541c9ab0b0a43da21ece8ccddaf$ // #include "libcef_dll/ctocpp/urlrequest_ctocpp.h" @@ -118,6 +118,20 @@ CefRefPtr CefURLRequestCToCpp::GetResponse() { return CefResponseCToCpp::Wrap(_retval); } +bool CefURLRequestCToCpp::ResponseWasCached() { + cef_urlrequest_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, response_was_cached)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = _struct->response_was_cached(_struct); + + // Return type: bool + return _retval ? true : false; +} + void CefURLRequestCToCpp::Cancel() { cef_urlrequest_t* _struct = GetStruct(); if (CEF_MEMBER_MISSING(_struct, cancel)) diff --git a/libcef_dll/ctocpp/urlrequest_ctocpp.h b/libcef_dll/ctocpp/urlrequest_ctocpp.h index b3b937a8f..5ab281d1e 100644 --- a/libcef_dll/ctocpp/urlrequest_ctocpp.h +++ b/libcef_dll/ctocpp/urlrequest_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=8f301ab7ac41ee16f9e8d5206f2c2b3d0f0fa5d2$ +// $hash=82b495b11a2564be98ffb520fefe8b2ea941c977$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CTOCPP_H_ @@ -38,6 +38,7 @@ class CefURLRequestCToCpp : public CefCToCppRefCounted GetResponse() OVERRIDE; + bool ResponseWasCached() OVERRIDE; void Cancel() OVERRIDE; }; diff --git a/tests/ceftests/urlrequest_unittest.cc b/tests/ceftests/urlrequest_unittest.cc index 7e8af6a35..b04476a9e 100644 --- a/tests/ceftests/urlrequest_unittest.cc +++ b/tests/ceftests/urlrequest_unittest.cc @@ -89,6 +89,7 @@ struct RequestRunSettings { expect_send_cookie(false), expect_save_cookie(false), expect_follow_redirect(true), + expect_response_was_cached(false), expected_send_count(-1), expected_receive_count(-1) {} @@ -140,6 +141,9 @@ struct RequestRunSettings { // If true the redirect is expected to be followed. bool expect_follow_redirect; + // If true the response is expected to be served from cache. + bool expect_response_was_cached; + // The expected number of requests to send, or -1 if unspecified. // Used only with the server backend. int expected_send_count; @@ -960,7 +964,10 @@ class RequestClient : public CefURLRequestClient { download_progress_ct_(0), download_data_ct_(0), upload_total_(0), - download_total_(0) { + download_total_(0), + status_(UR_UNKNOWN), + error_code_(ERR_NONE), + response_was_cached_(false) { EXPECT_FALSE(complete_callback_.is_null()); } @@ -971,6 +978,7 @@ class RequestClient : public CefURLRequestClient { EXPECT_TRUE(request_->IsReadOnly()); status_ = request->GetRequestStatus(); error_code_ = request->GetRequestError(); + response_was_cached_ = request->ResponseWasCached(); response_ = request->GetResponse(); if (response_) { EXPECT_TRUE(response_->IsReadOnly()); @@ -1031,6 +1039,7 @@ class RequestClient : public CefURLRequestClient { CefURLRequest::Status status_; CefURLRequest::ErrorCode error_code_; CefRefPtr response_; + bool response_was_cached_; private: IMPLEMENT_REFCOUNTING(RequestClient); @@ -1373,6 +1382,20 @@ class RequestTestRunner : public base::RefCountedThreadSafe { // should receive cached data. settings_.expected_send_count = 3; settings_.expected_receive_count = 1; + settings_.setup_next_request = + base::Bind(&RequestTestRunner::SetupCacheWithControlTestNext, this); + + complete_callback.Run(); + } + + void SetupCacheWithControlTestNext(int next_send_count, + const base::Closure& complete_callback) { + // Only handle from the cache. + settings_.expect_response_was_cached = true; + + // The following requests will use the same setup, so no more callbacks + // are required. + settings_.setup_next_request.Reset(); complete_callback.Run(); } @@ -1475,6 +1498,7 @@ class RequestTestRunner : public base::RefCountedThreadSafe { // Only handle from the cache. settings_.request->SetFlags(UR_FLAG_ONLY_FROM_CACHE); + settings_.expect_response_was_cached = true; // The following requests will use the same setup, so no more callbacks // are required. @@ -1508,6 +1532,7 @@ class RequestTestRunner : public base::RefCountedThreadSafe { CefRequest::HeaderMap headerMap; headerMap.insert(std::make_pair(kCacheControlHeader, "only-if-cached")); settings_.request->SetHeaderMap(headerMap); + settings_.expect_response_was_cached = true; // The following requests will use the same setup, so no more callbacks // are required. @@ -1555,6 +1580,9 @@ class RequestTestRunner : public base::RefCountedThreadSafe { if (expected_response && client->response_) TestResponseEqual(expected_response, client->response_, true); + EXPECT_EQ(settings_.expect_response_was_cached, + client->response_was_cached_); + EXPECT_EQ(1, client->request_complete_ct_); if (settings_.expect_upload_progress) {