summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos
diff options
context:
space:
mode:
authorcmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 23:14:37 +0000
committercmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 23:14:37 +0000
commit45636929754cf2622508668cdeded4f14196af81 (patch)
treeb835e1d94ba7a85c386f71e6a23a6510740a9431 /chrome/browser/chromeos
parent5ce82f432ac5cd5f241eb3a6b549c6e8089c3641 (diff)
downloadchromium_src-45636929754cf2622508668cdeded4f14196af81.zip
chromium_src-45636929754cf2622508668cdeded4f14196af81.tar.gz
chromium_src-45636929754cf2622508668cdeded4f14196af81.tar.bz2
[Chrome OS] Reimplement SignedSettings in terms of device policies.
Owner settings are being re-implemented as a single, signed protobuf that is stored by the chromium os 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. We cache it in the OwnershipService singleton. The SignedSettings API remains unchanged, semantically. This should all be re-implemented more cleanly (remove the out-dated notions of storing/retrieving properties and whitelisting, etc) as part of http://crosbug.com/14054 BUG=chromium-os:13230 TEST=unit tests Review URL: http://codereview.chromium.org/6831011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81828 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
-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;
}