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 "components/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 14 using content::BrowserThread; 15 16 namespace component_updater { 17 18 namespace { 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. 27 class 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 49 CUResourceThrottle::CUResourceThrottle() : state_(NEW) { 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 51 } 52 53 CUResourceThrottle::~CUResourceThrottle() { 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 55 } 56 57 void CUResourceThrottle::WillStartRequest(bool* defer) { 58 if (state_ != UNBLOCKED) { 59 state_ = BLOCKED; 60 *defer = true; 61 } else { 62 *defer = false; 63 } 64 } 65 66 void CUResourceThrottle::WillRedirectRequest(const GURL& new_url, bool* defer) { 67 WillStartRequest(defer); 68 } 69 70 const char* CUResourceThrottle::GetNameForLogging() const { 71 return "ComponentUpdateResourceThrottle"; 72 } 73 74 void CUResourceThrottle::Unblock() { 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 76 if (state_ == BLOCKED) 77 controller()->Resume(); 78 state_ = UNBLOCKED; 79 } 80 81 void UnblockThrottleOnUIThread(base::WeakPtr<CUResourceThrottle> rt) { 82 BrowserThread::PostTask(BrowserThread::IO, 83 FROM_HERE, 84 base::Bind(&CUResourceThrottle::Unblock, rt)); 85 } 86 87 } // namespace 88 89 content::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