OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/chromeos/login/signed_settings_helper.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/lazy_instance.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "chrome/browser/policy/proto/device_management_backend.pb.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 | |
15 using content::BrowserThread; | |
16 | |
17 namespace em = enterprise_management; | |
18 | |
19 namespace chromeos { | |
20 | |
21 namespace { | |
22 | |
23 class OpContext { | |
24 public: | |
25 class Delegate { | |
26 public: | |
27 virtual void OnOpCreated(OpContext* context) = 0; | |
28 virtual void OnOpStarted(OpContext* context) = 0; | |
29 virtual void OnOpCompleted(OpContext* context) = 0; | |
30 }; | |
31 | |
32 virtual ~OpContext() {} | |
33 | |
34 // Creates and execute op. | |
35 void Execute() { | |
36 CreateOp(); | |
37 CHECK(op_.get()); | |
38 if (delegate_) | |
39 delegate_->OnOpCreated(this); | |
40 | |
41 // Note that the context could be released when op_->Execute() returns. | |
42 // So keep a local copy of delegate and executing flag to use after | |
43 // the call. | |
44 Delegate* delegate = delegate_; | |
45 executing_ = true; | |
46 op_->Execute(); | |
47 if (delegate) | |
48 delegate->OnOpStarted(this); | |
49 } | |
50 | |
51 // Cancels the callback and cancels the op if it is not executing. | |
52 void Cancel() { | |
53 if (!executing_) | |
54 OnOpCompleted(); | |
55 } | |
56 | |
57 // Accessors. | |
58 SignedSettings* op() const { | |
59 return op_.get(); | |
60 } | |
61 | |
62 void set_delegate(Delegate* delegate) { | |
63 delegate_ = delegate; | |
64 } | |
65 | |
66 protected: | |
67 explicit OpContext(Delegate* delegate) | |
68 : executing_(false), | |
69 delegate_(delegate) { | |
70 } | |
71 | |
72 // Creates the op to execute. | |
73 virtual void CreateOp() = 0; | |
74 | |
75 // Callback on op completion. | |
76 virtual void OnOpCompleted() { | |
77 if (delegate_) | |
78 delegate_->OnOpCompleted(this); | |
79 | |
80 delete this; | |
81 } | |
82 | |
83 bool executing_; | |
84 Delegate* delegate_; | |
85 | |
86 scoped_refptr<SignedSettings> op_; | |
87 }; | |
88 | |
89 class StorePolicyOpContext | |
90 : public SignedSettings::Delegate<bool>, | |
91 public OpContext { | |
92 public: | |
93 StorePolicyOpContext(const em::PolicyFetchResponse& policy, | |
94 SignedSettingsHelper::StorePolicyCallback callback, | |
95 OpContext::Delegate* delegate) | |
96 : OpContext(delegate), | |
97 callback_(callback), | |
98 policy_(policy) { | |
99 } | |
100 | |
101 // chromeos::SignedSettings::Delegate implementation | |
102 virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code, | |
103 bool unused) OVERRIDE { | |
104 VLOG(2) << "OnSettingsOpCompleted, code = " << code; | |
105 callback_.Run(code); | |
106 OnOpCompleted(); | |
107 } | |
108 | |
109 protected: | |
110 // OpContext implementation | |
111 virtual void CreateOp() OVERRIDE { | |
112 op_ = SignedSettings::CreateStorePolicyOp(&policy_, this); | |
113 } | |
114 | |
115 private: | |
116 SignedSettingsHelper::StorePolicyCallback callback_; | |
117 em::PolicyFetchResponse policy_; | |
118 | |
119 DISALLOW_COPY_AND_ASSIGN(StorePolicyOpContext); | |
120 }; | |
121 | |
122 class RetrievePolicyOpContext | |
123 : public SignedSettings::Delegate<const em::PolicyFetchResponse&>, | |
124 public OpContext { | |
125 public: | |
126 RetrievePolicyOpContext(SignedSettingsHelper::RetrievePolicyCallback callback, | |
127 OpContext::Delegate* delegate) | |
128 : OpContext(delegate), | |
129 callback_(callback){ | |
130 } | |
131 | |
132 // chromeos::SignedSettings::Delegate implementation | |
133 virtual void OnSettingsOpCompleted( | |
134 SignedSettings::ReturnCode code, | |
135 const em::PolicyFetchResponse& policy) OVERRIDE { | |
136 callback_.Run(code, policy); | |
137 OnOpCompleted(); | |
138 } | |
139 | |
140 protected: | |
141 // OpContext implementation | |
142 virtual void CreateOp() OVERRIDE { | |
143 op_ = SignedSettings::CreateRetrievePolicyOp(this); | |
144 } | |
145 | |
146 private: | |
147 SignedSettingsHelper::RetrievePolicyCallback callback_; | |
148 | |
149 DISALLOW_COPY_AND_ASSIGN(RetrievePolicyOpContext); | |
150 }; | |
151 | |
152 } // namespace | |
153 | |
154 | |
155 class SignedSettingsHelperImpl : public SignedSettingsHelper, | |
156 public OpContext::Delegate { | |
157 public: | |
158 // SignedSettingsHelper implementation | |
159 virtual void StartStorePolicyOp(const em::PolicyFetchResponse& policy, | |
160 StorePolicyCallback callback) OVERRIDE; | |
161 virtual void StartRetrievePolicyOp(RetrievePolicyCallback callback) OVERRIDE; | |
162 | |
163 // OpContext::Delegate implementation | |
164 virtual void OnOpCreated(OpContext* context); | |
165 virtual void OnOpStarted(OpContext* context); | |
166 virtual void OnOpCompleted(OpContext* context); | |
167 | |
168 private: | |
169 SignedSettingsHelperImpl(); | |
170 virtual ~SignedSettingsHelperImpl(); | |
171 | |
172 void AddOpContext(OpContext* context); | |
173 void ClearAll(); | |
174 | |
175 std::vector<OpContext*> pending_contexts_; | |
176 | |
177 friend struct base::DefaultLazyInstanceTraits<SignedSettingsHelperImpl>; | |
178 DISALLOW_COPY_AND_ASSIGN(SignedSettingsHelperImpl); | |
179 }; | |
180 | |
181 static base::LazyInstance<SignedSettingsHelperImpl> | |
182 g_signed_settings_helper_impl = LAZY_INSTANCE_INITIALIZER; | |
183 | |
184 SignedSettingsHelperImpl::SignedSettingsHelperImpl() { | |
185 } | |
186 | |
187 SignedSettingsHelperImpl::~SignedSettingsHelperImpl() { | |
188 if (!pending_contexts_.empty()) { | |
189 LOG(WARNING) << "SignedSettingsHelperImpl shutdown with pending ops, " | |
190 << "changes will be lost."; | |
191 ClearAll(); | |
192 } | |
193 } | |
194 | |
195 void SignedSettingsHelperImpl::StartStorePolicyOp( | |
196 const em::PolicyFetchResponse& policy, | |
197 StorePolicyCallback callback) { | |
198 AddOpContext(new StorePolicyOpContext(policy, callback, this)); | |
199 } | |
200 | |
201 void SignedSettingsHelperImpl::StartRetrievePolicyOp( | |
202 RetrievePolicyCallback callback) { | |
203 AddOpContext(new RetrievePolicyOpContext(callback, this)); | |
204 } | |
205 | |
206 void SignedSettingsHelperImpl::AddOpContext(OpContext* context) { | |
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
208 CHECK(context); | |
209 | |
210 pending_contexts_.push_back(context); | |
211 if (pending_contexts_.size() == 1) | |
212 context->Execute(); | |
213 } | |
214 | |
215 void SignedSettingsHelperImpl::ClearAll() { | |
216 for (size_t i = 0; i < pending_contexts_.size(); ++i) { | |
217 pending_contexts_[i]->set_delegate(NULL); | |
218 pending_contexts_[i]->Cancel(); | |
219 } | |
220 pending_contexts_.clear(); | |
221 } | |
222 | |
223 void SignedSettingsHelperImpl::OnOpCreated(OpContext* context) { | |
224 if (test_delegate_) | |
225 test_delegate_->OnOpCreated(context->op()); | |
226 } | |
227 | |
228 void SignedSettingsHelperImpl::OnOpStarted(OpContext* context) { | |
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
230 | |
231 if (test_delegate_) | |
232 test_delegate_->OnOpStarted(context->op()); | |
233 } | |
234 | |
235 void SignedSettingsHelperImpl::OnOpCompleted(OpContext* context) { | |
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
237 DCHECK(pending_contexts_.front() == context); | |
238 | |
239 pending_contexts_.erase(pending_contexts_.begin()); | |
240 if (!pending_contexts_.empty()) | |
241 pending_contexts_.front()->Execute(); | |
242 | |
243 if (test_delegate_) | |
244 test_delegate_->OnOpCompleted(context->op()); | |
245 } | |
246 | |
247 SignedSettingsHelper* SignedSettingsHelper::Get() { | |
248 return g_signed_settings_helper_impl.Pointer(); | |
249 } | |
250 | |
251 } // namespace chromeos | |
OLD | NEW |