signed_settings.cc revision bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293
1// Copyright (c) 2010 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.h"
6
7#include <string>
8#include <vector>
9
10#include "base/ref_counted.h"
11#include "base/stringprintf.h"
12#include "chrome/browser/chrome_thread.h"
13#include "chrome/browser/chromeos/cros/cros_library.h"
14#include "chrome/browser/chromeos/cros/login_library.h"
15#include "chrome/browser/chromeos/login/ownership_service.h"
16
17namespace chromeos {
18
19SignedSettings::SignedSettings()
20    : service_(OwnershipService::GetSharedInstance()) {
21}
22
23SignedSettings::~SignedSettings() {}
24
25class CheckWhitelistOp : public SignedSettings {
26 public:
27  CheckWhitelistOp(const std::string& email,
28                   SignedSettings::Delegate<bool>* d);
29  virtual ~CheckWhitelistOp();
30  bool Execute();
31  // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
32  void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
33                       const std::vector<uint8>& payload);
34
35 private:
36  const std::string email_;
37  SignedSettings::Delegate<bool>* d_;
38};
39
40class WhitelistOp : public SignedSettings,
41                    public LoginLibrary::Delegate {
42 public:
43  WhitelistOp(const std::string& email,
44              bool add_to_whitelist,
45              SignedSettings::Delegate<bool>* d);
46  virtual ~WhitelistOp();
47  bool Execute();
48  // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
49  void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
50                       const std::vector<uint8>& payload);
51  // Implementation of LoginLibrary::Delegate::OnComplete()
52  void OnComplete(bool value);
53
54 private:
55  bool InitiateWhitelistOp(const std::vector<uint8>& signature);
56
57  const std::string email_;
58  const bool add_to_whitelist_;
59  SignedSettings::Delegate<bool>* d_;
60};
61
62class StorePropertyOp : public SignedSettings,
63                        public LoginLibrary::Delegate {
64 public:
65  StorePropertyOp(const std::string& name,
66                  const std::string& value,
67                  SignedSettings::Delegate<bool>* d);
68  virtual ~StorePropertyOp();
69  bool Execute();
70  // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
71  void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
72                       const std::vector<uint8>& payload);
73  // Implementation of LoginLibrary::Delegate::OnComplete()
74  void OnComplete(bool value);
75
76 private:
77  std::string name_;
78  std::string value_;
79  SignedSettings::Delegate<bool>* d_;
80};
81
82class RetrievePropertyOp : public SignedSettings {
83 public:
84  RetrievePropertyOp(const std::string& name,
85                     SignedSettings::Delegate<std::string>* d);
86  virtual ~RetrievePropertyOp();
87  bool Execute();
88  // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
89  void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
90                       const std::vector<uint8>& payload);
91
92 private:
93  std::string name_;
94  std::string value_;
95  SignedSettings::Delegate<std::string>* d_;
96};
97
98// static
99SignedSettings* SignedSettings::CreateCheckWhitelistOp(
100    const std::string& email,
101    SignedSettings::Delegate<bool>* d) {
102  return new CheckWhitelistOp(email, d);
103}
104
105// static
106SignedSettings* SignedSettings::CreateWhitelistOp(
107    const std::string& email,
108    bool add_to_whitelist,
109    SignedSettings::Delegate<bool>* d) {
110  return new WhitelistOp(email, add_to_whitelist, d);
111}
112
113// static
114SignedSettings* SignedSettings::CreateStorePropertyOp(
115    const std::string& name,
116    const std::string& value,
117    SignedSettings::Delegate<bool>* d) {
118  return new StorePropertyOp(name, value, d);
119}
120
121// static
122SignedSettings* SignedSettings::CreateRetrievePropertyOp(
123    const std::string& name,
124    SignedSettings::Delegate<std::string>* d) {
125  return new RetrievePropertyOp(name, d);
126}
127
128CheckWhitelistOp::CheckWhitelistOp(const std::string& email,
129                                   SignedSettings::Delegate<bool>* d)
130    : email_(email),
131      d_(d) {
132}
133
134CheckWhitelistOp::~CheckWhitelistOp() {}
135
136bool CheckWhitelistOp::Execute() {
137  CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded());
138  std::vector<uint8> sig;
139  if (!CrosLibrary::Get()->GetLoginLibrary()->CheckWhitelist(email_, &sig))
140    return false;
141
142  // Posts a task to the FILE thread to verify |sig|.
143  service_->StartVerifyAttempt(email_, sig, this);
144  return true;
145}
146
147void CheckWhitelistOp::OnKeyOpComplete(
148    const OwnerManager::KeyOpCode return_code,
149    const std::vector<uint8>& payload) {
150  // Ensure we're on the UI thread, due to the need to send DBus traffic.
151  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
152    ChromeThread::PostTask(
153        ChromeThread::UI, FROM_HERE,
154        NewRunnableMethod(this,
155                          &CheckWhitelistOp::OnKeyOpComplete,
156                          return_code, payload));
157    return;
158  }
159  if (return_code == OwnerManager::SUCCESS)
160    d_->OnSettingsOpSucceeded(true);
161  else
162    d_->OnSettingsOpFailed();
163}
164
165WhitelistOp::WhitelistOp(const std::string& email,
166                         bool add_to_whitelist,
167                         SignedSettings::Delegate<bool>* d)
168    : email_(email),
169      add_to_whitelist_(add_to_whitelist),
170      d_(d) {
171}
172
173WhitelistOp::~WhitelistOp() {}
174
175bool WhitelistOp::Execute() {
176  // Posts a task to the FILE thread to sign |email_|.
177  service_->StartSigningAttempt(email_, this);
178  return true;
179}
180
181void WhitelistOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
182                                  const std::vector<uint8>& payload) {
183  // Ensure we're on the UI thread, due to the need to send DBus traffic.
184  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
185    ChromeThread::PostTask(
186        ChromeThread::UI, FROM_HERE,
187        NewRunnableMethod(this,
188                          &WhitelistOp::OnKeyOpComplete,
189                          return_code, payload));
190    return;
191  }
192  // Now, sure we're on the UI thread.
193  bool success = false;
194  if (return_code == OwnerManager::SUCCESS) {
195    // OnComplete() will be called when this is done.
196    success = InitiateWhitelistOp(payload);
197  }
198  if (!success)
199    d_->OnSettingsOpFailed();
200}
201
202void WhitelistOp::OnComplete(bool value) {
203  if (value)
204    d_->OnSettingsOpSucceeded(value);
205  else
206    d_->OnSettingsOpFailed();
207}
208
209bool WhitelistOp::InitiateWhitelistOp(const std::vector<uint8>& signature) {
210  LoginLibrary* library = CrosLibrary::Get()->GetLoginLibrary();
211  if (add_to_whitelist_)
212    return library->WhitelistAsync(email_, signature, this);
213  return library->UnwhitelistAsync(email_, signature, this);
214}
215
216StorePropertyOp::StorePropertyOp(const std::string& name,
217                                 const std::string& value,
218                                 SignedSettings::Delegate<bool>* d)
219    : name_(name),
220      value_(value),
221      d_(d) {
222}
223
224StorePropertyOp::~StorePropertyOp() {}
225
226bool StorePropertyOp::Execute() {
227  // Posts a task to the FILE thread to sign |name_|=|value_|.
228  std::string to_sign = base::StringPrintf("%s=%s",
229                                           name_.c_str(),
230                                           value_.c_str());
231  service_->StartSigningAttempt(to_sign, this);
232  return true;
233}
234
235void StorePropertyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
236                                      const std::vector<uint8>& payload) {
237  // Ensure we're on the UI thread, due to the need to send DBus traffic.
238  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
239    ChromeThread::PostTask(
240        ChromeThread::UI, FROM_HERE,
241        NewRunnableMethod(this,
242                          &StorePropertyOp::OnKeyOpComplete,
243                          return_code, payload));
244    return;
245  }
246  // Now, sure we're on the UI thread.
247  bool success = false;
248  if (return_code == OwnerManager::SUCCESS) {
249    // OnComplete() will be called when this is done.
250    success = CrosLibrary::Get()->GetLoginLibrary()->StorePropertyAsync(name_,
251                                                                        value_,
252                                                                        payload,
253                                                                        this);
254  }
255  if (!success)
256    d_->OnSettingsOpFailed();
257}
258
259void StorePropertyOp::OnComplete(bool value) {
260  if (value)
261    d_->OnSettingsOpSucceeded(value);
262  else
263    d_->OnSettingsOpFailed();
264}
265
266RetrievePropertyOp::RetrievePropertyOp(const std::string& name,
267                                       SignedSettings::Delegate<std::string>* d)
268    : name_(name),
269      d_(d) {
270}
271
272RetrievePropertyOp::~RetrievePropertyOp() {}
273
274bool RetrievePropertyOp::Execute() {
275  CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded());
276  std::vector<uint8> sig;
277  if (!CrosLibrary::Get()->GetLoginLibrary()->RetrieveProperty(name_,
278                                                               &value_,
279                                                               &sig)) {
280    return false;
281  }
282  std::string to_verify = base::StringPrintf("%s=%s",
283                                             name_.c_str(),
284                                             value_.c_str());
285  // Posts a task to the FILE thread to verify |sig|.
286  service_->StartVerifyAttempt(to_verify, sig, this);
287  return true;
288}
289
290void RetrievePropertyOp::OnKeyOpComplete(
291    const OwnerManager::KeyOpCode return_code,
292    const std::vector<uint8>& payload) {
293  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
294    ChromeThread::PostTask(
295        ChromeThread::UI, FROM_HERE,
296        NewRunnableMethod(this,
297                          &RetrievePropertyOp::OnKeyOpComplete,
298                          return_code, payload));
299    return;
300  }
301  // Now, sure we're on the UI thread.
302  if (return_code == OwnerManager::SUCCESS)
303    d_->OnSettingsOpSucceeded(value_);
304  else
305    d_->OnSettingsOpFailed();
306}
307
308}  // namespace chromeos
309