signed_settings_helper.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
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_helper.h" 6 7#include <string> 8#include <vector> 9 10#include "base/logging.h" 11#include "base/ref_counted.h" 12#include "base/singleton.h" 13#include "chrome/browser/browser_thread.h" 14#include "chrome/browser/chromeos/login/signed_settings.h" 15 16namespace chromeos { 17 18namespace { 19 20class OpContext { 21 public: 22 class Delegate { 23 public: 24 virtual void OnOpCreated(OpContext* context) = 0; 25 virtual void OnOpStarted(OpContext* context) = 0; 26 virtual void OnOpCompleted(OpContext* context) = 0; 27 }; 28 29 virtual ~OpContext() {} 30 31 // Creates and execute op. 32 void Execute() { 33 CreateOp(); 34 CHECK(op_.get()); 35 if (delegate_) 36 delegate_->OnOpCreated(this); 37 38 // Note that the context could be released when op_->Execute() returns. 39 // So keep a local copy of delegate and executing flag to use after 40 // the call. 41 Delegate* delegate = delegate_; 42 bool executing = executing_ = op_->Execute(); 43 if (executing) { 44 if (delegate) 45 delegate->OnOpStarted(this); 46 } else { 47 OnOpFailed(); 48 } 49 } 50 51 // Cancels the callback. 52 void CancelCallback() { 53 callback_ = NULL; 54 } 55 56 // Cancels the callback and cancels the op if it is not executing. 57 void Cancel() { 58 CancelCallback(); 59 60 if (!executing_) 61 OnOpCompleted(); 62 } 63 64 // Accessors. 65 SignedSettings* op() const { 66 return op_.get(); 67 } 68 69 SignedSettingsHelper::Callback* callback() const { 70 return callback_; 71 } 72 73 void set_delegate(Delegate* delegate) { 74 delegate_ = delegate; 75 } 76 77 protected: 78 OpContext(SignedSettingsHelper::Callback* callback, 79 Delegate* delegate) 80 : executing_(false), 81 delegate_(delegate), 82 callback_(callback) { 83 } 84 85 // Creates the op to execute. 86 virtual void CreateOp() = 0; 87 88 // Callback on op completion. 89 virtual void OnOpCompleted() { 90 if (delegate_) 91 delegate_->OnOpCompleted(this); 92 93 delete this; 94 } 95 96 // Callback on op failure. 97 virtual void OnOpFailed() { 98 OnOpCompleted(); 99 } 100 101 bool executing_; 102 Delegate* delegate_; 103 104 scoped_refptr<SignedSettings> op_; 105 SignedSettingsHelper::Callback* callback_; 106}; 107 108class WhitelistOpContext : public SignedSettings::Delegate<bool>, 109 public OpContext { 110 public: 111 enum Type { 112 CHECK, 113 ADD, 114 REMOVE, 115 }; 116 117 WhitelistOpContext(Type type, 118 const std::string& email, 119 SignedSettingsHelper::Callback* callback, 120 Delegate* delegate) 121 : OpContext(callback, delegate), 122 type_(type), 123 email_(email) { 124 } 125 126 // chromeos::SignedSettings::Delegate implementation 127 virtual void OnSettingsOpSucceeded(bool value) { 128 if (callback_) { 129 switch (type_) { 130 case CHECK: 131 callback_->OnCheckWhiteListCompleted(value, email_); 132 break; 133 case ADD: 134 callback_->OnWhitelistCompleted(value, email_); 135 break; 136 case REMOVE: 137 callback_->OnUnwhitelistCompleted(value, email_); 138 break; 139 default: 140 LOG(ERROR) << "Unknown WhitelistOpContext type " << type_; 141 break; 142 } 143 } 144 145 OnOpCompleted(); 146 } 147 148 virtual void OnSettingsOpFailed() { 149 OnOpFailed(); 150 } 151 152 protected: 153 // OpContext implemenetation 154 virtual void CreateOp() { 155 switch (type_) { 156 case CHECK: 157 op_ = SignedSettings::CreateCheckWhitelistOp(email_, this); 158 break; 159 case ADD: 160 op_ = SignedSettings::CreateWhitelistOp(email_, true, this); 161 break; 162 case REMOVE: 163 op_ = SignedSettings::CreateWhitelistOp(email_, false, this); 164 break; 165 default: 166 LOG(ERROR) << "Unknown WhitelistOpContext type " << type_; 167 break; 168 } 169 } 170 171 virtual void OnOpFailed() { 172 if (callback_) { 173 switch (type_) { 174 case CHECK: 175 callback_->OnCheckWhiteListCompleted(false, email_); 176 break; 177 case ADD: 178 callback_->OnWhitelistCompleted(false, email_); 179 break; 180 case REMOVE: 181 callback_->OnUnwhitelistCompleted(false, email_); 182 break; 183 default: 184 LOG(ERROR) << "Unknown WhitelistOpContext type " << type_; 185 break; 186 } 187 } 188 189 OnOpCompleted(); 190 } 191 192 private: 193 Type type_; 194 std::string email_; 195 196 DISALLOW_COPY_AND_ASSIGN(WhitelistOpContext); 197}; 198 199class StorePropertyOpContext : public SignedSettings::Delegate<bool>, 200 public OpContext { 201 public: 202 StorePropertyOpContext(const std::string& name, 203 const std::string& value, 204 SignedSettingsHelper::Callback* callback, 205 Delegate* delegate) 206 : OpContext(callback, delegate), 207 name_(name), 208 value_(value) { 209 } 210 211 // chromeos::SignedSettings::Delegate implementation 212 virtual void OnSettingsOpSucceeded(bool value) { 213 if (callback_) 214 callback_->OnStorePropertyCompleted(true, name_, value_); 215 OnOpCompleted(); 216 } 217 218 virtual void OnSettingsOpFailed() { 219 OnOpFailed(); 220 } 221 222 protected: 223 // OpContext implemenetation 224 virtual void CreateOp() { 225 op_ = SignedSettings::CreateStorePropertyOp(name_, value_, this); 226 } 227 228 virtual void OnOpFailed() { 229 if (callback_) 230 callback_->OnStorePropertyCompleted(false, name_, value_); 231 OnOpCompleted(); 232 } 233 234 private: 235 std::string name_; 236 std::string value_; 237 238 DISALLOW_COPY_AND_ASSIGN(StorePropertyOpContext); 239}; 240 241class RetrievePropertyOpContext 242 : public SignedSettings::Delegate<std::string>, 243 public OpContext { 244 public: 245 RetrievePropertyOpContext(const std::string& name, 246 SignedSettingsHelper::Callback* callback, 247 Delegate* delegate) 248 : OpContext(callback, delegate), 249 name_(name) { 250 } 251 252 // chromeos::SignedSettings::Delegate implementation 253 virtual void OnSettingsOpSucceeded(std::string value) { 254 if (callback_) 255 callback_->OnRetrievePropertyCompleted(true, name_, value); 256 257 OnOpCompleted(); 258 } 259 260 virtual void OnSettingsOpFailed() { 261 OnOpFailed(); 262 } 263 264 protected: 265 // OpContext implemenetation 266 virtual void CreateOp() { 267 op_ = SignedSettings::CreateRetrievePropertyOp(name_, this); 268 } 269 270 virtual void OnOpFailed() { 271 if (callback_) 272 callback_->OnRetrievePropertyCompleted(false, name_, std::string()); 273 OnOpCompleted(); 274 } 275 276 private: 277 std::string name_; 278 279 DISALLOW_COPY_AND_ASSIGN(RetrievePropertyOpContext); 280}; 281 282} // namespace 283 284 285class SignedSettingsHelperImpl : public SignedSettingsHelper, 286 public OpContext::Delegate { 287 public: 288 // SignedSettingsHelper implementation 289 virtual void StartCheckWhitelistOp(const std::string& email, 290 Callback* callback); 291 virtual void StartWhitelistOp(const std::string& email, 292 bool add_to_whitelist, 293 Callback* callback); 294 virtual void StartStorePropertyOp(const std::string& name, 295 const std::string& value, 296 Callback* callback); 297 virtual void StartRetrieveProperty(const std::string& name, 298 Callback* callback); 299 virtual void CancelCallback(Callback* callback); 300 301 // OpContext::Delegate implementation 302 virtual void OnOpCreated(OpContext* context); 303 virtual void OnOpStarted(OpContext* context); 304 virtual void OnOpCompleted(OpContext* context); 305 306 private: 307 SignedSettingsHelperImpl(); 308 ~SignedSettingsHelperImpl(); 309 310 void AddOpContext(OpContext* context); 311 void ClearAll(); 312 313 std::vector<OpContext*> pending_contexts_; 314 315 friend struct DefaultSingletonTraits<SignedSettingsHelperImpl>; 316 DISALLOW_COPY_AND_ASSIGN(SignedSettingsHelperImpl); 317}; 318 319SignedSettingsHelperImpl::SignedSettingsHelperImpl() { 320} 321 322SignedSettingsHelperImpl::~SignedSettingsHelperImpl() { 323 if (!pending_contexts_.empty()) { 324 LOG(WARNING) << "SignedSettingsHelperImpl shutdown with pending ops, " 325 << "changes will be lost."; 326 ClearAll(); 327 } 328} 329 330void SignedSettingsHelperImpl::StartCheckWhitelistOp( 331 const std::string&email, 332 SignedSettingsHelper::Callback* callback) { 333 AddOpContext(new WhitelistOpContext( 334 WhitelistOpContext::CHECK, 335 email, 336 callback, 337 this)); 338} 339 340void SignedSettingsHelperImpl::StartWhitelistOp( 341 const std::string&email, 342 bool add_to_whitelist, 343 SignedSettingsHelper::Callback* callback) { 344 AddOpContext(new WhitelistOpContext( 345 add_to_whitelist ? WhitelistOpContext::ADD : WhitelistOpContext::REMOVE, 346 email, 347 callback, 348 this)); 349} 350 351void SignedSettingsHelperImpl::StartStorePropertyOp( 352 const std::string& name, 353 const std::string& value, 354 SignedSettingsHelper::SignedSettingsHelper::Callback* callback) { 355 AddOpContext(new StorePropertyOpContext( 356 name, 357 value, 358 callback, 359 this)); 360} 361 362void SignedSettingsHelperImpl::StartRetrieveProperty( 363 const std::string& name, 364 SignedSettingsHelper::Callback* callback) { 365 AddOpContext(new RetrievePropertyOpContext( 366 name, 367 callback, 368 this)); 369} 370 371void SignedSettingsHelperImpl::CancelCallback( 372 SignedSettingsHelper::Callback* callback) { 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 374 375 for (size_t i = 0; i < pending_contexts_.size(); ++i) { 376 if (pending_contexts_[i]->callback() == callback) { 377 pending_contexts_[i]->CancelCallback(); 378 } 379 } 380} 381 382void SignedSettingsHelperImpl::AddOpContext(OpContext* context) { 383 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 384 CHECK(context); 385 386 pending_contexts_.push_back(context); 387 if (pending_contexts_.size() == 1) 388 context->Execute(); 389} 390 391void SignedSettingsHelperImpl::ClearAll() { 392 for (size_t i = 0; i < pending_contexts_.size(); ++i) { 393 pending_contexts_[i]->set_delegate(NULL); 394 pending_contexts_[i]->Cancel(); 395 } 396 pending_contexts_.clear(); 397} 398 399void SignedSettingsHelperImpl::OnOpCreated(OpContext* context) { 400 if (test_delegate_) 401 test_delegate_->OnOpCreated(context->op()); 402} 403 404void SignedSettingsHelperImpl::OnOpStarted(OpContext* context) { 405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 406 407 if (test_delegate_) 408 test_delegate_->OnOpStarted(context->op()); 409} 410 411void SignedSettingsHelperImpl::OnOpCompleted(OpContext* context) { 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 413 DCHECK(pending_contexts_.front() == context); 414 415 pending_contexts_.erase(pending_contexts_.begin()); 416 if (!pending_contexts_.empty()) 417 pending_contexts_.front()->Execute(); 418 419 if (test_delegate_) 420 test_delegate_->OnOpCompleted(context->op()); 421} 422 423SignedSettingsHelper* SignedSettingsHelper::Get() { 424 return Singleton<SignedSettingsHelperImpl>::get(); 425} 426 427} // namespace chromeos 428