Home | History | Annotate | Download | only in component_updater
      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