1// Copyright (c) 2012 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 "content/browser/loader/throttling_resource_handler.h" 6 7#include "content/public/browser/resource_throttle.h" 8#include "content/public/common/resource_response.h" 9 10namespace content { 11 12ThrottlingResourceHandler::ThrottlingResourceHandler( 13 scoped_ptr<ResourceHandler> next_handler, 14 int child_id, 15 int request_id, 16 ScopedVector<ResourceThrottle> throttles) 17 : LayeredResourceHandler(next_handler.Pass()), 18 deferred_stage_(DEFERRED_NONE), 19 request_id_(request_id), 20 throttles_(throttles.Pass()), 21 index_(0), 22 cancelled_by_resource_throttle_(false) { 23 for (size_t i = 0; i < throttles_.size(); ++i) 24 throttles_[i]->set_controller(this); 25} 26 27ThrottlingResourceHandler::~ThrottlingResourceHandler() { 28} 29 30bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, 31 const GURL& new_url, 32 ResourceResponse* response, 33 bool* defer) { 34 DCHECK_EQ(request_id_, request_id); 35 DCHECK(!cancelled_by_resource_throttle_); 36 37 *defer = false; 38 while (index_ < throttles_.size()) { 39 throttles_[index_]->WillRedirectRequest(new_url, defer); 40 index_++; 41 if (cancelled_by_resource_throttle_) 42 return false; 43 if (*defer) { 44 deferred_stage_ = DEFERRED_REDIRECT; 45 deferred_url_ = new_url; 46 deferred_response_ = response; 47 return true; // Do not cancel. 48 } 49 } 50 51 index_ = 0; // Reset for next time. 52 53 return next_handler_->OnRequestRedirected(request_id, new_url, response, 54 defer); 55} 56 57bool ThrottlingResourceHandler::OnWillStart(int request_id, 58 const GURL& url, 59 bool* defer) { 60 DCHECK_EQ(request_id_, request_id); 61 DCHECK(!cancelled_by_resource_throttle_); 62 63 *defer = false; 64 while (index_ < throttles_.size()) { 65 throttles_[index_]->WillStartRequest(defer); 66 index_++; 67 if (cancelled_by_resource_throttle_) 68 return false; 69 if (*defer) { 70 deferred_stage_ = DEFERRED_START; 71 deferred_url_ = url; 72 return true; // Do not cancel. 73 } 74 } 75 76 index_ = 0; // Reset for next time. 77 78 return next_handler_->OnWillStart(request_id, url, defer); 79} 80 81bool ThrottlingResourceHandler::OnResponseStarted(int request_id, 82 ResourceResponse* response, 83 bool* defer) { 84 DCHECK_EQ(request_id_, request_id); 85 DCHECK(!cancelled_by_resource_throttle_); 86 87 while (index_ < throttles_.size()) { 88 throttles_[index_]->WillProcessResponse(defer); 89 index_++; 90 if (cancelled_by_resource_throttle_) 91 return false; 92 if (*defer) { 93 deferred_stage_ = DEFERRED_RESPONSE; 94 deferred_response_ = response; 95 return true; // Do not cancel. 96 } 97 } 98 99 index_ = 0; // Reset for next time. 100 101 return next_handler_->OnResponseStarted(request_id, response, defer); 102} 103 104void ThrottlingResourceHandler::Cancel() { 105 cancelled_by_resource_throttle_ = true; 106 controller()->Cancel(); 107} 108 109void ThrottlingResourceHandler::CancelAndIgnore() { 110 cancelled_by_resource_throttle_ = true; 111 controller()->CancelAndIgnore(); 112} 113 114void ThrottlingResourceHandler::CancelWithError(int error_code) { 115 cancelled_by_resource_throttle_ = true; 116 controller()->CancelWithError(error_code); 117} 118 119void ThrottlingResourceHandler::Resume() { 120 DCHECK(!cancelled_by_resource_throttle_); 121 122 DeferredStage last_deferred_stage = deferred_stage_; 123 deferred_stage_ = DEFERRED_NONE; 124 switch (last_deferred_stage) { 125 case DEFERRED_NONE: 126 NOTREACHED(); 127 break; 128 case DEFERRED_START: 129 ResumeStart(); 130 break; 131 case DEFERRED_REDIRECT: 132 ResumeRedirect(); 133 break; 134 case DEFERRED_RESPONSE: 135 ResumeResponse(); 136 break; 137 } 138} 139 140void ThrottlingResourceHandler::ResumeStart() { 141 DCHECK(!cancelled_by_resource_throttle_); 142 143 GURL url = deferred_url_; 144 deferred_url_ = GURL(); 145 146 bool defer = false; 147 if (!OnWillStart(request_id_, url, &defer)) { 148 controller()->Cancel(); 149 } else if (!defer) { 150 controller()->Resume(); 151 } 152} 153 154void ThrottlingResourceHandler::ResumeRedirect() { 155 DCHECK(!cancelled_by_resource_throttle_); 156 157 GURL new_url = deferred_url_; 158 deferred_url_ = GURL(); 159 scoped_refptr<ResourceResponse> response; 160 deferred_response_.swap(response); 161 162 bool defer = false; 163 if (!OnRequestRedirected(request_id_, new_url, response.get(), &defer)) { 164 controller()->Cancel(); 165 } else if (!defer) { 166 controller()->Resume(); 167 } 168} 169 170void ThrottlingResourceHandler::ResumeResponse() { 171 DCHECK(!cancelled_by_resource_throttle_); 172 173 scoped_refptr<ResourceResponse> response; 174 deferred_response_.swap(response); 175 176 bool defer = false; 177 if (!OnResponseStarted(request_id_, response.get(), &defer)) { 178 controller()->Cancel(); 179 } else if (!defer) { 180 controller()->Resume(); 181 } 182} 183 184} // namespace content 185