component_updater_resource_throttle.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1// Copyright 2014 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/component_updater/component_updater_resource_throttle.h" 6 7#include "base/location.h" 8#include "base/memory/weak_ptr.h" 9#include "chrome/browser/component_updater/component_updater_service.h" 10#include "content/public/browser/browser_thread.h" 11#include "content/public/browser/resource_controller.h" 12#include "content/public/browser/resource_throttle.h" 13 14using content::BrowserThread; 15 16namespace component_updater { 17 18namespace { 19 20/////////////////////////////////////////////////////////////////////////////// 21// In charge of blocking url requests until the |crx_id| component has been 22// updated. This class is touched solely from the IO thread. The UI thread 23// can post tasks to it via weak pointers. By default the request is blocked 24// unless the CrxUpdateService calls Unblock(). 25// The lifetime is controlled by Chrome's resource loader so the component 26// updater cannot touch objects from this class except via weak pointers. 27class CUResourceThrottle : public content::ResourceThrottle, 28 public base::SupportsWeakPtr<CUResourceThrottle> { 29 public: 30 CUResourceThrottle(); 31 virtual ~CUResourceThrottle(); 32 33 // Overriden from ResourceThrottle. 34 virtual void WillStartRequest(bool* defer) OVERRIDE; 35 virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; 36 virtual const char* GetNameForLogging() const OVERRIDE; 37 38 // Component updater calls this function via PostTask to unblock the request. 39 void Unblock(); 40 41 typedef std::vector<base::WeakPtr<CUResourceThrottle> > WeakPtrVector; 42 43 private: 44 enum State { NEW, BLOCKED, UNBLOCKED }; 45 46 State state_; 47}; 48 49CUResourceThrottle::CUResourceThrottle() : state_(NEW) { 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 51} 52 53CUResourceThrottle::~CUResourceThrottle() { 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 55} 56 57void CUResourceThrottle::WillStartRequest(bool* defer) { 58 if (state_ != UNBLOCKED) { 59 state_ = BLOCKED; 60 *defer = true; 61 } else { 62 *defer = false; 63 } 64} 65 66void CUResourceThrottle::WillRedirectRequest(const GURL& new_url, bool* defer) { 67 WillStartRequest(defer); 68} 69 70const char* CUResourceThrottle::GetNameForLogging() const { 71 return "ComponentUpdateResourceThrottle"; 72} 73 74void CUResourceThrottle::Unblock() { 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 76 if (state_ == BLOCKED) 77 controller()->Resume(); 78 state_ = UNBLOCKED; 79} 80 81void UnblockThrottleOnUIThread(base::WeakPtr<CUResourceThrottle> rt) { 82 BrowserThread::PostTask(BrowserThread::IO, 83 FROM_HERE, 84 base::Bind(&CUResourceThrottle::Unblock, rt)); 85} 86 87} // namespace 88 89content::ResourceThrottle* GetOnDemandResourceThrottle( 90 ComponentUpdateService* cus, 91 const std::string& crx_id) { 92 DCHECK_CURRENTLY_ON(BrowserThread::IO); 93 94 // We give the raw pointer to the caller, who will delete it at will 95 // and we keep for ourselves a weak pointer to it so we can post tasks 96 // from the UI thread without having to track lifetime directly. 97 CUResourceThrottle* rt = new CUResourceThrottle; 98 BrowserThread::PostTask( 99 BrowserThread::UI, 100 FROM_HERE, 101 base::Bind(&ComponentUpdateService::MaybeThrottle, 102 base::Unretained(cus), 103 crx_id, 104 base::Bind(&UnblockThrottleOnUIThread, rt->AsWeakPtr()))); 105 return rt; 106} 107 108} // namespace component_updater 109