| // Copyright (c) 2012 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 "content/browser/loader/throttling_resource_handler.h" |
| |
| #include "content/public/browser/resource_throttle.h" |
| #include "content/public/common/resource_response.h" |
| |
| namespace content { |
| |
| ThrottlingResourceHandler::ThrottlingResourceHandler( |
| scoped_ptr<ResourceHandler> next_handler, |
| int child_id, |
| int request_id, |
| ScopedVector<ResourceThrottle> throttles) |
| : LayeredResourceHandler(next_handler.Pass()), |
| deferred_stage_(DEFERRED_NONE), |
| request_id_(request_id), |
| throttles_(throttles.Pass()), |
| index_(0), |
| cancelled_by_resource_throttle_(false) { |
| for (size_t i = 0; i < throttles_.size(); ++i) |
| throttles_[i]->set_controller(this); |
| } |
| |
| ThrottlingResourceHandler::~ThrottlingResourceHandler() { |
| } |
| |
| bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, |
| const GURL& new_url, |
| ResourceResponse* response, |
| bool* defer) { |
| DCHECK_EQ(request_id_, request_id); |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| *defer = false; |
| while (index_ < throttles_.size()) { |
| throttles_[index_]->WillRedirectRequest(new_url, defer); |
| index_++; |
| if (cancelled_by_resource_throttle_) |
| return false; |
| if (*defer) { |
| deferred_stage_ = DEFERRED_REDIRECT; |
| deferred_url_ = new_url; |
| deferred_response_ = response; |
| return true; // Do not cancel. |
| } |
| } |
| |
| index_ = 0; // Reset for next time. |
| |
| return next_handler_->OnRequestRedirected(request_id, new_url, response, |
| defer); |
| } |
| |
| bool ThrottlingResourceHandler::OnWillStart(int request_id, |
| const GURL& url, |
| bool* defer) { |
| DCHECK_EQ(request_id_, request_id); |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| *defer = false; |
| while (index_ < throttles_.size()) { |
| throttles_[index_]->WillStartRequest(defer); |
| index_++; |
| if (cancelled_by_resource_throttle_) |
| return false; |
| if (*defer) { |
| deferred_stage_ = DEFERRED_START; |
| deferred_url_ = url; |
| return true; // Do not cancel. |
| } |
| } |
| |
| index_ = 0; // Reset for next time. |
| |
| return next_handler_->OnWillStart(request_id, url, defer); |
| } |
| |
| bool ThrottlingResourceHandler::OnResponseStarted(int request_id, |
| ResourceResponse* response, |
| bool* defer) { |
| DCHECK_EQ(request_id_, request_id); |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| while (index_ < throttles_.size()) { |
| throttles_[index_]->WillProcessResponse(defer); |
| index_++; |
| if (cancelled_by_resource_throttle_) |
| return false; |
| if (*defer) { |
| deferred_stage_ = DEFERRED_RESPONSE; |
| deferred_response_ = response; |
| return true; // Do not cancel. |
| } |
| } |
| |
| index_ = 0; // Reset for next time. |
| |
| return next_handler_->OnResponseStarted(request_id, response, defer); |
| } |
| |
| void ThrottlingResourceHandler::Cancel() { |
| cancelled_by_resource_throttle_ = true; |
| controller()->Cancel(); |
| } |
| |
| void ThrottlingResourceHandler::CancelAndIgnore() { |
| cancelled_by_resource_throttle_ = true; |
| controller()->CancelAndIgnore(); |
| } |
| |
| void ThrottlingResourceHandler::CancelWithError(int error_code) { |
| cancelled_by_resource_throttle_ = true; |
| controller()->CancelWithError(error_code); |
| } |
| |
| void ThrottlingResourceHandler::Resume() { |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| DeferredStage last_deferred_stage = deferred_stage_; |
| deferred_stage_ = DEFERRED_NONE; |
| switch (last_deferred_stage) { |
| case DEFERRED_NONE: |
| NOTREACHED(); |
| break; |
| case DEFERRED_START: |
| ResumeStart(); |
| break; |
| case DEFERRED_REDIRECT: |
| ResumeRedirect(); |
| break; |
| case DEFERRED_RESPONSE: |
| ResumeResponse(); |
| break; |
| } |
| } |
| |
| void ThrottlingResourceHandler::ResumeStart() { |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| GURL url = deferred_url_; |
| deferred_url_ = GURL(); |
| |
| bool defer = false; |
| if (!OnWillStart(request_id_, url, &defer)) { |
| controller()->Cancel(); |
| } else if (!defer) { |
| controller()->Resume(); |
| } |
| } |
| |
| void ThrottlingResourceHandler::ResumeRedirect() { |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| GURL new_url = deferred_url_; |
| deferred_url_ = GURL(); |
| scoped_refptr<ResourceResponse> response; |
| deferred_response_.swap(response); |
| |
| bool defer = false; |
| if (!OnRequestRedirected(request_id_, new_url, response.get(), &defer)) { |
| controller()->Cancel(); |
| } else if (!defer) { |
| controller()->Resume(); |
| } |
| } |
| |
| void ThrottlingResourceHandler::ResumeResponse() { |
| DCHECK(!cancelled_by_resource_throttle_); |
| |
| scoped_refptr<ResourceResponse> response; |
| deferred_response_.swap(response); |
| |
| bool defer = false; |
| if (!OnResponseStarted(request_id_, response.get(), &defer)) { |
| controller()->Cancel(); |
| } else if (!defer) { |
| controller()->Resume(); |
| } |
| } |
| |
| } // namespace content |