offline_resource_handler.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/renderer_host/offline_resource_handler.h" 6 7#include <vector> 8 9#include "base/histogram.h" 10#include "base/logging.h" 11#include "base/singleton.h" 12#include "base/string_util.h" 13#include "chrome/browser/chrome_thread.h" 14#include "chrome/browser/chromeos/network_state_notifier.h" 15#include "chrome/browser/chromeos/offline/offline_load_page.h" 16#include "chrome/browser/chromeos/offline/offline_load_service.h" 17#include "chrome/browser/renderer_host/resource_dispatcher_host.h" 18#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" 19#include "chrome/common/url_constants.h" 20 21OfflineResourceHandler::OfflineResourceHandler( 22 ResourceHandler* handler, 23 int host_id, 24 int route_id, 25 ResourceDispatcherHost* rdh, 26 URLRequest* request) 27 : next_handler_(handler), 28 process_host_id_(host_id), 29 render_view_id_(route_id), 30 rdh_(rdh), 31 request_(request), 32 deferred_request_id_(-1) { 33} 34 35bool OfflineResourceHandler::OnUploadProgress(int request_id, 36 uint64 position, 37 uint64 size) { 38 return next_handler_->OnUploadProgress(request_id, position, size); 39} 40 41bool OfflineResourceHandler::OnRequestRedirected(int request_id, 42 const GURL& new_url, 43 ResourceResponse* response, 44 bool* defer) { 45 return next_handler_->OnRequestRedirected( 46 request_id, new_url, response, defer); 47} 48 49bool OfflineResourceHandler::OnResponseStarted(int request_id, 50 ResourceResponse* response) { 51 return next_handler_->OnResponseStarted(request_id, response); 52} 53 54bool OfflineResourceHandler::OnResponseCompleted( 55 int request_id, 56 const URLRequestStatus& status, 57 const std::string& security_info) { 58 return next_handler_->OnResponseCompleted(request_id, status, security_info); 59} 60 61void OfflineResourceHandler::OnRequestClosed() { 62 next_handler_->OnRequestClosed(); 63} 64 65bool OfflineResourceHandler::OnWillStart(int request_id, 66 const GURL& url, 67 bool* defer) { 68 if (ShouldShowOfflinePage(url)) { 69 deferred_request_id_ = request_id; 70 deferred_url_ = url; 71 DLOG(INFO) << "WillStart: this=" << this << ", request id=" << request_id; 72 AddRef(); // Balanced with OnBlockingPageComplete 73 ChromeThread::PostTask( 74 ChromeThread::UI, FROM_HERE, 75 NewRunnableMethod(this, &OfflineResourceHandler::ShowOfflinePage)); 76 *defer = true; 77 return true; 78 } 79 return next_handler_->OnWillStart(request_id, url, defer); 80} 81 82// We'll let the original event handler provide a buffer, and reuse it for 83// subsequent reads until we're done buffering. 84bool OfflineResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf, 85 int* buf_size, int min_size) { 86 return next_handler_->OnWillRead(request_id, buf, buf_size, min_size); 87} 88 89bool OfflineResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { 90 return next_handler_->OnReadCompleted(request_id, bytes_read); 91} 92 93void OfflineResourceHandler::OnBlockingPageComplete(bool proceed) { 94 if (deferred_request_id_ < 0) { 95 LOG(WARNING) << "OnBlockingPageComplete called after completion: " 96 << " this=" << this << ", request_id=" 97 << deferred_request_id_; 98 NOTREACHED(); 99 return; 100 } 101 if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { 102 ChromeThread::PostTask( 103 ChromeThread::IO, FROM_HERE, 104 NewRunnableMethod(this, 105 &OfflineResourceHandler::OnBlockingPageComplete, 106 proceed)); 107 return; 108 } 109 if (proceed) { 110 Resume(); 111 } else { 112 int request_id = deferred_request_id_; 113 ClearRequestInfo(); 114 rdh_->CancelRequest(process_host_id_, request_id, false); 115 } 116 Release(); // Balanced with OnWillStart 117} 118 119void OfflineResourceHandler::ClearRequestInfo() { 120 deferred_url_ = GURL(); 121 deferred_request_id_ = -1; 122} 123 124bool OfflineResourceHandler::IsRemote(const GURL& url) const { 125 return url.SchemeIs(chrome::kFtpScheme) || 126 url.SchemeIs(chrome::kHttpScheme) || 127 url.SchemeIs(chrome::kHttpsScheme); 128} 129 130bool OfflineResourceHandler::ShouldShowOfflinePage(const GURL& url) const { 131 // Only check main frame. If the network is disconnected while 132 // loading other resources, we'll simply show broken link/images. 133 return IsRemote(url) && 134 !chromeos::NetworkStateNotifier::is_connected() && 135 ResourceDispatcherHost::InfoForRequest(request_)->resource_type() 136 == ResourceType::MAIN_FRAME && 137 !chromeos::OfflineLoadService::Get()->ShouldProceed( 138 process_host_id_, render_view_id_, url); 139} 140 141void OfflineResourceHandler::Resume() { 142 const GURL url = deferred_url_; 143 int request_id = deferred_request_id_; 144 ClearRequestInfo(); 145 146 chromeos::OfflineLoadService::Get()->Proceeded( 147 process_host_id_, render_view_id_, url); 148 149 DCHECK_NE(request_id, -1); 150 bool defer = false; 151 DLOG(INFO) << "Resume load: this=" << this 152 << ", request id=" << request_id; 153 next_handler_->OnWillStart(request_id, url, &defer); 154 if (!defer) 155 rdh_->StartDeferredRequest(process_host_id_, request_id); 156} 157 158void OfflineResourceHandler::ShowOfflinePage() { 159 chromeos::OfflineLoadPage::Show( 160 process_host_id_, render_view_id_, deferred_url_, this); 161} 162