1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/loader/detachable_resource_handler.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/time/time.h" 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/loader/resource_request_info_impl.h" 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/base/io_buffer.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/base/net_errors.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/url_request/url_request_status.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// This matches the maximum allocation size of AsyncResourceHandler. 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kReadBufSize = 32 * 1024; 180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace content { 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DetachableResourceHandler::DetachableResourceHandler( 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequest* request, 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeDelta cancel_delay, 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ResourceHandler> next_handler) 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : ResourceHandler(request), 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) next_handler_(next_handler.Pass()), 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) cancel_delay_(cancel_delay), 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_deferred_(false), 300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch is_finished_(false) { 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetRequestInfo()->set_detachable_handler(this); 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DetachableResourceHandler::~DetachableResourceHandler() { 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Cleanup back-pointer stored on the request info. 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetRequestInfo()->set_detachable_handler(NULL); 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::Detach() { 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_detached()) 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!is_finished_) { 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Simulate a cancel on the next handler before destroying it. 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus status(net::URLRequestStatus::CANCELED, 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::ERR_ABORTED); 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool defer_ignored = false; 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored); 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!defer_ignored); 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If |next_handler_| were to defer its shutdown in OnResponseCompleted, 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this would destroy it anyway. Fortunately, AsyncResourceHandler never 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // does this anyway, so DCHECK it. BufferedResourceHandler and RVH shutdown 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // already ignore deferred ResourceHandler shutdown, but 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // DetachableResourceHandler and the detach-on-renderer-cancel logic 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // introduces a case where this occurs when the renderer cancels a resource. 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // A OnWillRead / OnReadCompleted pair may still be in progress, but 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // OnWillRead passes back a scoped_refptr, so downstream handler's buffer will 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // survive long enough to complete that read. From there, future reads will 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // drain into |read_buffer_|. (If |next_handler_| is an AsyncResourceHandler, 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the net::IOBuffer takes a reference to the ResourceBuffer which owns the 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // shared memory.) 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) next_handler_.reset(); 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Time the request out if it takes too long. 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) detached_timer_.reset(new base::OneShotTimer<DetachableResourceHandler>()); 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) detached_timer_->Start( 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::Cancel); 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Resume if necessary. The request may have been deferred, say, waiting on a 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // full buffer in AsyncResourceHandler. Now that it has been detached, resume 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // and drain it. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (is_deferred_) { 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The nested ResourceHandler may have logged that it's blocking the 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // request. Log it as no longer doing so, to avoid a DCHECK on resume. 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request()->LogUnblocked(); 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Resume(); 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::SetController(ResourceController* controller) { 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ResourceHandler::SetController(controller); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Intercept the ResourceController for downstream handlers to keep track of 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // whether the request is deferred. 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (next_handler_) 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) next_handler_->SetController(this); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DetachableResourceHandler::OnUploadProgress(uint64 position, uint64 size) { 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return next_handler_->OnUploadProgress(position, size); 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DetachableResourceHandler::OnRequestRedirected( 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const net::RedirectInfo& redirect_info, 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ResourceResponse* response, 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool* defer) { 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!is_deferred_); 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool ret = next_handler_->OnRequestRedirected( 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) redirect_info, response, &is_deferred_); 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *defer = is_deferred_; 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ret; 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DetachableResourceHandler::OnResponseStarted(ResourceResponse* response, 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool* defer) { 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!is_deferred_); 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool ret = 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_handler_->OnResponseStarted(response, &is_deferred_); 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *defer = is_deferred_; 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ret; 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DetachableResourceHandler::OnWillStart(const GURL& url, bool* defer) { 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!is_deferred_); 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool ret = next_handler_->OnWillStart(url, &is_deferred_); 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *defer = is_deferred_; 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ret; 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DetachableResourceHandler::OnBeforeNetworkStart(const GURL& url, 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool* defer) { 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!is_deferred_); 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!next_handler_) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool ret = 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_handler_->OnBeforeNetworkStart(url, &is_deferred_); 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *defer = is_deferred_; 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ret; 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DetachableResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int* buf_size, 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int min_size) { 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) { 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(-1, min_size); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!read_buffer_.get()) 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) read_buffer_ = new net::IOBuffer(kReadBufSize); 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *buf = read_buffer_; 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *buf_size = kReadBufSize; 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return next_handler_->OnWillRead(buf, buf_size, min_size); 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DetachableResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!is_deferred_); 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool ret = 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_handler_->OnReadCompleted(bytes_read, &is_deferred_); 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *defer = is_deferred_; 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ret; 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::OnResponseCompleted( 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const net::URLRequestStatus& status, 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& security_info, 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool* defer) { 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // No DCHECK(!is_deferred_) as the request may have been cancelled while 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // deferred. 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_finished_ = true; 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_handler_->OnResponseCompleted(status, security_info, &is_deferred_); 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *defer = is_deferred_; 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DetachableResourceHandler::OnDataDownloaded(int bytes_downloaded) { 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!next_handler_) 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_handler_->OnDataDownloaded(bytes_downloaded); 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::Resume() { 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(is_deferred_); 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_deferred_ = false; 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller()->Resume(); 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::Cancel() { 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller()->Cancel(); 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::CancelAndIgnore() { 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller()->CancelAndIgnore(); 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DetachableResourceHandler::CancelWithError(int error_code) { 214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller()->CancelWithError(error_code); 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace content 218