Home | History | Annotate | Download | only in loader
      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 
     10 namespace content {
     11 
     12 ThrottlingResourceHandler::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 
     27 ThrottlingResourceHandler::~ThrottlingResourceHandler() {
     28 }
     29 
     30 bool 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 
     57 bool 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 
     81 bool 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 
    104 void ThrottlingResourceHandler::Cancel() {
    105   cancelled_by_resource_throttle_ = true;
    106   controller()->Cancel();
    107 }
    108 
    109 void ThrottlingResourceHandler::CancelAndIgnore() {
    110   cancelled_by_resource_throttle_ = true;
    111   controller()->CancelAndIgnore();
    112 }
    113 
    114 void ThrottlingResourceHandler::CancelWithError(int error_code) {
    115   cancelled_by_resource_throttle_ = true;
    116   controller()->CancelWithError(error_code);
    117 }
    118 
    119 void 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 
    140 void 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 
    154 void 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 
    170 void 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