summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/cros/login_library.cc30
-rw-r--r--chrome/browser/chromeos/cros/login_library.h5
-rw-r--r--chrome/browser/chromeos/cros_settings_names.cc5
-rw-r--r--chrome/browser/chromeos/cros_settings_names.h4
-rw-r--r--chrome/browser/chromeos/login/mock_ownership_service.h5
-rw-r--r--chrome/browser/chromeos/login/ownership_service.cc14
-rw-r--r--chrome/browser/chromeos/login/ownership_service.h14
-rw-r--r--chrome/browser/chromeos/login/signed_settings.cc633
-rw-r--r--chrome/browser/chromeos/login/signed_settings.h35
-rw-r--r--chrome/browser/chromeos/login/signed_settings_helper_unittest.cc106
-rw-r--r--chrome/browser/chromeos/login/signed_settings_unittest.cc413
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.cc4
-rw-r--r--chrome/browser/chromeos/user_cros_settings_provider.cc4
13 files changed, 979 insertions, 293 deletions
diff --git a/chrome/browser/chromeos/cros/login_library.cc b/chrome/browser/chromeos/cros/login_library.cc
index 4d5d4e4..3a042f9 100644
--- a/chrome/browser/chromeos/cros/login_library.cc
+++ b/chrome/browser/chromeos/cros/login_library.cc
@@ -9,12 +9,15 @@
#include "base/timer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/login/signed_settings.h"
#include "chrome/browser/chromeos/login/signed_settings_temp_storage.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/prefs/pref_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
#include "content/common/notification_type.h"
+namespace em = enterprise_management;
namespace chromeos {
class LoginLibraryImpl : public LoginLibrary {
@@ -113,7 +116,9 @@ class LoginLibraryImpl : public LoginLibrary {
return rv;
}
+ // DEPRECATED.
bool EnumerateWhitelisted(std::vector<std::string>* whitelisted) {
+ NOTREACHED();
UserList* list = NULL;
if (chromeos::EnumerateWhitelistedSafe(&list)) {
for (int i = 0; i < list->num_users; i++)
@@ -193,6 +198,24 @@ class LoginLibraryImpl : public LoginLibrary {
base::OneShotTimer<JobRestartRequest> timer_;
};
+ class StubDelegate
+ : public SignedSettings::Delegate<const em::PolicyFetchResponse&> {
+ public:
+ StubDelegate() : polfetcher_(NULL) {}
+ virtual ~StubDelegate() {}
+ void set_fetcher(SignedSettings* s) { polfetcher_ = s; }
+ SignedSettings* fetcher() { return polfetcher_.get(); }
+ // Implementation of SignedSettings::Delegate
+ virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& value) {
+ VLOG(2) << "Done Fetching Policy";
+ delete this;
+ }
+ private:
+ scoped_refptr<SignedSettings> polfetcher_;
+ DISALLOW_COPY_AND_ASSIGN(StubDelegate);
+ };
+
static void Handler(void* object, const OwnershipEvent& event) {
LoginLibraryImpl* self = static_cast<LoginLibraryImpl*>(object);
switch (event) {
@@ -253,9 +276,10 @@ class LoginLibraryImpl : public LoginLibrary {
}
void CompletePropertyOp(bool result) {
- if (property_op_callback_) {
- property_op_callback_->OnComplete(result);
- property_op_callback_ = NULL;
+ if (result) {
+ StubDelegate* stub = new StubDelegate(); // Manages its own lifetime.
+ stub->set_fetcher(SignedSettings::CreateRetrievePolicyOp(stub));
+ stub->fetcher()->Execute();
}
}
diff --git a/chrome/browser/chromeos/cros/login_library.h b/chrome/browser/chromeos/cros/login_library.h
index 55d1ce6..d61f6ac 100644
--- a/chrome/browser/chromeos/cros/login_library.h
+++ b/chrome/browser/chromeos/cros/login_library.h
@@ -77,6 +77,11 @@ class LoginLibrary {
const std::vector<uint8>& signature,
Delegate* callback) = 0;
+ // DEPRECATED. We have re-implemented owner-signed settings by fetching
+ // and caching a policy, and then pulling values from there. This is all
+ // handled at the SignedSettings layer, so anyone using this stuff directly
+ // should not be doing so anymore.
+ //
// Retrieves the user white list. Note the call is for display purpose only.
// To determine if an email is white listed, you MUST use CheckWhitelist.
// Returns true if the request is successfully dispatched.
diff --git a/chrome/browser/chromeos/cros_settings_names.cc b/chrome/browser/chromeos/cros_settings_names.cc
index 46e5ee5..ea9aa69 100644
--- a/chrome/browser/chromeos/cros_settings_names.cc
+++ b/chrome/browser/chromeos/cros_settings_names.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -15,6 +15,9 @@ const char kAccountsPrefShowUserNamesOnSignIn[]
= "cros.accounts.showUserNamesOnSignIn";
const char kAccountsPrefUsers[] = "cros.accounts.users";
+// Name of signed setting persisted on device, writeable only by owner.
+const char kSettingProxyEverywhere[] = "cros.proxy.everywhere";
+
// All cros.signed.* settings are stored in SignedSettings.
const char kSignedDataRoamingEnabled[] = "cros.signed.data_roaming_enabled";
diff --git a/chrome/browser/chromeos/cros_settings_names.h b/chrome/browser/chromeos/cros_settings_names.h
index 14b3889..75f4fa9 100644
--- a/chrome/browser/chromeos/cros_settings_names.h
+++ b/chrome/browser/chromeos/cros_settings_names.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -15,6 +15,8 @@ extern const char kAccountsPrefAllowNewUser[];
extern const char kAccountsPrefShowUserNamesOnSignIn[];
extern const char kAccountsPrefUsers[];
+extern const char kSettingProxyEverywhere[];
+
extern const char kSignedDataRoamingEnabled[];
extern const char kSystemTimezone[];
diff --git a/chrome/browser/chromeos/login/mock_ownership_service.h b/chrome/browser/chromeos/login/mock_ownership_service.h
index db88843..3c9aae0 100644
--- a/chrome/browser/chromeos/login/mock_ownership_service.h
+++ b/chrome/browser/chromeos/login/mock_ownership_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -15,6 +15,9 @@ namespace chromeos {
class MockOwnershipService : public OwnershipService {
public:
+ MOCK_METHOD1(set_cached_policy, void(const em::PolicyData&));
+ MOCK_METHOD0(has_cached_policy, bool(void));
+ MOCK_METHOD0(cached_policy, const em::PolicyData&(void));
MOCK_METHOD0(IsAlreadyOwned, bool(void));
MOCK_METHOD1(GetStatus, OwnershipService::Status(bool));
MOCK_METHOD0(StartLoadOwnerKeyAttempt, void(void));
diff --git a/chrome/browser/chromeos/login/ownership_service.cc b/chrome/browser/chromeos/login/ownership_service.cc
index 85ad7a1..34643c9 100644
--- a/chrome/browser/chromeos/login/ownership_service.cc
+++ b/chrome/browser/chromeos/login/ownership_service.cc
@@ -28,6 +28,7 @@ OwnershipService* OwnershipService::GetSharedInstance() {
OwnershipService::OwnershipService()
: manager_(new OwnerManager),
utils_(OwnerKeyUtils::Create()),
+ policy_(NULL),
ownership_status_(OWNERSHIP_UNKNOWN) {
notification_registrar_.Add(
this,
@@ -50,6 +51,19 @@ OwnershipService::OwnershipService()
OwnershipService::~OwnershipService() {}
+void OwnershipService::set_cached_policy(const em::PolicyData& pol) {
+ policy_.reset(pol.New());
+ policy_->CheckTypeAndMergeFrom(pol);
+}
+
+bool OwnershipService::has_cached_policy() {
+ return policy_.get();
+}
+
+const em::PolicyData& OwnershipService::cached_policy() {
+ return *(policy_.get());
+}
+
bool OwnershipService::IsAlreadyOwned() {
return file_util::PathExists(utils_->GetOwnerKeyFilePath());
}
diff --git a/chrome/browser/chromeos/login/ownership_service.h b/chrome/browser/chromeos/login/ownership_service.h
index 3ec68d7..c82cbcd 100644
--- a/chrome/browser/chromeos/login/ownership_service.h
+++ b/chrome/browser/chromeos/login/ownership_service.h
@@ -13,6 +13,7 @@
#include "base/synchronization/lock.h"
#include "chrome/browser/chromeos/login/owner_key_utils.h"
#include "chrome/browser/chromeos/login/owner_manager.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
@@ -22,6 +23,7 @@ namespace base {
template <typename T> struct DefaultLazyInstanceTraits;
}
+namespace em = enterprise_management;
namespace chromeos {
class OwnershipService : public NotificationObserver {
@@ -37,6 +39,17 @@ class OwnershipService : public NotificationObserver {
static OwnershipService* GetSharedInstance();
virtual ~OwnershipService();
+ // Owner settings are being re-implemented as a single, signed protobuf
+ // that is stored by the session manager. Thus, to write a setting, you
+ // need to have the existing policy, update it, re-sign it, and then have
+ // it stored. This could be done by requesting the policy every time, or
+ // by caching it and updating it upon every successful store.
+ // Caching is faster and easier, so we'll do that. These are the
+ // getters/setters for the cached policy.
+ virtual void set_cached_policy(const em::PolicyData& pol);
+ virtual bool has_cached_policy();
+ virtual const em::PolicyData& cached_policy();
+
// Sets a new owner key. This will _not_ load the key material from disk, but
// rather update Chrome's in-memory copy of the key. |callback| will be
// invoked once the operation completes.
@@ -120,6 +133,7 @@ class OwnershipService : public NotificationObserver {
scoped_refptr<OwnerManager> manager_;
scoped_refptr<OwnerKeyUtils> utils_;
+ scoped_ptr<em::PolicyData> policy_;
NotificationRegistrar notification_registrar_;
Status ownership_status_;
base::Lock ownership_status_lock_;
diff --git a/chrome/browser/chromeos/login/signed_settings.cc b/chrome/browser/chromeos/login/signed_settings.cc
index 6e90a93..93d22b4 100644
--- a/chrome/browser/chromeos/login/signed_settings.cc
+++ b/chrome/browser/chromeos/login/signed_settings.cc
@@ -13,30 +13,90 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/signed_settings_temp_storage.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
#include "content/browser/browser_thread.h"
namespace chromeos {
+using google::protobuf::RepeatedPtrField;
+using std::string;
+
+// static
+const char SignedSettings::kDevicePolicyType[] = "google/chromeos/device";
+
+SignedSettings::Relay::Relay(SignedSettings* s) : settings_(s) {
+}
+
+SignedSettings::Relay::~Relay() {}
+
+void SignedSettings::Relay::OnSettingsOpCompleted(
+ SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& value) {
+ if (code == SignedSettings::SUCCESS) {
+ settings_->Execute();
+ return;
+ }
+ settings_->Fail(code);
+}
SignedSettings::SignedSettings()
- : service_(OwnershipService::GetSharedInstance()) {
+ : service_(OwnershipService::GetSharedInstance()),
+ relay_(NULL),
+ polfetcher_(NULL) {
}
SignedSettings::~SignedSettings() {}
+void SignedSettings::TryToFetchPolicyAndCallBack() {
+ relay_.reset(new Relay(this));
+ polfetcher_ = SignedSettings::CreateRetrievePolicyOp(relay_.get());
+ polfetcher_->set_service(service_);
+ polfetcher_->Execute();
+}
+
+// static
+bool SignedSettings::PolicyIsSane(const em::PolicyFetchResponse& value,
+ em::PolicyData* poldata) {
+ if (value.has_policy_data()) {
+ poldata->ParseFromString(value.policy_data());
+ if (poldata->has_policy_type() &&
+ poldata->policy_type() == kDevicePolicyType &&
+ poldata->has_policy_value()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// static
SignedSettings::ReturnCode SignedSettings::MapKeyOpCode(
OwnerManager::KeyOpCode return_code) {
return (return_code == OwnerManager::KEY_UNAVAILABLE ?
KEY_UNAVAILABLE : BAD_SIGNATURE);
}
-void SignedSettings::OnBoolComplete(void* delegate, bool success) {
- SignedSettings::Delegate<bool>* d =
- static_cast< SignedSettings::Delegate<bool>* >(delegate);
- d->OnSettingsOpCompleted(success ? SUCCESS : NOT_FOUND, success);
+// static
+bool SignedSettings::EnumerateWhitelist(std::vector<std::string>* whitelisted) {
+ OwnershipService* service = OwnershipService::GetSharedInstance();
+ if (!service->has_cached_policy())
+ return false;
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(service->cached_policy().policy_value());
+ if (!pol.has_user_whitelist())
+ return false;
+
+ const RepeatedPtrField<std::string>& whitelist =
+ pol.user_whitelist().user_whitelist();
+ for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
+ it != whitelist.end();
+ ++it) {
+ whitelisted->push_back(*it);
+ }
+ return true;
}
class CheckWhitelistOp : public SignedSettings {
@@ -45,55 +105,88 @@ class CheckWhitelistOp : public SignedSettings {
SignedSettings::Delegate<bool>* d);
virtual ~CheckWhitelistOp();
void Execute();
- // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
+ void Fail(SignedSettings::ReturnCode code);
+ void Succeed(bool value);
+ // Implementation of OwnerManager::Delegate
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload);
private:
+ bool LookUpInPolicy(const std::string& email);
+ // Always call d_->OnSettingOpCompleted() via this call.
+ // It guarantees that the callback will not be triggered until _after_
+ // Execute() returns, which is implicitly assumed by SignedSettingsHelper
+ // in some cases.
+ void PerformCallback(SignedSettings::ReturnCode code, bool value);
+
const std::string email_;
SignedSettings::Delegate<bool>* d_;
};
class WhitelistOp : public SignedSettings,
- public LoginLibrary::Delegate {
+ public SignedSettings::Delegate<bool> {
public:
WhitelistOp(const std::string& email,
bool add_to_whitelist,
SignedSettings::Delegate<bool>* d);
virtual ~WhitelistOp();
void Execute();
- // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
+ void Fail(SignedSettings::ReturnCode code);
+ void Succeed(bool value);
+ // Implementation of OwnerManager::Delegate
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload);
- // Implementation of LoginLibrary::Delegate::OnComplete()
- void OnComplete(bool value);
+ // Implementation of SignedSettings::Delegate
+ void OnSettingsOpCompleted(ReturnCode code, bool value);
private:
- bool InitiateWhitelistOp(const std::vector<uint8>& signature);
+ void ModifyWhitelist(const std::string& email,
+ bool add_to_whitelist,
+ em::UserWhitelistProto* whitelist_proto);
+ // Always call d_->OnSettingOpCompleted() via this call.
+ // It guarantees that the callback will not be triggered until _after_
+ // Execute() returns, which is implicitly assumed by SignedSettingsHelper
+ // in some cases.
+ void PerformCallback(SignedSettings::ReturnCode code, bool value);
const std::string email_;
const bool add_to_whitelist_;
SignedSettings::Delegate<bool>* d_;
+ em::PolicyFetchResponse to_store_;
+ scoped_refptr<SignedSettings> store_op_;
};
class StorePropertyOp : public SignedSettings,
- public LoginLibrary::Delegate {
+ public SignedSettings::Delegate<bool> {
public:
StorePropertyOp(const std::string& name,
const std::string& value,
SignedSettings::Delegate<bool>* d);
virtual ~StorePropertyOp();
void Execute();
- // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
+ void Fail(SignedSettings::ReturnCode code);
+ void Succeed(bool value);
+ // Implementation of OwnerManager::Delegate
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload);
- // Implementation of LoginLibrary::Delegate::OnComplete()
- void OnComplete(bool value);
+ // Implementation of SignedSettings::Delegate
+ void OnSettingsOpCompleted(ReturnCode code, bool value);
private:
+ void SetInPolicy(const std::string& prop,
+ const std::string& value,
+ em::PolicyData* poldata);
+ // Always call d_->OnSettingOpCompleted() via this call.
+ // It guarantees that the callback will not be triggered until _after_
+ // Execute() returns, which is implicitly assumed by SignedSettingsHelper
+ // in some cases.
+ void PerformCallback(SignedSettings::ReturnCode code, bool value);
+
std::string name_;
std::string value_;
SignedSettings::Delegate<bool>* d_;
+ em::PolicyFetchResponse to_store_;
+ scoped_refptr<SignedSettings> store_op_;
};
class RetrievePropertyOp : public SignedSettings {
@@ -102,15 +195,22 @@ class RetrievePropertyOp : public SignedSettings {
SignedSettings::Delegate<std::string>* d);
virtual ~RetrievePropertyOp();
void Execute();
+ void Fail(SignedSettings::ReturnCode code);
+ void Succeed(const std::string& value);
// Implementation of OwnerManager::Delegate::OnKeyOpComplete()
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload);
private:
- // RetrievePropertyCallback
- static void OnRetrievePropertyNotify(void* user_data,
- bool success,
- const Property* property);
+ static const char* kVeritas[];
+
+ std::string LookUpInPolicy(const std::string& prop);
+ // Always call d_->OnSettingOpCompleted() via this call.
+ // It guarantees that the callback will not be triggered until _after_
+ // Execute() returns, which is implicitly assumed by SignedSettingsHelper
+ // in some cases.
+ void PerformCallback(SignedSettings::ReturnCode code,
+ const std::string& value);
std::string name_;
std::string value_;
@@ -123,11 +223,20 @@ class StorePolicyOp : public SignedSettings {
SignedSettings::Delegate<bool>* d);
virtual ~StorePolicyOp();
void Execute();
- // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
+ void Fail(SignedSettings::ReturnCode code);
+ void Succeed(bool value);
+ // Implementation of OwnerManager::Delegate
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload);
private:
+ static void OnBoolComplete(void* delegate, bool success);
+ // Always call d_->OnSettingOpCompleted() via this call.
+ // It guarantees that the callback will not be triggered until _after_
+ // Execute() returns, which is implicitly assumed by SignedSettingsHelper
+ // in some cases.
+ void PerformCallback(SignedSettings::ReturnCode code, bool value);
+
em::PolicyFetchResponse* policy_;
SignedSettings::Delegate<bool>* d_;
@@ -140,7 +249,9 @@ class RetrievePolicyOp : public SignedSettings {
SignedSettings::Delegate<const em::PolicyFetchResponse&>* d);
virtual ~RetrievePolicyOp();
void Execute();
- // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
+ void Fail(SignedSettings::ReturnCode code);
+ void Succeed(const em::PolicyFetchResponse& value);
+ // Implementation of OwnerManager::Delegate
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload);
@@ -148,11 +259,17 @@ class RetrievePolicyOp : public SignedSettings {
static void OnStringComplete(void* delegate,
const char* policy,
const unsigned int len);
+ // Always call d_->OnSettingOpCompleted() via this call.
+ // It guarantees that the callback will not be triggered until _after_
+ // Execute() returns, which is implicitly assumed by SignedSettingsHelper
+ // in some cases.
+ void PerformCallback(SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& value);
+
+ void ProcessPolicy(const char* out, const unsigned int len);
em::PolicyFetchResponse policy_;
SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_;
-
- void ProcessPolicy(const char* out, const unsigned int len);
};
// static
@@ -219,31 +336,48 @@ void CheckWhitelistOp::Execute() {
CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded());
std::vector<uint8> sig;
std::string email_to_check = email_;
- if (!CrosLibrary::Get()->GetLoginLibrary()->CheckWhitelist(
- email_to_check, &sig)) {
- // If the exact match was not found try to match agains a wildcard entry
- // where the domain only matches (e.g. *@example.com). In theory we should
- // always have correctly formated mail address here but a little precaution
- // does no harm.
- if (email_.find('@') != std::string::npos) {
- email_to_check = std::string("*").append(email_.substr(email_.find('@')));
- if (!CrosLibrary::Get()->GetLoginLibrary()->CheckWhitelist(
- email_to_check, &sig)) {
- d_->OnSettingsOpCompleted(NOT_FOUND, false);
- return;
- }
- } else {
- d_->OnSettingsOpCompleted(NOT_FOUND, false);
+ if (!service_->has_cached_policy()) {
+ TryToFetchPolicyAndCallBack();
+ return;
+ }
+ if (LookUpInPolicy(email_to_check)) {
+ VLOG(2) << "Whitelist check was successful for " << email_to_check;
+ Succeed(true);
+ return;
+ }
+ // If the exact match was not found try to match against a wildcard entry
+ // where the domain only matches (e.g. *@example.com). In theory we should
+ // always have correctly formated mail address here but a little precaution
+ // does no harm.
+ if (email_.find('@') != std::string::npos) {
+ email_to_check = std::string("*").append(email_.substr(email_.find('@')));
+ if (LookUpInPolicy(email_to_check)) {
+ VLOG(2) << "Whitelist check was successful for " << email_to_check;
+ Succeed(true);
return;
}
}
- // Posts a task to the FILE thread to verify |sig|.
- service_->StartVerifyAttempt(email_to_check, sig, this);
+ Fail(NOT_FOUND);
+ return;
+}
+
+void CheckWhitelistOp::Fail(SignedSettings::ReturnCode code) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &CheckWhitelistOp::PerformCallback, code, false));
+}
+
+void CheckWhitelistOp::Succeed(bool value) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &CheckWhitelistOp::PerformCallback,
+ SUCCESS, value));
}
void CheckWhitelistOp::OnKeyOpComplete(
const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload) {
+ NOTREACHED();
// Ensure we're on the UI thread, due to the need to send DBus traffic.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
@@ -255,11 +389,33 @@ void CheckWhitelistOp::OnKeyOpComplete(
}
if (return_code == OwnerManager::SUCCESS) {
VLOG(2) << "Whitelist check was successful.";
- d_->OnSettingsOpCompleted(SUCCESS, true);
+ Succeed(true);
} else {
VLOG(2) << "Whitelist check failed.";
- d_->OnSettingsOpCompleted(SignedSettings::MapKeyOpCode(return_code), false);
+ Fail(SignedSettings::MapKeyOpCode(return_code));
+ }
+}
+
+bool CheckWhitelistOp::LookUpInPolicy(const std::string& email) {
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(service_->cached_policy().policy_value());
+ if (!pol.has_user_whitelist())
+ return false;
+
+ const RepeatedPtrField<std::string>& whitelist =
+ pol.user_whitelist().user_whitelist();
+ for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
+ it != whitelist.end();
+ ++it) {
+ if (email == *it)
+ return true;
}
+ return false;
+}
+
+void CheckWhitelistOp::PerformCallback(SignedSettings::ReturnCode code,
+ bool value) {
+ d_->OnSettingsOpCompleted(code, value);
}
WhitelistOp::WhitelistOp(const std::string& email,
@@ -273,43 +429,98 @@ WhitelistOp::WhitelistOp(const std::string& email,
WhitelistOp::~WhitelistOp() {}
void WhitelistOp::Execute() {
- // Posts a task to the FILE thread to sign |email_|.
- service_->StartSigningAttempt(email_, this);
+ if (!service_->has_cached_policy()) {
+ TryToFetchPolicyAndCallBack();
+ return;
+ }
+ em::PolicyData to_sign;
+ to_sign.CheckTypeAndMergeFrom(service_->cached_policy());
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(to_sign.policy_value());
+ em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist();
+ ModifyWhitelist(email_, add_to_whitelist_, whitelist_proto);
+ to_sign.set_policy_value(pol.SerializeAsString());
+ to_store_.set_policy_data(to_sign.SerializeAsString());
+ service_->StartSigningAttempt(to_store_.policy_data(), this);
+}
+
+void WhitelistOp::Fail(SignedSettings::ReturnCode code) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &WhitelistOp::PerformCallback, code, false));
+}
+
+void WhitelistOp::Succeed(bool value) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &WhitelistOp::PerformCallback, SUCCESS, value));
}
void WhitelistOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
- const std::vector<uint8>& payload) {
+ const std::vector<uint8>& sig) {
// Ensure we're on the UI thread, due to the need to send DBus traffic.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableMethod(this,
&WhitelistOp::OnKeyOpComplete,
- return_code, payload));
+ return_code, sig));
return;
}
+ VLOG(2) << "WhitelistOp::OnKeyOpComplete return_code = " << return_code;
// Now, sure we're on the UI thread.
if (return_code == OwnerManager::SUCCESS) {
- // OnComplete() will be called by this call, if it succeeds.
- if (!InitiateWhitelistOp(payload))
- d_->OnSettingsOpCompleted(OPERATION_FAILED, false);
+ to_store_.set_policy_data_signature(
+ std::string(reinterpret_cast<const char*>(&sig[0]), sig.size()));
+ store_op_ = CreateStorePolicyOp(&to_store_, this);
+ // d_->OnSettingsOpCompleted() will be called by this call.
+ store_op_->Execute();
} else {
- d_->OnSettingsOpCompleted(SignedSettings::MapKeyOpCode(return_code), false);
+ Fail(SignedSettings::MapKeyOpCode(return_code));
}
}
-void WhitelistOp::OnComplete(bool value) {
- if (value)
- d_->OnSettingsOpCompleted(SUCCESS, value);
- else
- d_->OnSettingsOpCompleted(NOT_FOUND, false);
+void WhitelistOp::OnSettingsOpCompleted(ReturnCode code, bool value) {
+ if (value && to_store_.has_policy_data()) {
+ em::PolicyData poldata;
+ poldata.ParseFromString(to_store_.policy_data());
+ service_->set_cached_policy(poldata);
+ Succeed(value);
+ return;
+ }
+ Fail(NOT_FOUND);
+}
+
+void WhitelistOp::ModifyWhitelist(const std::string& email,
+ bool add_to_whitelist,
+ em::UserWhitelistProto* whitelist_proto) {
+ int i = 0;
+ const RepeatedPtrField<string>& whitelist = whitelist_proto->user_whitelist();
+ for (RepeatedPtrField<string>::const_iterator it = whitelist.begin();
+ it != whitelist.end();
+ ++it, ++i) {
+ if (email == *it)
+ break;
+ }
+ // |i| contains the index of |email|, if it is in |whitelist|.
+ if (add_to_whitelist) {
+ if (i >= whitelist.size()) // |email| was not in |whitelist|, we must add.
+ whitelist_proto->add_user_whitelist(email);
+ return;
+ } else {
+ if (i < whitelist.size()) { // |email| was in |whitelist|, we must remove.
+ RepeatedPtrField<string>* change_list =
+ whitelist_proto->mutable_user_whitelist();
+ change_list->SwapElements(i, whitelist.size() - 1); // Move to end.
+ change_list->RemoveLast();
+ }
+ return;
+ }
+ LOG(WARNING) << "Whitelist modification no-op: " << email;
}
-bool WhitelistOp::InitiateWhitelistOp(const std::vector<uint8>& signature) {
- LoginLibrary* library = CrosLibrary::Get()->GetLoginLibrary();
- if (add_to_whitelist_)
- return library->WhitelistAsync(email_, signature, this);
- return library->UnwhitelistAsync(email_, signature, this);
+void WhitelistOp::PerformCallback(SignedSettings::ReturnCode code, bool value) {
+ d_->OnSettingsOpCompleted(code, value);
}
StorePropertyOp::StorePropertyOp(const std::string& name,
@@ -317,7 +528,8 @@ StorePropertyOp::StorePropertyOp(const std::string& name,
SignedSettings::Delegate<bool>* d)
: name_(name),
value_(value),
- d_(d) {
+ d_(d),
+ store_op_(NULL) {
}
StorePropertyOp::~StorePropertyOp() {}
@@ -328,50 +540,111 @@ void StorePropertyOp::Execute() {
g_browser_process->local_state() &&
SignedSettingsTempStorage::Store(name_, value_,
g_browser_process->local_state())) {
- d_->OnSettingsOpCompleted(SUCCESS, true);
+ Succeed(true);
return;
}
}
- // Posts a task to the FILE thread to sign |name_|=|value_|.
- std::string to_sign = base::StringPrintf("%s=%s",
- name_.c_str(),
- value_.c_str());
- service_->StartSigningAttempt(to_sign, this);
+ if (!service_->has_cached_policy()) {
+ TryToFetchPolicyAndCallBack();
+ return;
+ }
+ // Posts a task to the FILE thread to sign policy.
+ em::PolicyData to_sign;
+ to_sign.CheckTypeAndMergeFrom(service_->cached_policy());
+ SetInPolicy(name_, value_, &to_sign);
+ to_store_.set_policy_data(to_sign.SerializeAsString());
+ service_->StartSigningAttempt(to_store_.policy_data(), this);
+}
+
+void StorePropertyOp::Fail(SignedSettings::ReturnCode code) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &StorePropertyOp::PerformCallback, code, false));
+}
+
+void StorePropertyOp::Succeed(bool value) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &StorePropertyOp::PerformCallback,
+ SUCCESS, value));
}
void StorePropertyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
- const std::vector<uint8>& payload) {
+ const std::vector<uint8>& sig) {
// Ensure we're on the UI thread, due to the need to send DBus traffic.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableMethod(this,
&StorePropertyOp::OnKeyOpComplete,
- return_code, payload));
+ return_code, sig));
return;
}
VLOG(2) << "StorePropertyOp::OnKeyOpComplete return_code = " << return_code;
// Now, sure we're on the UI thread.
if (return_code == OwnerManager::SUCCESS) {
- // OnComplete() will be called by this call, if it succeeds.
- if (!CrosLibrary::Get()->GetLoginLibrary()->StorePropertyAsync(name_,
- value_,
- payload,
- this)) {
- d_->OnSettingsOpCompleted(OPERATION_FAILED, false);
- }
+ to_store_.set_policy_data_signature(
+ std::string(reinterpret_cast<const char*>(&sig[0]), sig.size()));
+ store_op_ = CreateStorePolicyOp(&to_store_, this);
+ // d_->OnSettingsOpCompleted() will be called by this call.
+ store_op_->Execute();
} else {
- d_->OnSettingsOpCompleted(SignedSettings::MapKeyOpCode(return_code), false);
+ Fail(SignedSettings::MapKeyOpCode(return_code));
}
}
-void StorePropertyOp::OnComplete(bool value) {
- if (value)
- d_->OnSettingsOpCompleted(SUCCESS, value);
- else
- d_->OnSettingsOpCompleted(NOT_FOUND, false);
+void StorePropertyOp::OnSettingsOpCompleted(ReturnCode code, bool value) {
+ if (value && to_store_.has_policy_data()) {
+ em::PolicyData poldata;
+ poldata.ParseFromString(to_store_.policy_data());
+ service_->set_cached_policy(poldata);
+ Succeed(value);
+ return;
+ }
+ Fail(NOT_FOUND);
+}
+
+void StorePropertyOp::SetInPolicy(const std::string& prop,
+ const std::string& value,
+ em::PolicyData* poldata) {
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(poldata->policy_value());
+ if (prop == kAccountsPrefAllowNewUser) {
+ em::AllowNewUsersProto* allow = pol.mutable_allow_new_users();
+ allow->set_allow_new_users(value == "true");
+
+ } else if (prop == kAccountsPrefAllowGuest) {
+ em::GuestModeEnabledProto* guest = pol.mutable_guest_mode_enabled();
+ guest->set_guest_mode_enabled(value == "true");
+
+ } else if (prop == kAccountsPrefShowUserNamesOnSignIn) {
+ em::ShowUserNamesOnSigninProto* show = pol.mutable_show_user_names();
+ show->set_show_user_names(value == "true");
+
+ } else if (prop == kSignedDataRoamingEnabled) {
+ em::DataRoamingEnabledProto* roam = pol.mutable_data_roaming_enabled();
+ roam->set_data_roaming_enabled(value == "true");
+
+ } else if (prop == kSettingProxyEverywhere) {
+ // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed.
+ // TODO(cmasone): Until then, we will have to parse serialized JSON
+ // representing proxy settings, as generated by
+ // ProxyConfigServiceImpl::Serialize(). The code needs to translate into a
+ // DeviceProxySettingsProto (defined in chrome_device_policy.proto).
+ } else {
+ NOTREACHED();
+ }
+ poldata->set_policy_value(pol.SerializeAsString());
+}
+
+void StorePropertyOp::PerformCallback(SignedSettings::ReturnCode code,
+ bool value) {
+ d_->OnSettingsOpCompleted(code, value);
}
+// static
+const char* RetrievePropertyOp::kVeritas[] = { "false", "true" };
+
RetrievePropertyOp::RetrievePropertyOp(const std::string& name,
SignedSettings::Delegate<std::string>* d)
: name_(name),
@@ -392,58 +665,93 @@ void RetrievePropertyOp::Execute() {
g_browser_process->local_state() &&
SignedSettingsTempStorage::Retrieve(
name_, &value_, g_browser_process->local_state())) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this,
- &RetrievePropertyOp::OnKeyOpComplete,
- OwnerManager::SUCCESS, std::vector<uint8>()));
+ Succeed(value_);
return;
}
}
- CrosLibrary::Get()->GetLoginLibrary()->RequestRetrieveProperty(name_,
- &RetrievePropertyOp::OnRetrievePropertyNotify, this);
-}
-
-// static
-void RetrievePropertyOp::OnRetrievePropertyNotify(void* user_data,
- bool success, const Property* property) {
- RetrievePropertyOp* self = static_cast<RetrievePropertyOp*>(user_data);
- if (!success) {
- self->d_->OnSettingsOpCompleted(NOT_FOUND, std::string());
+ if (!service_->has_cached_policy()) {
+ TryToFetchPolicyAndCallBack();
return;
}
+ std::string value = LookUpInPolicy(name_);
+ if (value.empty())
+ Fail(NOT_FOUND);
+ else
+ Succeed(value);
+}
- self->value_ = property->value;
-
- std::vector<uint8> sig;
- sig.assign(property->signature->data,
- property->signature->data + property->signature->length);
+void RetrievePropertyOp::Fail(SignedSettings::ReturnCode code) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &RetrievePropertyOp::PerformCallback,
+ code, std::string()));
+}
- std::string to_verify = base::StringPrintf("%s=%s",
- self->name_.c_str(),
- self->value_.c_str());
- // Posts a task to the FILE thread to verify |sig|.
- self->service_->StartVerifyAttempt(to_verify, sig, self);
+void RetrievePropertyOp::Succeed(const std::string& value) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &RetrievePropertyOp::PerformCallback, SUCCESS, value));
}
+// DEPRECATED.
void RetrievePropertyOp::OnKeyOpComplete(
const OwnerManager::KeyOpCode return_code,
- const std::vector<uint8>& payload) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this,
- &RetrievePropertyOp::OnKeyOpComplete,
- return_code, payload));
- return;
+ const std::vector<uint8>& sig) {
+ NOTREACHED();
+}
+
+std::string RetrievePropertyOp::LookUpInPolicy(const std::string& prop) {
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(service_->cached_policy().policy_value());
+ if (prop == kAccountsPrefAllowNewUser) {
+ if (pol.has_allow_new_users() &&
+ pol.allow_new_users().has_allow_new_users() &&
+ pol.allow_new_users().allow_new_users()) {
+ return kVeritas[1]; // New users allowed, user_whitelist() ignored.
+ }
+ // If we have the allow_new_users bool, and it is true, we honor that above.
+ // In all other cases (don't have it, have it and it is set to false, etc),
+ // We will honor the user_whitelist() if it is there and populated.
+ // Otherwise, fail open (to do otherwise could render the device unusable).
+ if (!pol.has_user_whitelist())
+ return kVeritas[1]; // Default to allowing new users.
+ return kVeritas[pol.user_whitelist().user_whitelist_size() == 0];
+
+ } else if (prop == kAccountsPrefAllowGuest) {
+ if (!pol.has_guest_mode_enabled() ||
+ !pol.guest_mode_enabled().has_guest_mode_enabled())
+ return kVeritas[1]; // Default to allowing guests;
+ return kVeritas[pol.guest_mode_enabled().guest_mode_enabled()];
+
+ } else if (prop == kAccountsPrefShowUserNamesOnSignIn) {
+ if (!pol.has_show_user_names() ||
+ !pol.show_user_names().has_show_user_names())
+ return kVeritas[1]; // Default to showing pods on the login screen;
+ return kVeritas[pol.show_user_names().show_user_names()];
+
+ } else if (prop == kSignedDataRoamingEnabled) {
+ if (!pol.has_data_roaming_enabled() ||
+ !pol.data_roaming_enabled().has_data_roaming_enabled())
+ return kVeritas[0]; // Default to disabling cellular data roaming;
+ return kVeritas[pol.data_roaming_enabled().data_roaming_enabled()];
+
+ } else if (prop == kSettingProxyEverywhere) {
+ // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed.
+ // TODO(cmasone): Until then, we will have to return serialized JSON
+ // representing proxy settings, to be consumed by
+ // ProxyConfigServiceImpl::Deserialize(). We need code to translate a
+ // DeviceProxySettingsProto (defined in chrome_device_policy.proto) into
+ // a serialzed JSON string of this form.
}
- // Now, sure we're on the UI thread.
- if (return_code == OwnerManager::SUCCESS)
- d_->OnSettingsOpCompleted(SUCCESS, value_);
- else
- d_->OnSettingsOpCompleted(SignedSettings::MapKeyOpCode(return_code),
- std::string());
+ return std::string();
+}
+
+void RetrievePropertyOp::PerformCallback(SignedSettings::ReturnCode code,
+ const std::string& value) {
+ d_->OnSettingsOpCompleted(code, value);
}
StorePolicyOp::StorePolicyOp(em::PolicyFetchResponse* policy,
@@ -454,16 +762,46 @@ StorePolicyOp::StorePolicyOp(em::PolicyFetchResponse* policy,
StorePolicyOp::~StorePolicyOp() {}
+// static
+void StorePolicyOp::OnBoolComplete(void* delegate, bool success) {
+ StorePolicyOp* op = static_cast<StorePolicyOp*>(delegate);
+ if (success)
+ op->Succeed(true);
+ else
+ op->Fail(NOT_FOUND);
+}
+
void StorePolicyOp::Execute() {
// get protobuf contents to sign
if (!policy_->has_policy_data())
- d_->OnSettingsOpCompleted(OPERATION_FAILED, false);
+ Fail(OPERATION_FAILED);
if (!policy_->has_policy_data_signature())
service_->StartSigningAttempt(policy_->policy_data(), this);
else
RequestStorePolicy();
}
+void StorePolicyOp::Fail(SignedSettings::ReturnCode code) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &StorePolicyOp::PerformCallback, code, false));
+}
+
+void StorePolicyOp::Succeed(bool ignored) {
+ SignedSettings::ReturnCode code = SUCCESS;
+ bool to_ret = true;
+ em::PolicyData poldata;
+ if (SignedSettings::PolicyIsSane(*policy_, &poldata)) {
+ service_->set_cached_policy(poldata);
+ } else {
+ code = NOT_FOUND;
+ to_ret = false;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &StorePolicyOp::PerformCallback, code, to_ret));
+}
+
void StorePolicyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload) {
// Ensure we're on the UI thread, due to the need to send DBus traffic.
@@ -483,7 +821,7 @@ void StorePolicyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
RequestStorePolicy();
return;
}
- d_->OnSettingsOpCompleted(SignedSettings::MapKeyOpCode(return_code), false);
+ Fail(SignedSettings::MapKeyOpCode(return_code));
}
void StorePolicyOp::RequestStorePolicy() {
@@ -491,13 +829,18 @@ void StorePolicyOp::RequestStorePolicy() {
if (policy_->SerializeToString(&serialized)) {
CrosLibrary::Get()->GetLoginLibrary()->RequestStorePolicy(
serialized,
- &SignedSettings::OnBoolComplete,
- d_);
+ &StorePolicyOp::OnBoolComplete,
+ this);
} else {
- d_->OnSettingsOpCompleted(OPERATION_FAILED, false);
+ Fail(OPERATION_FAILED);
}
}
+void StorePolicyOp::PerformCallback(SignedSettings::ReturnCode code,
+ bool value) {
+ d_->OnSettingsOpCompleted(code, value);
+}
+
RetrievePolicyOp::RetrievePolicyOp(
SignedSettings::Delegate<const em::PolicyFetchResponse&>* d)
: d_(d) {
@@ -510,6 +853,28 @@ void RetrievePolicyOp::Execute() {
&RetrievePolicyOp::OnStringComplete, this);
}
+void RetrievePolicyOp::Fail(SignedSettings::ReturnCode code) {
+ VLOG(2) << "RetrievePolicyOp::Execute() failed with " << code;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &RetrievePolicyOp::PerformCallback, code,
+ em::PolicyFetchResponse()));
+}
+
+void RetrievePolicyOp::Succeed(const em::PolicyFetchResponse& value) {
+ em::PolicyData poldata;
+ if (SignedSettings::PolicyIsSane(value, &poldata)) {
+ service_->set_cached_policy(poldata);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &RetrievePolicyOp::PerformCallback,
+ SUCCESS, value));
+ } else {
+ Fail(NOT_FOUND);
+ }
+}
+
void RetrievePolicyOp::OnKeyOpComplete(
const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload) {
@@ -523,10 +888,9 @@ void RetrievePolicyOp::OnKeyOpComplete(
}
// Now, sure we're on the UI thread.
if (return_code == OwnerManager::SUCCESS)
- d_->OnSettingsOpCompleted(SUCCESS, policy_);
+ Succeed(policy_);
else
- d_->OnSettingsOpCompleted(SignedSettings::MapKeyOpCode(return_code),
- em::PolicyFetchResponse());
+ Fail(SignedSettings::MapKeyOpCode(return_code));
}
// static
@@ -540,15 +904,15 @@ void RetrievePolicyOp::OnStringComplete(void* delegate,
void RetrievePolicyOp::ProcessPolicy(const char* out, const unsigned int len) {
if (!out || !policy_.ParseFromString(std::string(out, len)) ||
(!policy_.has_policy_data() && !policy_.has_policy_data_signature())) {
- d_->OnSettingsOpCompleted(NOT_FOUND, policy_);
+ Fail(NOT_FOUND);
return;
}
if (!policy_.has_policy_data()) {
- d_->OnSettingsOpCompleted(OPERATION_FAILED, em::PolicyFetchResponse());
+ Fail(OPERATION_FAILED);
return;
}
if (!policy_.has_policy_data_signature()) {
- d_->OnSettingsOpCompleted(BAD_SIGNATURE, em::PolicyFetchResponse());
+ Fail(BAD_SIGNATURE);
return;
}
std::vector<uint8> sig;
@@ -557,4 +921,9 @@ void RetrievePolicyOp::ProcessPolicy(const char* out, const unsigned int len) {
service_->StartVerifyAttempt(policy_.policy_data(), sig, this);
}
+void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& value) {
+ d_->OnSettingsOpCompleted(code, value);
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/signed_settings.h b/chrome/browser/chromeos/login/signed_settings.h
index 1a374d2..8cef17b 100644
--- a/chrome/browser/chromeos/login/signed_settings.h
+++ b/chrome/browser/chromeos/login/signed_settings.h
@@ -32,6 +32,7 @@
namespace enterprise_management {
class PolicyFetchResponse;
+class PolicyData;
} // namespace enterprise_management
namespace em = enterprise_management;
@@ -89,16 +90,25 @@ class SignedSettings : public base::RefCountedThreadSafe<SignedSettings>,
static SignedSettings* CreateRetrievePolicyOp(
SignedSettings::Delegate<const em::PolicyFetchResponse&>* d);
+ static bool EnumerateWhitelist(std::vector<std::string>* whitelisted);
+
static ReturnCode MapKeyOpCode(OwnerManager::KeyOpCode code);
virtual void Execute() = 0;
- // Implementation of OwnerManager::Delegate::OnKeyOpComplete()
+ virtual void Fail(ReturnCode code) = 0;
+
+ // Implementation of OwnerManager::Delegate
void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,
const std::vector<uint8>& payload) = 0;
protected:
- static void OnBoolComplete(void* delegate, bool success);
+ static bool PolicyIsSane(const em::PolicyFetchResponse& value,
+ em::PolicyData* poldata);
+
+ void set_service(OwnershipService* service) { service_ = service; }
+
+ void TryToFetchPolicyAndCallBack();
OwnershipService* service_;
@@ -106,7 +116,26 @@ class SignedSettings : public base::RefCountedThreadSafe<SignedSettings>,
friend class SignedSettingsTest;
friend class SignedSettingsHelperTest;
- void set_service(OwnershipService* service) { service_ = service; }
+ class Relay
+ : public SignedSettings::Delegate<const em::PolicyFetchResponse&> {
+ public:
+ // |s| must outlive your Relay instance.
+ explicit Relay(SignedSettings* s);
+ virtual ~Relay();
+ // Implementation of SignedSettings::Delegate
+ virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
+ const em::PolicyFetchResponse& value);
+ private:
+ SignedSettings* settings_;
+ DISALLOW_COPY_AND_ASSIGN(Relay);
+ };
+
+ // Format of this string is documented in device_management_backend.proto.
+ static const char kDevicePolicyType[];
+
+ scoped_ptr<Relay> relay_;
+ scoped_refptr<SignedSettings> polfetcher_;
+ DISALLOW_COPY_AND_ASSIGN(SignedSettings);
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/signed_settings_helper_unittest.cc b/chrome/browser/chromeos/login/signed_settings_helper_unittest.cc
index 7badf48..f0db486 100644
--- a/chrome/browser/chromeos/login/signed_settings_helper_unittest.cc
+++ b/chrome/browser/chromeos/login/signed_settings_helper_unittest.cc
@@ -1,21 +1,31 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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/chromeos/login/signed_settings_helper.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
#include "chrome/browser/chromeos/login/mock_ownership_service.h"
#include "chrome/browser/chromeos/login/owner_manager.h"
#include "chrome/browser/chromeos/login/signed_settings.h"
+#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "content/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
+using ::testing::A;
+using ::testing::AtLeast;
using ::testing::InSequence;
+using ::testing::Invoke;
using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::SaveArg;
+using ::testing::WithArg;
+namespace em = enterprise_management;
namespace chromeos {
class MockSignedSettingsHelperCallback : public SignedSettingsHelper::Callback {
@@ -41,8 +51,8 @@ class SignedSettingsHelperTest : public ::testing::Test,
public:
SignedSettingsHelperTest()
: fake_email_("fakey@example.com"),
- fake_prop_("prop_name"),
- fake_value_("stub"),
+ fake_prop_(kAccountsPrefAllowGuest),
+ fake_value_("false"),
message_loop_(MessageLoop::TYPE_UI),
ui_thread_(BrowserThread::UI, &message_loop_),
file_thread_(BrowserThread::FILE),
@@ -64,7 +74,6 @@ class SignedSettingsHelperTest : public ::testing::Test,
}
virtual void OnOpStarted(SignedSettings* op) {
- op->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
}
virtual void OnOpCompleted(SignedSettings* op) {
@@ -73,6 +82,18 @@ class SignedSettingsHelperTest : public ::testing::Test,
MessageLoop::current()->Quit();
}
+ static void OnKeyOpComplete(OwnerManager::Delegate* op) {
+ op->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ }
+
+ em::PolicyData BuildPolicyData() {
+ em::PolicyData to_return;
+ em::ChromeDeviceSettingsProto pol;
+ to_return.set_policy_type(SignedSettings::kDevicePolicyType);
+ to_return.set_policy_value(pol.SerializeAsString());
+ return to_return;
+ }
+
const std::string fake_email_;
const std::string fake_prop_;
const std::string fake_value_;
@@ -90,29 +111,45 @@ class SignedSettingsHelperTest : public ::testing::Test,
TEST_F(SignedSettingsHelperTest, SerializedOps) {
MockSignedSettingsHelperCallback cb;
- ON_CALL(m_, GetStatus(_))
- .WillByDefault(Return(OwnershipService::OWNERSHIP_TAKEN));
- EXPECT_CALL(m_, GetStatus(_)).Times(2);
+ EXPECT_CALL(m_, GetStatus(_))
+ .Times(2)
+ .WillRepeatedly(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .Times(5)
+ .WillRepeatedly(Return(true));
+ em::PolicyData fake_pol = BuildPolicyData();
+ EXPECT_CALL(m_, cached_policy())
+ .Times(5)
+ .WillRepeatedly(ReturnRef(fake_pol));
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .Times(3)
+ .WillRepeatedly(SaveArg<0>(&fake_pol));
+
InSequence s;
- EXPECT_CALL(m_, StartVerifyAttempt(_, _, _)).Times(1);
- EXPECT_CALL(cb, OnCheckWhitelistCompleted(SignedSettings::SUCCESS, _))
- .Times(1);
- EXPECT_CALL(m_, StartSigningAttempt(_, _)).Times(1);
+ EXPECT_CALL(m_, StartSigningAttempt(_, A<OwnerManager::Delegate*>()))
+ .WillOnce(WithArg<1>(Invoke(&SignedSettingsHelperTest::OnKeyOpComplete)));
EXPECT_CALL(cb, OnWhitelistCompleted(SignedSettings::SUCCESS, _))
.Times(1);
- EXPECT_CALL(m_, StartSigningAttempt(_, _)).Times(1);
+
+ EXPECT_CALL(cb, OnCheckWhitelistCompleted(SignedSettings::SUCCESS, _))
+ .Times(1);
+
+ EXPECT_CALL(m_, StartSigningAttempt(_, A<OwnerManager::Delegate*>()))
+ .WillOnce(WithArg<1>(Invoke(&SignedSettingsHelperTest::OnKeyOpComplete)));
EXPECT_CALL(cb, OnUnwhitelistCompleted(SignedSettings::SUCCESS, _))
.Times(1);
- EXPECT_CALL(m_, StartSigningAttempt(_, _)).Times(1);
+
+ EXPECT_CALL(m_, StartSigningAttempt(_, A<OwnerManager::Delegate*>()))
+ .WillOnce(WithArg<1>(Invoke(&SignedSettingsHelperTest::OnKeyOpComplete)));
EXPECT_CALL(cb, OnStorePropertyCompleted(SignedSettings::SUCCESS, _, _))
.Times(1);
- EXPECT_CALL(m_, StartVerifyAttempt(_, _, _)).Times(1);
+
EXPECT_CALL(cb, OnRetrievePropertyCompleted(SignedSettings::SUCCESS, _, _))
.Times(1);
pending_ops_ = 5;
- SignedSettingsHelper::Get()->StartCheckWhitelistOp(fake_email_, &cb);
SignedSettingsHelper::Get()->StartWhitelistOp(fake_email_, true, &cb);
+ SignedSettingsHelper::Get()->StartCheckWhitelistOp(fake_email_, &cb);
SignedSettingsHelper::Get()->StartWhitelistOp(fake_email_, false, &cb);
SignedSettingsHelper::Get()->StartStorePropertyOp(fake_prop_, fake_value_,
&cb);
@@ -124,34 +161,49 @@ TEST_F(SignedSettingsHelperTest, SerializedOps) {
TEST_F(SignedSettingsHelperTest, CanceledOps) {
MockSignedSettingsHelperCallback cb;
- ON_CALL(m_, GetStatus(_))
- .WillByDefault(Return(OwnershipService::OWNERSHIP_TAKEN));
- EXPECT_CALL(m_, GetStatus(_)).Times(2);
+ EXPECT_CALL(m_, GetStatus(_))
+ .Times(2)
+ .WillRepeatedly(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .Times(6)
+ .WillRepeatedly(Return(true));
+ em::PolicyData fake_pol = BuildPolicyData();
+ EXPECT_CALL(m_, cached_policy())
+ .Times(7)
+ .WillRepeatedly(ReturnRef(fake_pol));
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .Times(3)
+ .WillRepeatedly(SaveArg<0>(&fake_pol));
+
InSequence s;
- EXPECT_CALL(m_, StartVerifyAttempt(_, _, _)).Times(1);
- EXPECT_CALL(cb, OnCheckWhitelistCompleted(SignedSettings::SUCCESS, _))
- .Times(1);
- EXPECT_CALL(m_, StartSigningAttempt(_, _)).Times(1);
+
+ EXPECT_CALL(m_, StartSigningAttempt(_, A<OwnerManager::Delegate*>()))
+ .WillOnce(WithArg<1>(Invoke(&SignedSettingsHelperTest::OnKeyOpComplete)));
EXPECT_CALL(cb, OnWhitelistCompleted(SignedSettings::SUCCESS, _))
.Times(1);
- EXPECT_CALL(m_, StartSigningAttempt(_, _)).Times(1);
+
+ EXPECT_CALL(cb, OnCheckWhitelistCompleted(SignedSettings::SUCCESS, _))
+ .Times(1);
+
+ EXPECT_CALL(m_, StartSigningAttempt(_, A<OwnerManager::Delegate*>()))
+ .WillOnce(WithArg<1>(Invoke(&SignedSettingsHelperTest::OnKeyOpComplete)));
EXPECT_CALL(cb, OnUnwhitelistCompleted(SignedSettings::SUCCESS, _))
.Times(1);
// CheckWhitelistOp for cb_to_be_canceled still gets executed but callback
// does not happen.
- EXPECT_CALL(m_, StartVerifyAttempt(_, _, _)).Times(1);
- EXPECT_CALL(m_, StartSigningAttempt(_, _)).Times(1);
+ EXPECT_CALL(m_, StartSigningAttempt(_, A<OwnerManager::Delegate*>()))
+ .WillOnce(WithArg<1>(Invoke(&SignedSettingsHelperTest::OnKeyOpComplete)));
EXPECT_CALL(cb, OnStorePropertyCompleted(SignedSettings::SUCCESS, _, _))
.Times(1);
- EXPECT_CALL(m_, StartVerifyAttempt(_, _, _)).Times(1);
+
EXPECT_CALL(cb, OnRetrievePropertyCompleted(SignedSettings::SUCCESS, _, _))
.Times(1);
pending_ops_ = 6;
- SignedSettingsHelper::Get()->StartCheckWhitelistOp(fake_email_, &cb);
SignedSettingsHelper::Get()->StartWhitelistOp(fake_email_, true, &cb);
+ SignedSettingsHelper::Get()->StartCheckWhitelistOp(fake_email_, &cb);
SignedSettingsHelper::Get()->StartWhitelistOp(fake_email_, false, &cb);
MockSignedSettingsHelperCallback cb_to_be_canceled;
diff --git a/chrome/browser/chromeos/login/signed_settings_unittest.cc b/chrome/browser/chromeos/login/signed_settings_unittest.cc
index 80f6815..cbe0a10 100644
--- a/chrome/browser/chromeos/login/signed_settings_unittest.cc
+++ b/chrome/browser/chromeos/login/signed_settings_unittest.cc
@@ -11,9 +11,11 @@
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/mock_library_loader.h"
#include "chrome/browser/chromeos/cros/mock_login_library.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
#include "chrome/browser/chromeos/login/mock_owner_key_utils.h"
#include "chrome/browser/chromeos/login/mock_ownership_service.h"
#include "chrome/browser/chromeos/login/owner_manager_unittest.h"
+#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/test/thread_test_helper.h"
#include "content/browser/browser_thread.h"
@@ -21,11 +23,16 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::A;
using ::testing::AnyNumber;
using ::testing::InvokeArgument;
using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::SaveArg;
using ::testing::StrEq;
+using ::testing::WithArg;
using ::testing::_;
+using google::protobuf::RepeatedPtrField;
namespace em = enterprise_management;
namespace chromeos {
@@ -97,8 +104,8 @@ class SignedSettingsTest : public ::testing::Test {
SignedSettingsTest()
: fake_email_("fakey@example.com"),
fake_domain_("*@example.com"),
- fake_prop_("prop_name"),
- fake_value_("stub"),
+ fake_prop_(kAccountsPrefAllowGuest),
+ fake_value_("false"),
message_loop_(MessageLoop::TYPE_UI),
ui_thread_(BrowserThread::UI, &message_loop_),
file_thread_(BrowserThread::FILE),
@@ -120,32 +127,65 @@ class SignedSettingsTest : public ::testing::Test {
s->set_service(m);
}
- void FailingCheckWhitelist(const OwnerManager::KeyOpCode return_code) {
- NormalDelegate<bool> d(false);
- scoped_refptr<SignedSettings> s(
- SignedSettings::CreateCheckWhitelistOp(fake_email_, &d));
- d.expect_failure(SignedSettings::MapKeyOpCode(return_code));
-
- mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartVerifyAttempt(fake_email_, _, _))
- .Times(1);
+ em::PolicyData BuildPolicyData(std::vector<std::string> whitelist) {
+ em::PolicyData to_return;
+ em::ChromeDeviceSettingsProto pol;
+ em::GuestModeEnabledProto* allow = pol.mutable_guest_mode_enabled();
+ allow->set_guest_mode_enabled(false);
+
+ if (!whitelist.empty()) {
+ em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist();
+ for (std::vector<std::string>::const_iterator it = whitelist.begin();
+ it != whitelist.end();
+ ++it) {
+ whitelist_proto->add_user_whitelist(*it);
+ }
+ }
+
+ to_return.set_policy_type(SignedSettings::kDevicePolicyType);
+ to_return.set_policy_value(pol.SerializeAsString());
+ return to_return;
+ }
- s->Execute();
- s->OnKeyOpComplete(return_code, std::vector<uint8>());
+ void SetAllowNewUsers(bool desired, em::PolicyData* poldata) {
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(poldata->policy_value());
+ em::AllowNewUsersProto* allow = pol.mutable_allow_new_users();
+ allow->set_allow_new_users(desired);
+ poldata->set_policy_value(pol.SerializeAsString());
}
- void FailingWhitelistOp(const OwnerManager::KeyOpCode return_code) {
- NormalDelegate<bool> d(false);
- scoped_refptr<SignedSettings> s(
- SignedSettings::CreateWhitelistOp(fake_email_, true, &d));
- d.expect_failure(SignedSettings::MapKeyOpCode(return_code));
+ bool CheckWhitelist(const std::string& email, const em::PolicyData& poldata) {
+ if (!poldata.has_policy_value())
+ return false;
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(poldata.policy_value());
+ if (!pol.has_user_whitelist())
+ return false;
+
+ const RepeatedPtrField<std::string>& whitelist =
+ pol.user_whitelist().user_whitelist();
+ for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
+ it != whitelist.end();
+ ++it) {
+ if (email == *it)
+ return true;
+ }
+ return false;
+ }
- mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartSigningAttempt(fake_email_, _))
+ void ExpectWhitelistOp(SignedSettings* s,
+ em::PolicyData* fake_pol,
+ em::PolicyData* out_pol) {
+ mock_service(s, &m_);
+ EXPECT_CALL(m_, StartSigningAttempt(_, _))
.Times(1);
-
- s->Execute();
- s->OnKeyOpComplete(return_code, std::vector<uint8>());
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(*fake_pol));
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .WillOnce(SaveArg<0>(out_pol));
}
void FailingStorePropertyOp(const OwnerManager::KeyOpCode return_code) {
@@ -153,35 +193,21 @@ class SignedSettingsTest : public ::testing::Test {
scoped_refptr<SignedSettings> s(
SignedSettings::CreateStorePropertyOp(fake_prop_, fake_value_, &d));
d.expect_failure(SignedSettings::MapKeyOpCode(return_code));
- std::string to_sign = base::StringPrintf("%s=%s",
- fake_prop_.c_str(),
- fake_value_.c_str());
- mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartSigningAttempt(to_sign, _))
- .Times(1);
- EXPECT_CALL(m_, GetStatus(_))
- .WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN));
- s->Execute();
- s->OnKeyOpComplete(return_code, std::vector<uint8>());
- }
-
- void FailingRetrievePropertyOp(const OwnerManager::KeyOpCode return_code) {
- NormalDelegate<std::string> d(fake_value_);
- scoped_refptr<SignedSettings> s(
- SignedSettings::CreateRetrievePropertyOp(fake_prop_, &d));
- d.expect_failure(SignedSettings::MapKeyOpCode(return_code));
- std::string to_verify = base::StringPrintf("%s=%s",
- fake_prop_.c_str(),
- fake_value_.c_str());
mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartVerifyAttempt(to_verify, _, _))
+ EXPECT_CALL(m_, StartSigningAttempt(_, _))
.Times(1);
EXPECT_CALL(m_, GetStatus(_))
.WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+ em::PolicyData fake_pol;
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(fake_pol));
s->Execute();
s->OnKeyOpComplete(return_code, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
void FailingStorePolicyOp(const OwnerManager::KeyOpCode return_code) {
@@ -202,6 +228,7 @@ class SignedSettingsTest : public ::testing::Test {
s->Execute();
s->OnKeyOpComplete(return_code, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
MockLoginLibrary* MockLoginLib() {
@@ -245,6 +272,26 @@ class SignedSettingsTest : public ::testing::Test {
return fake_policy;
}
+ void DoRetrieveProperty(const std::string& name,
+ const std::string& value,
+ em::PolicyData* fake_pol) {
+ NormalDelegate<std::string> d(value);
+ d.expect_success();
+ scoped_refptr<SignedSettings> s(
+ SignedSettings::CreateRetrievePropertyOp(name, &d));
+ mock_service(s.get(), &m_);
+ EXPECT_CALL(m_, GetStatus(_))
+ .WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(*fake_pol));
+
+ s->Execute();
+ message_loop_.RunAllPending();
+ }
+
const std::string fake_email_;
const std::string fake_domain_;
const std::string fake_prop_;
@@ -274,25 +321,38 @@ TEST_F(SignedSettingsTest, CheckWhitelist) {
SignedSettings::CreateCheckWhitelistOp(fake_email_, &d));
mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartVerifyAttempt(fake_email_, _, _))
- .Times(1);
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+
+ std::vector<std::string> whitelist(1, fake_email_);
+ whitelist.push_back(fake_email_ + "m");
+ em::PolicyData fake_pol = BuildPolicyData(whitelist);
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(fake_pol));
s->Execute();
- s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
TEST_F(SignedSettingsTest, CheckWhitelistWildcards) {
NormalDelegate<bool> d(true);
d.expect_success();
scoped_refptr<SignedSettings> s(
- SignedSettings::CreateCheckWhitelistOp(fake_domain_, &d));
+ SignedSettings::CreateCheckWhitelistOp(fake_email_, &d));
mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartVerifyAttempt(fake_domain_, _, _))
- .Times(1);
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+
+ std::vector<std::string> whitelist(1, fake_domain_);
+ whitelist.push_back(fake_email_ + "m");
+ em::PolicyData fake_pol = BuildPolicyData(whitelist);
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(fake_pol))
+ .WillOnce(ReturnRef(fake_pol));
s->Execute();
- s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
TEST_F(SignedSettingsTest, CheckWhitelistNotFound) {
@@ -300,23 +360,19 @@ TEST_F(SignedSettingsTest, CheckWhitelistNotFound) {
scoped_refptr<SignedSettings> s(
SignedSettings::CreateCheckWhitelistOp(fake_email_, &d));
d.expect_failure(SignedSettings::NOT_FOUND);
- MockLoginLibrary* lib = MockLoginLib();
- EXPECT_CALL(*lib, CheckWhitelist(fake_email_, _))
- .WillOnce(Return(false))
- .RetiresOnSaturation();
- EXPECT_CALL(*lib, CheckWhitelist(fake_domain_, _))
- .WillOnce(Return(false))
- .RetiresOnSaturation();
- s->Execute();
- UnMockLoginLib();
-}
-TEST_F(SignedSettingsTest, CheckWhitelistNoKey) {
- FailingCheckWhitelist(OwnerManager::KEY_UNAVAILABLE);
-}
+ mock_service(s.get(), &m_);
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+
+ std::vector<std::string> whitelist(1, fake_email_ + "m");
+ em::PolicyData fake_pol = BuildPolicyData(whitelist);
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(fake_pol))
+ .WillOnce(ReturnRef(fake_pol));
-TEST_F(SignedSettingsTest, CheckWhitelistFailed) {
- FailingCheckWhitelist(OwnerManager::OPERATION_FAILED);
+ s->Execute();
+ message_loop_.RunAllPending();
}
TEST_F(SignedSettingsTest, Whitelist) {
@@ -324,14 +380,32 @@ TEST_F(SignedSettingsTest, Whitelist) {
d.expect_success();
scoped_refptr<SignedSettings> s(
SignedSettings::CreateWhitelistOp(fake_email_, true, &d));
+ em::PolicyData in_pol = BuildPolicyData(std::vector<std::string>());
+ em::PolicyData out_pol;
+ ExpectWhitelistOp(s.get(), &in_pol, &out_pol);
- mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartSigningAttempt(fake_email_, _))
- .Times(1);
+ s->Execute();
+ s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ message_loop_.RunAllPending();
+
+ ASSERT_TRUE(CheckWhitelist(fake_email_, out_pol));
+}
+
+TEST_F(SignedSettingsTest, AddToExistingWhitelist) {
+ NormalDelegate<bool> d(true);
+ d.expect_success();
+ scoped_refptr<SignedSettings> s(
+ SignedSettings::CreateWhitelistOp(fake_email_, true, &d));
+ em::PolicyData in_pol =
+ BuildPolicyData(std::vector<std::string>(1, fake_domain_));
+ em::PolicyData out_pol;
+ ExpectWhitelistOp(s.get(), &in_pol, &out_pol);
s->Execute();
s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
message_loop_.RunAllPending();
+
+ ASSERT_TRUE(CheckWhitelist(fake_email_, out_pol));
}
TEST_F(SignedSettingsTest, Unwhitelist) {
@@ -339,22 +413,35 @@ TEST_F(SignedSettingsTest, Unwhitelist) {
d.expect_success();
scoped_refptr<SignedSettings> s(
SignedSettings::CreateWhitelistOp(fake_email_, false, &d));
-
- mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartSigningAttempt(fake_email_, _))
- .Times(1);
+ em::PolicyData in_pol =
+ BuildPolicyData(std::vector<std::string>(1, fake_email_));
+ em::PolicyData out_pol;
+ ExpectWhitelistOp(s.get(), &in_pol, &out_pol);
s->Execute();
s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
message_loop_.RunAllPending();
-}
-TEST_F(SignedSettingsTest, WhitelistNoKey) {
- FailingWhitelistOp(OwnerManager::KEY_UNAVAILABLE);
+ ASSERT_FALSE(CheckWhitelist(fake_email_, out_pol));
}
-TEST_F(SignedSettingsTest, WhitelistFailed) {
- FailingWhitelistOp(OwnerManager::OPERATION_FAILED);
+TEST_F(SignedSettingsTest, RemoveFromExistingWhitelist) {
+ NormalDelegate<bool> d(true);
+ d.expect_success();
+ scoped_refptr<SignedSettings> s(
+ SignedSettings::CreateWhitelistOp(fake_email_, false, &d));
+ std::vector<std::string> whitelist(1, fake_domain_);
+ whitelist.push_back(fake_email_);
+ whitelist.push_back(fake_email_ + "m");
+ em::PolicyData in_pol = BuildPolicyData(whitelist);
+ em::PolicyData out_pol;
+ ExpectWhitelistOp(s.get(), &in_pol, &out_pol);
+
+ s->Execute();
+ s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ message_loop_.RunAllPending();
+
+ ASSERT_FALSE(CheckWhitelist(fake_email_, out_pol));
}
TEST_F(SignedSettingsTest, StoreProperty) {
@@ -362,18 +449,32 @@ TEST_F(SignedSettingsTest, StoreProperty) {
d.expect_success();
scoped_refptr<SignedSettings> s(
SignedSettings::CreateStorePropertyOp(fake_prop_, fake_value_, &d));
- std::string to_sign = base::StringPrintf("%s=%s",
- fake_prop_.c_str(),
- fake_value_.c_str());
+
mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartSigningAttempt(to_sign, _))
+ EXPECT_CALL(m_, StartSigningAttempt(_, _))
.Times(1);
EXPECT_CALL(m_, GetStatus(_))
.WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+ em::PolicyData in_pol =
+ BuildPolicyData(std::vector<std::string>(1, fake_email_));
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(in_pol));
+ em::PolicyData out_pol;
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .WillOnce(SaveArg<0>(&out_pol));
s->Execute();
s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
message_loop_.RunAllPending();
+
+ ASSERT_TRUE(out_pol.has_policy_value());
+ em::ChromeDeviceSettingsProto pol;
+ pol.ParseFromString(out_pol.policy_value());
+ ASSERT_TRUE(pol.has_guest_mode_enabled());
+ ASSERT_TRUE(pol.guest_mode_enabled().has_guest_mode_enabled());
+ ASSERT_FALSE(pol.guest_mode_enabled().guest_mode_enabled());
}
TEST_F(SignedSettingsTest, StorePropertyNoKey) {
@@ -385,61 +486,118 @@ TEST_F(SignedSettingsTest, StorePropertyFailed) {
}
TEST_F(SignedSettingsTest, RetrieveProperty) {
+ em::PolicyData fake_pol = BuildPolicyData(std::vector<std::string>());
+ DoRetrieveProperty(fake_prop_, fake_value_, &fake_pol);
+}
+
+TEST_F(SignedSettingsTest, ExplicitlyAllowNewUsers) {
+ em::PolicyData fake_pol = BuildPolicyData(std::vector<std::string>());
+ SetAllowNewUsers(true, &fake_pol);
+ DoRetrieveProperty(kAccountsPrefAllowNewUser, "true", &fake_pol);
+}
+
+TEST_F(SignedSettingsTest, ExplicitlyDisallowNewUsers) {
+ std::vector<std::string> whitelist(1, fake_email_ + "m");
+ em::PolicyData fake_pol = BuildPolicyData(whitelist);
+ SetAllowNewUsers(false, &fake_pol);
+ DoRetrieveProperty(kAccountsPrefAllowNewUser, "false", &fake_pol);
+}
+
+TEST_F(SignedSettingsTest, ImplicitlyDisallowNewUsers) {
+ std::vector<std::string> whitelist(1, fake_email_ + "m");
+ em::PolicyData fake_pol = BuildPolicyData(whitelist);
+ DoRetrieveProperty(kAccountsPrefAllowNewUser, "false", &fake_pol);
+}
+
+TEST_F(SignedSettingsTest, AccidentallyDisallowNewUsers) {
+ em::PolicyData fake_pol = BuildPolicyData(std::vector<std::string>());
+ SetAllowNewUsers(false, &fake_pol);
+ DoRetrieveProperty(kAccountsPrefAllowNewUser, "true", &fake_pol);
+}
+
+TEST_F(SignedSettingsTest, RetrievePropertyNotFound) {
NormalDelegate<std::string> d(fake_value_);
- d.expect_success();
+ d.expect_failure(SignedSettings::NOT_FOUND);
scoped_refptr<SignedSettings> s(
- SignedSettings::CreateRetrievePropertyOp(fake_prop_, &d));
- std::string to_verify = base::StringPrintf("%s=%s",
- fake_prop_.c_str(),
- fake_value_.c_str());
+ SignedSettings::CreateRetrievePropertyOp("unknown_prop", &d));
mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartVerifyAttempt(to_verify, _, _))
- .Times(1);
EXPECT_CALL(m_, GetStatus(_))
.WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(true));
+
+ em::PolicyData fake_pol = BuildPolicyData(std::vector<std::string>());
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(fake_pol));
s->Execute();
- s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
-TEST_F(SignedSettingsTest, RetrievePropertyNotFound) {
+ACTION_P(Retrieve, s) { (*arg0)((void*)arg1, s.c_str(), s.length()); }
+ACTION_P(FinishKeyOp, s) { arg2->OnKeyOpComplete(OwnerManager::SUCCESS, s); }
+
+TEST_F(SignedSettingsTest, RetrievePolicyToRetrieveProperty) {
NormalDelegate<std::string> d(fake_value_);
+ d.expect_success();
scoped_refptr<SignedSettings> s(
SignedSettings::CreateRetrievePropertyOp(fake_prop_, &d));
- d.expect_failure(SignedSettings::NOT_FOUND);
+
+ em::PolicyData fake_pol = BuildPolicyData(std::vector<std::string>());
+ std::string data = fake_pol.SerializeAsString();
+ std::string signed_serialized;
+ em::PolicyFetchResponse signed_policy = BuildProto(data,
+ fake_value_,
+ &signed_serialized);
MockLoginLibrary* lib = MockLoginLib();
- EXPECT_CALL(*lib, RequestRetrieveProperty(fake_prop_, _, _))
- .WillOnce(
- InvokeArgument<1>(static_cast<void*>(s.get()),
- false,
- static_cast<chromeos::Property*>(NULL)))
+ EXPECT_CALL(*lib, RequestRetrievePolicy(_, _))
+ .WillOnce(Retrieve(signed_serialized))
.RetiresOnSaturation();
- s->Execute();
- UnMockLoginLib();
-}
-TEST_F(SignedSettingsTest, RetrievePropertyNoKey) {
- FailingRetrievePropertyOp(OwnerManager::KEY_UNAVAILABLE);
-}
+ mock_service(s.get(), &m_);
-TEST_F(SignedSettingsTest, RetrievePropertyFailed) {
- FailingRetrievePropertyOp(OwnerManager::OPERATION_FAILED);
+ EXPECT_CALL(m_, GetStatus(_))
+ .WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN))
+ .WillOnce(Return(OwnershipService::OWNERSHIP_TAKEN));
+ EXPECT_CALL(m_, has_cached_policy())
+ .WillOnce(Return(false))
+ .WillOnce(Return(true));
+ em::PolicyData out_pol;
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .WillOnce(SaveArg<0>(&out_pol));
+ EXPECT_CALL(m_, cached_policy())
+ .WillOnce(ReturnRef(out_pol));
+
+ std::vector<uint8> fake_sig(fake_value_.c_str(),
+ fake_value_.c_str() + fake_value_.length());
+ EXPECT_CALL(m_, StartVerifyAttempt(data, fake_sig, _))
+ .WillOnce(FinishKeyOp(fake_sig))
+ .RetiresOnSaturation();
+
+ s->Execute();
+ message_loop_.RunAllPending();
+ UnMockLoginLib();
}
TEST_F(SignedSettingsTest, SignAndStorePolicy) {
NormalDelegate<bool> d(true);
d.expect_success();
+ em::PolicyData in_pol = BuildPolicyData(std::vector<std::string>());
+ std::string data_serialized = in_pol.SerializeAsString();
std::string serialized;
- em::PolicyFetchResponse fake_policy = BuildProto(fake_prop_,
+ em::PolicyFetchResponse fake_policy = BuildProto(data_serialized,
std::string(),
&serialized);
scoped_refptr<SignedSettings> s(
SignedSettings::CreateStorePolicyOp(&fake_policy, &d));
mock_service(s.get(), &m_);
- EXPECT_CALL(m_, StartSigningAttempt(StrEq(fake_prop_), _))
+ EXPECT_CALL(m_, StartSigningAttempt(StrEq(data_serialized), _))
.Times(1);
+ em::PolicyData out_pol;
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .WillOnce(SaveArg<0>(&out_pol));
// Ask for signature over unsigned policy.
s->Execute();
@@ -447,17 +605,18 @@ TEST_F(SignedSettingsTest, SignAndStorePolicy) {
// Fake out a successful signing.
std::string signed_serialized;
- em::PolicyFetchResponse signed_policy = BuildProto(fake_prop_,
+ em::PolicyFetchResponse signed_policy = BuildProto(data_serialized,
fake_value_,
&signed_serialized);
std::vector<uint8> fake_sig(fake_value_.c_str(),
fake_value_.c_str() + fake_value_.length());
MockLoginLibrary* lib = MockLoginLib();
- EXPECT_CALL(*lib, RequestStorePolicy(StrEq(signed_serialized), _, &d))
- .WillOnce(InvokeArgument<1>(static_cast<void*>(&d), true))
+ EXPECT_CALL(*lib, RequestStorePolicy(StrEq(signed_serialized), _, s.get()))
+ .WillOnce(InvokeArgument<1>(static_cast<void*>(s.get()), true))
.RetiresOnSaturation();
s->OnKeyOpComplete(OwnerManager::SUCCESS, fake_sig);
+ message_loop_.RunAllPending();
UnMockLoginLib();
}
@@ -465,16 +624,24 @@ TEST_F(SignedSettingsTest, StoreSignedPolicy) {
NormalDelegate<bool> d(true);
d.expect_success();
- std::string serialized;
- em::PolicyFetchResponse fake_policy = BuildProto(fake_prop_,
- fake_value_,
- &serialized);
+ em::PolicyData in_pol = BuildPolicyData(std::vector<std::string>());
+ std::string serialized = in_pol.SerializeAsString();
+ std::string signed_serialized;
+ em::PolicyFetchResponse signed_policy = BuildProto(serialized,
+ fake_value_,
+ &signed_serialized);
scoped_refptr<SignedSettings> s(
- SignedSettings::CreateStorePolicyOp(&fake_policy, &d));
+ SignedSettings::CreateStorePolicyOp(&signed_policy, &d));
MockLoginLibrary* lib = MockLoginLib();
- EXPECT_CALL(*lib, RequestStorePolicy(StrEq(serialized), _, &d))
- .WillOnce(InvokeArgument<1>(static_cast<void*>(&d), true))
+ EXPECT_CALL(*lib, RequestStorePolicy(StrEq(signed_serialized), _, s.get()))
+ .WillOnce(InvokeArgument<1>(static_cast<void*>(s.get()), true))
.RetiresOnSaturation();
+
+ mock_service(s.get(), &m_);
+ em::PolicyData out_pol;
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .WillOnce(SaveArg<0>(&out_pol));
+
s->Execute();
message_loop_.RunAllPending();
UnMockLoginLib();
@@ -500,11 +667,14 @@ TEST_F(SignedSettingsTest, StorePolicyNoPolicyData) {
SignedSettings::CreateStorePolicyOp(&fake_policy, &d));
s->Execute();
+ message_loop_.RunAllPending();
}
TEST_F(SignedSettingsTest, RetrievePolicy) {
+ em::PolicyData in_pol = BuildPolicyData(std::vector<std::string>());
+ std::string serialized = in_pol.SerializeAsString();
std::string signed_serialized;
- em::PolicyFetchResponse signed_policy = BuildProto(fake_prop_,
+ em::PolicyFetchResponse signed_policy = BuildProto(serialized,
fake_value_,
&signed_serialized);
ProtoDelegate d(signed_policy);
@@ -521,14 +691,18 @@ TEST_F(SignedSettingsTest, RetrievePolicy) {
mock_service(s.get(), &m_);
std::vector<uint8> fake_sig(fake_value_.c_str(),
fake_value_.c_str() + fake_value_.length());
- EXPECT_CALL(m_, StartVerifyAttempt(fake_prop_, fake_sig, _))
+ EXPECT_CALL(m_, StartVerifyAttempt(serialized, fake_sig, _))
.Times(1);
+ em::PolicyData out_pol;
+ EXPECT_CALL(m_, set_cached_policy(A<const em::PolicyData&>()))
+ .WillOnce(SaveArg<0>(&out_pol));
s->Execute();
message_loop_.RunAllPending();
UnMockLoginLib();
s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
TEST_F(SignedSettingsTest, RetrieveNullPolicy) {
@@ -614,6 +788,7 @@ TEST_F(SignedSettingsTest, RetrieveMalsignedPolicy) {
UnMockLoginLib();
s->OnKeyOpComplete(OwnerManager::OPERATION_FAILED, std::vector<uint8>());
+ message_loop_.RunAllPending();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.cc b/chrome/browser/chromeos/proxy_config_service_impl.cc
index 4613dec..161aaa4 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl.cc
@@ -10,6 +10,7 @@
#include "base/string_util.h"
#include "base/task.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
#include "chrome/common/json_value_serializer.h"
#include "content/browser/browser_thread.h"
@@ -92,9 +93,6 @@ std::string ProxyConfigToString(
return stream.str();
}
-// Name of signed setting persisted on device, writeable only by owner.
-const char* kSettingProxyEverywhere = "cros.proxy.everywhere";
-
// Names used for dictionary values to serialize chromeos::ProxyConfig.
const char* kMode = "mode";
const char* kSource = "src";
diff --git a/chrome/browser/chromeos/user_cros_settings_provider.cc b/chrome/browser/chromeos/user_cros_settings_provider.cc
index 4e76d86..d0b9a4e 100644
--- a/chrome/browser/chromeos/user_cros_settings_provider.cc
+++ b/chrome/browser/chromeos/user_cros_settings_provider.cc
@@ -133,9 +133,7 @@ bool GetUserWhitelist(ListValue* user_list) {
DCHECK(!prefs->IsManagedPreference(kAccountsPrefUsers));
std::vector<std::string> whitelist;
- if (!CrosLibrary::Get()->EnsureLoaded() ||
- !CrosLibrary::Get()->GetLoginLibrary()->EnumerateWhitelisted(
- &whitelist)) {
+ if (!SignedSettings::EnumerateWhitelist(&whitelist)) {
LOG(WARNING) << "Failed to retrieve user whitelist.";
return false;
}