16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/component_updater/component_updater_resource_throttle.h"
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/location.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/memory/weak_ptr.h"
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_updater_service.h"
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/public/browser/resource_controller.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/public/browser/resource_throttle.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using content::BrowserThread;
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace component_updater {
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// In charge of blocking url requests until the |crx_id| component has been
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// updated. This class is touched solely from the IO thread. The UI thread
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// can post tasks to it via weak pointers. By default the request is blocked
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// unless the CrxUpdateService calls Unblock().
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// The lifetime is controlled by Chrome's resource loader so the component
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// updater cannot touch objects from this class except via weak pointers.
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class CUResourceThrottle : public content::ResourceThrottle,
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                           public base::SupportsWeakPtr<CUResourceThrottle> {
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CUResourceThrottle();
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~CUResourceThrottle();
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Overriden from ResourceThrottle.
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void WillStartRequest(bool* defer) OVERRIDE;
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE;
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual const char* GetNameForLogging() const OVERRIDE;
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Component updater calls this function via PostTask to unblock the request.
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void Unblock();
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  typedef std::vector<base::WeakPtr<CUResourceThrottle> > WeakPtrVector;
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  enum State { NEW, BLOCKED, UNBLOCKED };
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  State state_;
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)CUResourceThrottle::CUResourceThrottle() : state_(NEW) {
506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)CUResourceThrottle::~CUResourceThrottle() {
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CUResourceThrottle::WillStartRequest(bool* defer) {
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (state_ != UNBLOCKED) {
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    state_ = BLOCKED;
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    *defer = true;
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else {
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    *defer = false;
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CUResourceThrottle::WillRedirectRequest(const GURL& new_url, bool* defer) {
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  WillStartRequest(defer);
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char* CUResourceThrottle::GetNameForLogging() const {
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return "ComponentUpdateResourceThrottle";
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CUResourceThrottle::Unblock() {
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (state_ == BLOCKED)
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    controller()->Resume();
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  state_ = UNBLOCKED;
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void UnblockThrottleOnUIThread(base::WeakPtr<CUResourceThrottle> rt) {
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO,
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          FROM_HERE,
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          base::Bind(&CUResourceThrottle::Unblock, rt));
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)content::ResourceThrottle* GetOnDemandResourceThrottle(
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ComponentUpdateService* cus,
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& crx_id) {
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::IO);
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // We give the raw pointer to the caller, who will delete it at will
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // and we keep for ourselves a weak pointer to it so we can post tasks
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // from the UI thread without having to track lifetime directly.
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CUResourceThrottle* rt = new CUResourceThrottle;
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  BrowserThread::PostTask(
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      BrowserThread::UI,
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE,
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&ComponentUpdateService::MaybeThrottle,
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 base::Unretained(cus),
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 crx_id,
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 base::Bind(&UnblockThrottleOnUIThread, rt->AsWeakPtr())));
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return rt;
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace component_updater
109