Index: chrome/browser/prerender/prerender_resource_handler.cc |
diff --git a/chrome/browser/prerender/prerender_resource_handler.cc b/chrome/browser/prerender/prerender_resource_handler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..507782eef924636ef88b73cf379a1ae302f57a97 |
--- /dev/null |
+++ b/chrome/browser/prerender/prerender_resource_handler.cc |
@@ -0,0 +1,179 @@ |
+// Copyright (c) 2011 The Chromium 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 "chrome/browser/prerender/prerender_resource_handler.h" |
+ |
+#include "chrome/browser/net/chrome_url_request_context.h" |
+#include "chrome/common/resource_response.h" |
+#include "net/base/load_flags.h" |
+#include "net/http/http_response_headers.h" |
+#include "net/url_request/url_request.h" |
+ |
+namespace { |
+ |
+base::Time DefaultGetCurrentTime() { |
+ return base::Time::Now(); |
+} |
+ |
+bool ShouldPrerender(const GURL& url, |
+ const ResourceResponse* response, |
+ PrerenderResourceHandler::GetCurrentTimeFunction get_time, |
+ base::TimeDelta prerender_duration) { |
+ if (!response) |
+ return false; |
+ const ResourceResponseHead& rrh = response->response_head; |
+ if (!url.is_valid()) |
+ return false; |
+ if (!rrh.headers) |
+ return false; |
+ if (!(url.SchemeIs("http") || url.SchemeIs("https"))) |
+ return false; |
+ if (rrh.mime_type != "text/html") |
+ return false; |
+ if (rrh.headers->response_code() != 200) |
+ return false; |
+ if (rrh.headers->RequiresValidation( |
+ rrh.request_time, |
+ rrh.response_time, |
+ get_time() + prerender_duration)) |
+ return false; |
+ return true; |
+} |
+ |
+} // namespace |
+ |
+PrerenderResourceHandler* PrerenderResourceHandler::MaybeCreate( |
+ const net::URLRequest& request, |
+ ChromeURLRequestContext* context, |
+ ResourceHandler* next_handler) { |
+ if (!context || !context->prerender_manager()) |
+ return NULL; |
+ if (!(request.load_flags() & net::LOAD_PREFETCH)) |
+ return NULL; |
+ if (request.method() != "GET") |
+ return NULL; |
+ return new PrerenderResourceHandler(next_handler, |
+ context->prerender_manager()); |
+} |
+ |
+PrerenderResourceHandler::PrerenderResourceHandler( |
+ ResourceHandler* next_handler, |
+ PrerenderManager* prerender_manager) |
+ : next_handler_(next_handler), |
+ prerender_manager_(prerender_manager), |
+ ALLOW_THIS_IN_INITIALIZER_LIST( |
+ prerender_callback_(NewCallback( |
+ this, &PrerenderResourceHandler::StartPrerender))), |
+ prerender_duration_( |
+ base::TimeDelta::FromSeconds(kDefaultPrerenderDurationSeconds)), |
+ get_current_time_(&DefaultGetCurrentTime) { |
+ DCHECK(next_handler); |
+ DCHECK(prerender_manager); |
+} |
+ |
+// This constructor is only used from unit tests. |
+PrerenderResourceHandler::PrerenderResourceHandler( |
+ ResourceHandler* next_handler, |
+ PrerenderCallback* callback) |
+ : next_handler_(next_handler), |
+ prerender_callback_(callback), |
+ prerender_duration_( |
+ base::TimeDelta::FromSeconds(kDefaultPrerenderDurationSeconds)), |
+ get_current_time_(&DefaultGetCurrentTime) { |
+ DCHECK(next_handler); |
+ DCHECK(callback); |
+} |
+ |
+PrerenderResourceHandler::~PrerenderResourceHandler() { |
+} |
+ |
+bool PrerenderResourceHandler::OnUploadProgress(int request_id, |
+ uint64 position, |
+ uint64 size) { |
+ return next_handler_->OnUploadProgress(request_id, position, size); |
+} |
+ |
+bool PrerenderResourceHandler::OnRequestRedirected(int request_id, |
+ const GURL& url, |
+ ResourceResponse* response, |
+ bool* defer) { |
+ bool will_redirect = next_handler_->OnRequestRedirected( |
+ request_id, url, response, defer); |
+ if (will_redirect) |
+ url_ = url; |
+ return will_redirect; |
+} |
+ |
+bool PrerenderResourceHandler::OnResponseStarted(int request_id, |
+ ResourceResponse* response) { |
+ if (ShouldPrerender(url_, |
+ response, |
+ get_current_time_, |
+ prerender_duration_)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ NewRunnableMethod( |
+ this, |
+ &PrerenderResourceHandler::RunCallbackFromUIThread, |
+ url_)); |
+ } |
+ return next_handler_->OnResponseStarted(request_id, response); |
+} |
+ |
+bool PrerenderResourceHandler::OnWillStart(int request_id, |
+ const GURL& url, |
+ bool* defer) { |
+ bool will_start = next_handler_->OnWillStart(request_id, url, defer); |
+ if (will_start) |
+ url_ = url; |
+ return will_start; |
+} |
+ |
+bool PrerenderResourceHandler::OnWillRead(int request_id, |
+ net::IOBuffer** buf, |
+ int* buf_size, |
+ int min_size) { |
+ return next_handler_->OnWillRead(request_id, buf, buf_size, min_size); |
+} |
+ |
+bool PrerenderResourceHandler::OnReadCompleted(int request_id, |
+ int* bytes_read) { |
+ return next_handler_->OnReadCompleted(request_id, bytes_read); |
+} |
+ |
+bool PrerenderResourceHandler::OnResponseCompleted( |
+ int request_id, |
+ const net::URLRequestStatus& status, |
+ const std::string& security_info) { |
+ return next_handler_->OnResponseCompleted(request_id, status, security_info); |
+} |
+ |
+void PrerenderResourceHandler::OnRequestClosed() { |
+ next_handler_->OnRequestClosed(); |
+} |
+ |
+void PrerenderResourceHandler::RunCallbackFromUIThread(const GURL& url) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ prerender_callback_->Run(url); |
+} |
+ |
+void PrerenderResourceHandler::StartPrerender(const GURL& url) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ prerender_manager_->AddPreload(url); |
+} |
+ |
+void PrerenderResourceHandler::set_prerender_duration(base::TimeDelta dt) { |
+ prerender_duration_ = dt; |
+} |
+ |
+void PrerenderResourceHandler::set_get_current_time_function( |
+ GetCurrentTimeFunction get_current_time) { |
+ DCHECK(get_current_time); |
+ get_current_time_ = get_current_time; |
+} |
+ |
+// Note: this should stay in line with prerendermanager |
+// static |
+const int PrerenderResourceHandler::kDefaultPrerenderDurationSeconds = 20; |