| // 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 "content/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 prerender { |
| |
| namespace { |
| |
| bool ShouldPrerenderURL(const GURL& url) { |
| if (!url.is_valid()) |
| return false; |
| if (!url.SchemeIs("http")) { |
| RecordFinalStatus(FINAL_STATUS_HTTPS); |
| return false; |
| } |
| return true; |
| } |
| |
| bool ValidateAliasURLs(const std::vector<GURL>& urls) { |
| for (std::vector<GURL>::const_iterator it = urls.begin(); |
| it != urls.end(); |
| ++it) { |
| if (!ShouldPrerenderURL(*it)) |
| return false; |
| } |
| return true; |
| } |
| |
| bool ShouldPrerender(const ResourceResponse* response) { |
| if (!response) |
| return false; |
| const ResourceResponseHead& rrh = response->response_head; |
| if (!rrh.headers) |
| return false; |
| if (rrh.mime_type != "text/html") |
| return false; |
| if (rrh.headers->response_code() != 200) |
| return false; |
| return true; |
| } |
| |
| } // namespace |
| |
| PrerenderResourceHandler* PrerenderResourceHandler::MaybeCreate( |
| const net::URLRequest& request, |
| ChromeURLRequestContext* context, |
| ResourceHandler* next_handler, |
| bool is_from_prerender, |
| int child_id, |
| int route_id) { |
| if (!context || !context->prerender_manager()) |
| return NULL; |
| if (!(request.load_flags() & net::LOAD_PREFETCH)) |
| return NULL; |
| if (!ShouldPrerenderURL(request.url())) |
| return NULL; |
| if (request.method() != "GET") |
| return NULL; |
| |
| return new PrerenderResourceHandler(request, |
| next_handler, |
| context->prerender_manager(), |
| is_from_prerender, |
| child_id, |
| route_id); |
| } |
| |
| PrerenderResourceHandler::PrerenderResourceHandler( |
| const net::URLRequest& request, |
| ResourceHandler* next_handler, |
| PrerenderManager* prerender_manager, |
| bool make_pending, |
| int child_id, |
| int route_id) |
| : next_handler_(next_handler), |
| prerender_manager_(prerender_manager), |
| ALLOW_THIS_IN_INITIALIZER_LIST( |
| prerender_callback_(NewCallback( |
| this, &PrerenderResourceHandler::StartPrerender))), |
| request_(request), |
| child_id_(child_id), |
| route_id_(route_id), |
| make_pending_(make_pending) { |
| DCHECK(next_handler); |
| DCHECK(prerender_manager); |
| } |
| |
| PrerenderResourceHandler::PrerenderResourceHandler( |
| const net::URLRequest& request, |
| ResourceHandler* next_handler, |
| PrerenderCallback* callback) |
| : next_handler_(next_handler), |
| prerender_callback_(callback), |
| request_(request) { |
| 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) { |
| if (!ShouldPrerenderURL(url)) |
| return false; |
| alias_urls_.push_back(url); |
| url_ = url; |
| } |
| return will_redirect; |
| } |
| |
| bool PrerenderResourceHandler::OnResponseStarted(int request_id, |
| ResourceResponse* response) { |
| if (ShouldPrerender(response)) { |
| DCHECK(ValidateAliasURLs(alias_urls_)); |
| BrowserThread::PostTask( |
| BrowserThread::UI, |
| FROM_HERE, |
| NewRunnableMethod( |
| this, |
| &PrerenderResourceHandler::RunCallbackFromUIThread, |
| std::make_pair(child_id_, route_id_), |
| url_, |
| alias_urls_, |
| GURL(request_.referrer()), |
| make_pending_)); |
| } |
| 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) { |
| if (!ShouldPrerenderURL(url)) |
| return false; |
| alias_urls_.push_back(url); |
| 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 std::pair<int, int>& child_route_id_pair, |
| const GURL& url, |
| const std::vector<GURL>& alias_urls, |
| const GURL& referrer, |
| bool make_pending) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| prerender_callback_->Run(child_route_id_pair, |
| url, alias_urls, referrer, |
| make_pending); |
| } |
| |
| void PrerenderResourceHandler::StartPrerender( |
| const std::pair<int, int>& child_route_id_pair, |
| const GURL& url, |
| const std::vector<GURL>& alias_urls, |
| const GURL& referrer, |
| bool make_pending) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| if (!prerender_manager_->is_enabled()) |
| return; |
| if (make_pending) { |
| prerender_manager_->AddPendingPreload(child_route_id_pair, |
| url, alias_urls, referrer); |
| } else { |
| prerender_manager_->AddPreload(url, alias_urls, referrer); |
| } |
| } |
| |
| } // namespace prerender |