summaryrefslogtreecommitdiffstats
path: root/chrome/browser/component_updater/component_updater_resource_throttle.cc
blob: dac716eaca7e8287ca8e48c682a3f48190f9ee50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/component_updater/component_updater_resource_throttle.h"

#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "components/component_updater/component_updater_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_throttle.h"

using content::BrowserThread;

namespace component_updater {

namespace {

///////////////////////////////////////////////////////////////////////////////
// In charge of blocking url requests until the |crx_id| component has been
// updated. This class is touched solely from the IO thread. The UI thread
// can post tasks to it via weak pointers. By default the request is blocked
// unless the CrxUpdateService calls Unblock().
// The lifetime is controlled by Chrome's resource loader so the component
// updater cannot touch objects from this class except via weak pointers.
class CUResourceThrottle : public content::ResourceThrottle,
                           public base::SupportsWeakPtr<CUResourceThrottle> {
 public:
  CUResourceThrottle();
  ~CUResourceThrottle() override;

  // Overriden from ResourceThrottle.
  void WillStartRequest(bool* defer) override;
  void WillRedirectRequest(const net::RedirectInfo& redirect_info,
                           bool* defer) override;
  const char* GetNameForLogging() const override;

  // Component updater calls this function via PostTask to unblock the request.
  void Unblock();

  typedef std::vector<base::WeakPtr<CUResourceThrottle> > WeakPtrVector;

 private:
  enum State { NEW, BLOCKED, UNBLOCKED };

  State state_;
};

CUResourceThrottle::CUResourceThrottle() : state_(NEW) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

CUResourceThrottle::~CUResourceThrottle() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

void CUResourceThrottle::WillStartRequest(bool* defer) {
  if (state_ != UNBLOCKED) {
    state_ = BLOCKED;
    *defer = true;
  } else {
    *defer = false;
  }
}

void CUResourceThrottle::WillRedirectRequest(
    const net::RedirectInfo& redirect_info, bool* defer) {
  WillStartRequest(defer);
}

const char* CUResourceThrottle::GetNameForLogging() const {
  return "ComponentUpdateResourceThrottle";
}

void CUResourceThrottle::Unblock() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (state_ == BLOCKED)
    controller()->Resume();
  state_ = UNBLOCKED;
}

void UnblockThrottleOnUIThread(base::WeakPtr<CUResourceThrottle> rt) {
  BrowserThread::PostTask(BrowserThread::IO,
                          FROM_HERE,
                          base::Bind(&CUResourceThrottle::Unblock, rt));
}

}  // namespace

content::ResourceThrottle* GetOnDemandResourceThrottle(
    ComponentUpdateService* cus,
    const std::string& crx_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // We give the raw pointer to the caller, who will delete it at will
  // and we keep for ourselves a weak pointer to it so we can post tasks
  // from the UI thread without having to track lifetime directly.
  CUResourceThrottle* rt = new CUResourceThrottle;
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      base::Bind(&ComponentUpdateService::MaybeThrottle,
                 base::Unretained(cus),
                 crx_id,
                 base::Bind(&UnblockThrottleOnUIThread, rt->AsWeakPtr())));
  return rt;
}

}  // namespace component_updater