Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(687)

Unified Diff: webkit/media/buffered_resource_loader.cc

Issue 10387200: Suppress pause-and-buffer behavior when the HTTP response won't satisfy future requests via cache. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Alternative implementation requiring no further WebKit changes Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/media/buffered_resource_loader.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/media/buffered_resource_loader.cc
diff --git a/webkit/media/buffered_resource_loader.cc b/webkit/media/buffered_resource_loader.cc
index 14ca0a12625058e61d70919b3de945f23cb05cbc..2afc2ac350dc657da8893c5e7e1104dd367f6ed7 100644
--- a/webkit/media/buffered_resource_loader.cc
+++ b/webkit/media/buffered_resource_loader.cc
@@ -4,13 +4,18 @@
#include "webkit/media/buffered_resource_loader.h"
+#include <math.h>
+
#include "base/callback_helpers.h"
#include "base/format_macros.h"
+#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "media/base/media_log.h"
#include "net/http/http_request_headers.h"
+#include "net/http/http_util.h"
+#include "net/http/http_version.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderOptions.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h"
@@ -18,6 +23,8 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLResponse.h"
+using base::Time;
+using base::TimeDelta;
using WebKit::WebFrame;
using WebKit::WebString;
using WebKit::WebURLError;
@@ -111,6 +118,7 @@ BufferedResourceLoader::BufferedResourceLoader(
: buffer_(kMinBufferCapacity, kMinBufferCapacity),
loader_failed_(false),
defer_strategy_(strategy),
+ might_be_reused_from_cache_in_future_(true),
range_supported_(false),
saved_forward_capacity_(0),
url_(url),
@@ -352,6 +360,96 @@ void BufferedResourceLoader::didSendData(
NOTIMPLEMENTED();
}
+// Reasons that a cached WebURLResponse will *not* prevent a future request to
+// the server.
+enum UncacheableReason {
+ kNoData = 1, // Not 200 or 206.
+ kPre11PartialResponse = 2, // 206 but HTTP version < 1.1.
+ kNoStrongValidatorOnPartialResponse = 3, // 206, no strong validator.
+ kNoValidatorOnFullResponse = 4, // 200, no strong or weak validator.
+ kShortMaxAge = 5, // Max age less than 1h (arbitrary value).
+ kExpiresTooSoon = 6, // Expires in less than 1h (arbitrary value).
+ kHasMustRevalidate = 7, // Response asks for revalidation.
+ kNoCache = 8, // Response included a no-cache header.
+ kNoStore = 9, // Response included a no-store header.
+ kMaxReason // Needs to be one more than max legitimate reason.
+};
+
+// Return true if "response" might be used for a future request (using the disk
+// cache). This is basically a laundry list of reasons we *know* the response
+// won't be useful in the future.
+static bool MightBeReusedFromCacheInFuture(const WebURLResponse& response) {
darin (slow to review) 2012/05/22 05:30:59 style nit: usually best not to interrupt the defin
+ std::vector<UncacheableReason> reasons;
darin (slow to review) 2012/05/22 05:30:59 what's the point of building up this vector? why
+ const int code = response.httpStatusCode();
+ const int version = response.httpVersion();
+ const net::HttpVersion http_version =
+ version == WebURLResponse::HTTP_1_1 ? net::HttpVersion(1, 1) :
+ version == WebURLResponse::HTTP_1_0 ? net::HttpVersion(1, 0) :
+ version == WebURLResponse::HTTP_0_9 ? net::HttpVersion(0, 9) :
+ net::HttpVersion();
+ if (code != kHttpOK && code != kHttpPartialContent)
+ reasons.push_back(kNoData);
+ if (http_version < net::HttpVersion(1, 1) && code == kHttpPartialContent)
+ reasons.push_back(kPre11PartialResponse);
+ if (!net::HttpUtil::HasStrongValidators(
+ http_version,
+ response.httpHeaderField("etag").utf8(),
+ response.httpHeaderField("Last-Modified").utf8(),
+ response.httpHeaderField("Date").utf8())) {
+ if (code == kHttpPartialContent)
+ reasons.push_back(kNoStrongValidatorOnPartialResponse);
+ else if (code == kHttpOK)
+ reasons.push_back(kNoValidatorOnFullResponse);
+ }
+
+ std::string cache_control_header =
+ response.httpHeaderField("cache-control").utf8();
+ StringToLowerASCII(&cache_control_header);
+ if (cache_control_header.find("no-cache") != std::string::npos)
+ reasons.push_back(kNoCache);
+ if (cache_control_header.find("no-store") != std::string::npos)
+ reasons.push_back(kNoStore);
+ if (cache_control_header.find("must-revalidate") != std::string::npos)
+ reasons.push_back(kHasMustRevalidate);
+
+ const TimeDelta kMinimumAgeForUsefulness =
+ TimeDelta::FromSeconds(3600); // Arbitrary value.
+
+ const char kMaxAgePrefix[] = "max-age=";
+ const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1;
+ if (LowerCaseEqualsASCII(
+ cache_control_header.begin(),
+ cache_control_header.begin() + kMaxAgePrefixLen,
+ kMaxAgePrefix)) {
+ int64 max_age_seconds;
+ base::StringToInt64(
+ base::StringPiece(
+ cache_control_header.begin() + kMaxAgePrefixLen,
+ cache_control_header.end()),
+ &max_age_seconds);
+ if (TimeDelta::FromSeconds(max_age_seconds) < kMinimumAgeForUsefulness)
+ reasons.push_back(kShortMaxAge);
+ }
+
+ Time date;
+ Time expires;
+ if (Time::FromString(response.httpHeaderField("Date").utf8().data(), &date) &&
+ Time::FromString(
+ response.httpHeaderField("Expires").utf8().data(), &expires) &&
+ date > Time() && expires > Time() &&
+ (expires - date) < kMinimumAgeForUsefulness) {
+ reasons.push_back(kExpiresTooSoon);
+ }
+
+ UMA_HISTOGRAM_BOOLEAN("Media.CacheUseful", reasons.empty());
+ for (size_t i = 0; i < reasons.size(); ++i) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.UncacheableReason", reasons[i], kMaxReason);
+ }
+
+ return reasons.empty();
+}
+
void BufferedResourceLoader::didReceiveResponse(
WebURLLoader* loader,
const WebURLResponse& response) {
@@ -368,6 +466,9 @@ void BufferedResourceLoader::didReceiveResponse(
if (start_cb_.is_null())
return;
+ might_be_reused_from_cache_in_future_ =
+ MightBeReusedFromCacheInFuture(response);
+
// Expected content length can be |kPositionNotSpecified|, in that case
// |content_length_| is not specified and this is a streaming response.
content_length_ = response.expectedContentLength();
@@ -540,6 +641,8 @@ bool BufferedResourceLoader::HasSingleOrigin() const {
}
void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) {
+ if (!might_be_reused_from_cache_in_future_ && strategy == kNeverDefer)
+ strategy = kThresholdDefer;
defer_strategy_ = strategy;
UpdateDeferBehavior();
}
« no previous file with comments | « webkit/media/buffered_resource_loader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698