summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjkummerow@chromium.org <jkummerow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-11 10:59:08 +0000
committerjkummerow@chromium.org <jkummerow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-11 10:59:08 +0000
commit6ced4e79b6b816022957ca3dbad7712b49aa2f36 (patch)
tree1ab8d3426c1f5f902745b37d20382a4befdd97f0
parent087b8c8ecf6630ab31d30913148e0e613a0ab881 (diff)
downloadchromium_src-6ced4e79b6b816022957ca3dbad7712b49aa2f36.zip
chromium_src-6ced4e79b6b816022957ca3dbad7712b49aa2f36.tar.gz
chromium_src-6ced4e79b6b816022957ca3dbad7712b49aa2f36.tar.bz2
Provide backend methods for device enrollment UI
BUG=chromium-os:13277 TEST=Existing unit tests Review URL: http://codereview.chromium.org/6794022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81088 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/login/signed_settings.cc8
-rw-r--r--chrome/browser/chromeos/login/signed_settings.h8
-rw-r--r--chrome/browser/chromeos/login/signed_settings_unittest.cc7
-rw-r--r--chrome/browser/policy/browser_policy_connector.cc32
-rw-r--r--chrome/browser/policy/browser_policy_connector.h30
-rw-r--r--chrome/browser/policy/cloud_policy_cache_base.cc15
-rw-r--r--chrome/browser/policy/cloud_policy_cache_base.h11
-rw-r--r--chrome/browser/policy/cloud_policy_controller.cc74
-rw-r--r--chrome/browser/policy/cloud_policy_controller.h32
-rw-r--r--chrome/browser/policy/cloud_policy_controller_unittest.cc54
-rw-r--r--chrome/browser/policy/cloud_policy_subsystem.cc39
-rw-r--r--chrome/browser/policy/cloud_policy_subsystem.h52
-rw-r--r--chrome/browser/policy/device_management_backend_impl.cc4
-rw-r--r--chrome/browser/policy/device_policy_cache.cc81
-rw-r--r--chrome/browser/policy/device_policy_cache.h10
-rw-r--r--chrome/browser/policy/device_policy_cache_unittest.cc5
-rw-r--r--chrome/browser/policy/device_policy_identity_strategy.cc159
-rw-r--r--chrome/browser/policy/device_policy_identity_strategy.h66
-rw-r--r--chrome/browser/policy/device_token_fetcher.cc40
-rw-r--r--chrome/browser/policy/device_token_fetcher.h17
-rw-r--r--chrome/browser/policy/device_token_fetcher_unittest.cc70
-rw-r--r--chrome/browser/policy/mock_device_management_backend.h14
-rw-r--r--chrome/browser/policy/mock_device_management_service.cc50
-rw-r--r--chrome/browser/policy/mock_device_management_service.h66
-rw-r--r--chrome/browser/policy/policy_notifier.cc69
-rw-r--r--chrome/browser/policy/policy_notifier.h69
-rw-r--r--chrome/browser/policy/proto/device_management_backend.proto8
-rw-r--r--chrome/browser/policy/user_policy_identity_strategy.cc1
-rw-r--r--chrome/browser/policy/user_policy_identity_strategy.h15
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi2
31 files changed, 739 insertions, 371 deletions
diff --git a/chrome/browser/chromeos/login/signed_settings.cc b/chrome/browser/chromeos/login/signed_settings.cc
index 8eec528..6e90a93 100644
--- a/chrome/browser/chromeos/login/signed_settings.cc
+++ b/chrome/browser/chromeos/login/signed_settings.cc
@@ -30,7 +30,7 @@ SignedSettings::~SignedSettings() {}
SignedSettings::ReturnCode SignedSettings::MapKeyOpCode(
OwnerManager::KeyOpCode return_code) {
return (return_code == OwnerManager::KEY_UNAVAILABLE ?
- KEY_UNAVAILABLE : OPERATION_FAILED);
+ KEY_UNAVAILABLE : BAD_SIGNATURE);
}
void SignedSettings::OnBoolComplete(void* delegate, bool success) {
@@ -543,10 +543,14 @@ void RetrievePolicyOp::ProcessPolicy(const char* out, const unsigned int len) {
d_->OnSettingsOpCompleted(NOT_FOUND, policy_);
return;
}
- if (!policy_.has_policy_data() || !policy_.has_policy_data_signature()) {
+ if (!policy_.has_policy_data()) {
d_->OnSettingsOpCompleted(OPERATION_FAILED, em::PolicyFetchResponse());
return;
}
+ if (!policy_.has_policy_data_signature()) {
+ d_->OnSettingsOpCompleted(BAD_SIGNATURE, em::PolicyFetchResponse());
+ return;
+ }
std::vector<uint8> sig;
const char* sig_ptr = policy_.policy_data_signature().c_str();
sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length());
diff --git a/chrome/browser/chromeos/login/signed_settings.h b/chrome/browser/chromeos/login/signed_settings.h
index 01092e5..1a374d2 100644
--- a/chrome/browser/chromeos/login/signed_settings.h
+++ b/chrome/browser/chromeos/login/signed_settings.h
@@ -7,6 +7,7 @@
#pragma once
#include <string>
+#include <vector>
#include "base/memory/ref_counted.h"
#include "chrome/browser/chromeos/login/owner_manager.h"
@@ -42,9 +43,10 @@ class SignedSettings : public base::RefCountedThreadSafe<SignedSettings>,
public:
enum ReturnCode {
SUCCESS,
- NOT_FOUND, // Email address or property name not found.
- KEY_UNAVAILABLE, // Owner key not yet configured.
- OPERATION_FAILED // Signature op or IPC to signed settings daemon failed.
+ NOT_FOUND, // Email address or property name not found.
+ KEY_UNAVAILABLE, // Owner key not yet configured.
+ OPERATION_FAILED, // IPC to signed settings daemon failed.
+ BAD_SIGNATURE // Signature verification failed.
};
template <class T>
diff --git a/chrome/browser/chromeos/login/signed_settings_unittest.cc b/chrome/browser/chromeos/login/signed_settings_unittest.cc
index e477388..6570cac 100644
--- a/chrome/browser/chromeos/login/signed_settings_unittest.cc
+++ b/chrome/browser/chromeos/login/signed_settings_unittest.cc
@@ -490,8 +490,7 @@ TEST_F(SignedSettingsTest, StorePolicyFailed) {
TEST_F(SignedSettingsTest, StorePolicyNoPolicyData) {
NormalDelegate<bool> d(false);
- d.expect_failure(
- SignedSettings::MapKeyOpCode(OwnerManager::OPERATION_FAILED));
+ d.expect_failure(SignedSettings::OPERATION_FAILED);
std::string serialized;
em::PolicyFetchResponse fake_policy = BuildProto(std::string(),
@@ -573,7 +572,7 @@ TEST_F(SignedSettingsTest, RetrieveUnsignedPolicy) {
std::string(),
&serialized);
ProtoDelegate d(policy);
- d.expect_failure(SignedSettings::OPERATION_FAILED);
+ d.expect_failure(SignedSettings::BAD_SIGNATURE);
scoped_refptr<SignedSettings> s(SignedSettings::CreateRetrievePolicyOp(&d));
MockLoginLibrary* lib = MockLoginLib();
@@ -594,7 +593,7 @@ TEST_F(SignedSettingsTest, RetrieveMalsignedPolicy) {
fake_value_,
&signed_serialized);
ProtoDelegate d(signed_policy);
- d.expect_failure(SignedSettings::OPERATION_FAILED);
+ d.expect_failure(SignedSettings::BAD_SIGNATURE);
scoped_refptr<SignedSettings> s(SignedSettings::CreateRetrievePolicyOp(&d));
MockLoginLibrary* lib = MockLoginLib();
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index b11d16e..df75c9b 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -8,7 +8,6 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
#include "chrome/browser/policy/cloud_policy_subsystem.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
@@ -45,9 +44,9 @@ BrowserPolicyConnector::BrowserPolicyConnector() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableDevicePolicy)) {
identity_strategy_.reset(new DevicePolicyIdentityStrategy());
- cloud_policy_subsystem_.reset(
- new CloudPolicySubsystem(identity_strategy_.get(),
- new DevicePolicyCache()));
+ cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
+ identity_strategy_.get(),
+ new DevicePolicyCache(identity_strategy_.get())));
}
#endif
}
@@ -62,7 +61,9 @@ BrowserPolicyConnector::~BrowserPolicyConnector() {
if (cloud_policy_subsystem_.get())
cloud_policy_subsystem_->Shutdown();
cloud_policy_subsystem_.reset();
+#if defined(OS_CHROMEOS)
identity_strategy_.reset();
+#endif
}
ConfigurationPolicyProvider*
@@ -137,6 +138,29 @@ void BrowserPolicyConnector::RegisterPrefs(PrefService* local_state) {
kDefaultPolicyRefreshRateInMilliseconds);
}
+void BrowserPolicyConnector::SetCredentials(const std::string& owner_email,
+ const std::string& gaia_token,
+ const std::string& machine_id) {
+#if defined(OS_CHROMEOS)
+ if (identity_strategy_.get())
+ identity_strategy_->SetAuthCredentials(owner_email, gaia_token, machine_id);
+#endif
+}
+
+bool BrowserPolicyConnector::IsEnterpriseManaged() {
+#if defined(OS_CHROMEOS)
+ return (identity_strategy_.get() &&
+ !identity_strategy_->GetDeviceToken().empty());
+#else
+ return false;
+#endif
+}
+
+void BrowserPolicyConnector::StopAutoRetry() {
+ if (cloud_policy_subsystem_.get())
+ cloud_policy_subsystem_->StopAutoRetry();
+}
+
void BrowserPolicyConnector::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h
index 2271f213..93995c8 100644
--- a/chrome/browser/policy/browser_policy_connector.h
+++ b/chrome/browser/policy/browser_policy_connector.h
@@ -6,6 +6,8 @@
#define CHROME_BROWSER_POLICY_BROWSER_POLICY_CONNECTOR_H_
#pragma once
+#include <string>
+
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/notification_observer.h"
@@ -21,9 +23,9 @@ class URLRequestContextGetter;
namespace policy {
-class CloudPolicyIdentityStrategy;
class CloudPolicySubsystem;
class ConfigurationPolicyProvider;
+class DevicePolicyIdentityStrategy;
// Manages the lifecycle of browser-global policy infrastructure, such as the
// platform policy providers.
@@ -40,8 +42,30 @@ class BrowserPolicyConnector : public NotificationObserver {
ConfigurationPolicyProvider* GetRecommendedPlatformProvider() const;
ConfigurationPolicyProvider* GetRecommendedCloudProvider() const;
+ // Returns a weak pointer to the CloudPolicySubsystem managed by this
+ // policy connector, or NULL if no such subsystem exists (i.e. when running
+ // outside ChromeOS).
+ CloudPolicySubsystem* cloud_policy_subsystem() {
+ return cloud_policy_subsystem_.get();
+ }
+
static void RegisterPrefs(PrefService* user_prefs);
+ // Used to set the credentials stored in the identity strategy associated
+ // with this policy connector.
+ void SetCredentials(const std::string& owner_email,
+ const std::string& gaia_token,
+ const std::string& machine_id);
+
+ // Returns true if this device is managed by an enterprise (as opposed to
+ // a local owner).
+ bool IsEnterpriseManaged();
+
+ // Exposes the StopAutoRetry() method of the CloudPolicySubsystem managed
+ // by this connector, which can be used to disable automatic
+ // retrying behavior.
+ void StopAutoRetry();
+
// NotificationObserver implementation:
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -67,7 +91,9 @@ class BrowserPolicyConnector : public NotificationObserver {
scoped_ptr<ConfigurationPolicyProvider> managed_platform_provider_;
scoped_ptr<ConfigurationPolicyProvider> recommended_platform_provider_;
- scoped_ptr<CloudPolicyIdentityStrategy> identity_strategy_;
+#if defined(OS_CHROMEOS)
+ scoped_ptr<DevicePolicyIdentityStrategy> identity_strategy_;
+#endif
scoped_ptr<CloudPolicySubsystem> cloud_policy_subsystem_;
NotificationRegistrar registrar_;
diff --git a/chrome/browser/policy/cloud_policy_cache_base.cc b/chrome/browser/policy/cloud_policy_cache_base.cc
index 8af7533..3f1f48c 100644
--- a/chrome/browser/policy/cloud_policy_cache_base.cc
+++ b/chrome/browser/policy/cloud_policy_cache_base.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/values.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/policy_notifier.h"
namespace policy {
@@ -54,7 +55,8 @@ class CloudPolicyCacheBase::CloudPolicyProvider
};
CloudPolicyCacheBase::CloudPolicyCacheBase()
- : initialization_complete_(false),
+ : notifier_(NULL),
+ initialization_complete_(false),
is_unmanaged_(false) {
managed_policy_provider_.reset(
new CloudPolicyProvider(
@@ -109,6 +111,8 @@ bool CloudPolicyCacheBase::SetPolicyInternal(
FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
observer_list_, OnUpdatePolicy());
}
+ InformNotifier(CloudPolicySubsystem::SUCCESS,
+ CloudPolicySubsystem::NO_DETAILS);
return true;
}
@@ -152,4 +156,13 @@ bool CloudPolicyCacheBase::DecodePolicyResponse(
return DecodePolicyData(policy_data, mandatory, recommended);
}
+void CloudPolicyCacheBase::InformNotifier(
+ CloudPolicySubsystem::PolicySubsystemState state,
+ CloudPolicySubsystem::ErrorDetails error_details) {
+ // TODO(jkummerow): To obsolete this NULL-check, make all uses of
+ // UserPolicyCache explicitly set a notifier using |set_policy_notifier()|.
+ if (notifier_)
+ notifier_->Inform(state, error_details, PolicyNotifier::POLICY_CACHE);
+}
+
} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_cache_base.h b/chrome/browser/policy/cloud_policy_cache_base.h
index 44cfd87..f97d6cf 100644
--- a/chrome/browser/policy/cloud_policy_cache_base.h
+++ b/chrome/browser/policy/cloud_policy_cache_base.h
@@ -11,6 +11,7 @@
#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "base/time.h"
+#include "chrome/browser/policy/cloud_policy_subsystem.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/policy_map.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
@@ -18,6 +19,7 @@
namespace policy {
class PolicyMap;
+class PolicyNotifier;
namespace em = enterprise_management;
@@ -37,6 +39,10 @@ class CloudPolicyCacheBase : public base::NonThreadSafe {
CloudPolicyCacheBase();
virtual ~CloudPolicyCacheBase();
+ void set_policy_notifier(PolicyNotifier* notifier) {
+ notifier_ = notifier;
+ }
+
// Loads persisted policy information.
virtual void Load() = 0;
@@ -82,6 +88,9 @@ class CloudPolicyCacheBase : public base::NonThreadSafe {
PolicyMap* recommended,
base::Time* timestamp);
+ void InformNotifier(CloudPolicySubsystem::PolicySubsystemState state,
+ CloudPolicySubsystem::ErrorDetails error_details);
+
// See comment for |initialization_complete_|.
bool initialization_complete() {
return initialization_complete_;
@@ -105,6 +114,8 @@ class CloudPolicyCacheBase : public base::NonThreadSafe {
scoped_ptr<ConfigurationPolicyProvider> managed_policy_provider_;
scoped_ptr<ConfigurationPolicyProvider> recommended_policy_provider_;
+ PolicyNotifier* notifier_;
+
// The time at which the policy was last refreshed. Is updated both upon
// successful and unsuccessful refresh attempts.
base::Time last_policy_refresh_time_;
diff --git a/chrome/browser/policy/cloud_policy_controller.cc b/chrome/browser/policy/cloud_policy_controller.cc
index 9337b02..60171b1 100644
--- a/chrome/browser/policy/cloud_policy_controller.cc
+++ b/chrome/browser/policy/cloud_policy_controller.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/policy/cloud_policy_cache_base.h"
#include "chrome/browser/policy/cloud_policy_subsystem.h"
#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
// Domain names that are known not to be managed.
@@ -60,15 +61,17 @@ static const int kPolicyRefreshRateInMilliseconds =
3 * 60 * 60 * 1000; // 3 hours.
CloudPolicyController::CloudPolicyController(
+ DeviceManagementService* service,
CloudPolicyCacheBase* cache,
- DeviceManagementBackend* backend,
DeviceTokenFetcher* token_fetcher,
- CloudPolicyIdentityStrategy* identity_strategy)
+ CloudPolicyIdentityStrategy* identity_strategy,
+ PolicyNotifier* notifier)
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
- Initialize(cache,
- backend,
+ Initialize(service,
+ cache,
token_fetcher,
identity_strategy,
+ notifier,
kPolicyRefreshRateInMilliseconds,
kPolicyRefreshDeviationFactorPercent,
kPolicyRefreshDeviationMaxInMilliseconds,
@@ -89,17 +92,13 @@ void CloudPolicyController::SetRefreshRate(int64 refresh_rate_milliseconds) {
SetState(STATE_POLICY_VALID);
}
+void CloudPolicyController::StopAutoRetry() {
+ CancelDelayedWork();
+ backend_.reset();
+}
+
void CloudPolicyController::HandlePolicyResponse(
const em::DevicePolicyResponse& response) {
- // In case state has changed by the user while request was in progress ignore
- // the answer.
- if (state_ == STATE_TOKEN_UNAVAILABLE ||
- state_ == STATE_TOKEN_UNMANAGED ||
- state_ == STATE_TOKEN_ERROR) {
- LOG(WARNING) << "Unexpected reply from policy server received. Ignoring.";
- return;
- }
-
if (response.response_size() > 0) {
if (response.response_size() > 1) {
LOG(WARNING) << "More than one policy in the response of the device "
@@ -116,15 +115,6 @@ void CloudPolicyController::HandlePolicyResponse(
}
void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) {
- // In case state has changed by the user while request was in progress ignore
- // the answer.
- if (state_ == STATE_TOKEN_UNAVAILABLE ||
- state_ == STATE_TOKEN_UNMANAGED ||
- state_ == STATE_TOKEN_ERROR) {
- LOG(WARNING) << "Unexpected reply from policy server received. Ignoring.";
- return;
- }
-
switch (code) {
case DeviceManagementBackend::kErrorServiceDeviceNotFound:
case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: {
@@ -177,19 +167,21 @@ void CloudPolicyController::OnCredentialsChanged() {
}
CloudPolicyController::CloudPolicyController(
+ DeviceManagementService* service,
CloudPolicyCacheBase* cache,
- DeviceManagementBackend* backend,
DeviceTokenFetcher* token_fetcher,
CloudPolicyIdentityStrategy* identity_strategy,
+ PolicyNotifier* notifier,
int64 policy_refresh_rate_ms,
int policy_refresh_deviation_factor_percent,
int64 policy_refresh_deviation_max_ms,
int64 policy_refresh_error_delay_ms)
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
- Initialize(cache,
- backend,
+ Initialize(service,
+ cache,
token_fetcher,
identity_strategy,
+ notifier,
policy_refresh_rate_ms,
policy_refresh_deviation_factor_percent,
policy_refresh_deviation_max_ms,
@@ -197,20 +189,22 @@ CloudPolicyController::CloudPolicyController(
}
void CloudPolicyController::Initialize(
+ DeviceManagementService* service,
CloudPolicyCacheBase* cache,
- DeviceManagementBackend* backend,
DeviceTokenFetcher* token_fetcher,
CloudPolicyIdentityStrategy* identity_strategy,
+ PolicyNotifier* notifier,
int64 policy_refresh_rate_ms,
int policy_refresh_deviation_factor_percent,
int64 policy_refresh_deviation_max_ms,
int64 policy_refresh_error_delay_ms) {
DCHECK(cache);
+ service_ = service;
cache_ = cache;
- backend_.reset(backend);
token_fetcher_ = token_fetcher;
identity_strategy_ = identity_strategy;
+ notifier_ = notifier;
state_ = STATE_TOKEN_UNAVAILABLE;
delayed_work_task_ = NULL;
policy_refresh_rate_ms_ = policy_refresh_rate_ms;
@@ -242,6 +236,7 @@ void CloudPolicyController::FetchToken() {
}
void CloudPolicyController::SendPolicyRequest() {
+ backend_.reset(service_->CreateBackend());
DCHECK(!identity_strategy_->GetDeviceToken().empty());
em::DevicePolicyRequest policy_request;
em::PolicyFetchRequest* fetch_request = policy_request.add_request();
@@ -262,7 +257,10 @@ void CloudPolicyController::SendPolicyRequest() {
void CloudPolicyController::DoDelayedWork() {
DCHECK(delayed_work_task_);
delayed_work_task_ = NULL;
+ DoWork();
+}
+void CloudPolicyController::DoWork() {
switch (state_) {
case STATE_TOKEN_UNAVAILABLE:
case STATE_TOKEN_ERROR:
@@ -291,6 +289,7 @@ void CloudPolicyController::CancelDelayedWork() {
void CloudPolicyController::SetState(
CloudPolicyController::ControllerState new_state) {
state_ = new_state;
+ backend_.reset(); // Discard any pending requests.
base::Time now(base::Time::NowFromSystemTime());
base::Time refresh_at;
@@ -299,8 +298,12 @@ void CloudPolicyController::SetState(
last_refresh = now;
// Determine when to take the next step.
+ bool inform_notifier_done = false;
switch (state_) {
case STATE_TOKEN_UNMANAGED:
+ notifier_->Inform(CloudPolicySubsystem::UNMANAGED,
+ CloudPolicySubsystem::NO_DETAILS,
+ PolicyNotifier::POLICY_CONTROLLER);
break;
case STATE_TOKEN_UNAVAILABLE:
// The controller is not yet initialized and needs to immediately fetch
@@ -309,6 +312,8 @@ void CloudPolicyController::SetState(
// Immediately try to fetch the token on initialization or policy after a
// token update. Subsequent retries will respect the back-off strategy.
refresh_at = now;
+ // |notifier_| isn't informed about anything at this point, we wait for
+ // the result of the next action first.
break;
case STATE_POLICY_VALID:
// Delay is only reset if the policy fetch operation was successful. This
@@ -317,9 +322,21 @@ void CloudPolicyController::SetState(
effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
refresh_at =
last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay());
+ notifier_->Inform(CloudPolicySubsystem::SUCCESS,
+ CloudPolicySubsystem::NO_DETAILS,
+ PolicyNotifier::POLICY_CONTROLLER);
break;
case STATE_TOKEN_ERROR:
+ notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
+ CloudPolicySubsystem::BAD_DMTOKEN,
+ PolicyNotifier::POLICY_CONTROLLER);
+ inform_notifier_done = true;
case STATE_POLICY_ERROR:
+ if (!inform_notifier_done) {
+ notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
+ CloudPolicySubsystem::POLICY_NETWORK_ERROR,
+ PolicyNotifier::POLICY_CONTROLLER);
+ }
refresh_at = now + base::TimeDelta::FromMilliseconds(
effective_policy_refresh_error_delay_ms_);
effective_policy_refresh_error_delay_ms_ =
@@ -330,6 +347,9 @@ void CloudPolicyController::SetState(
effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
refresh_at = now + base::TimeDelta::FromMilliseconds(
effective_policy_refresh_error_delay_ms_);
+ notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
+ CloudPolicySubsystem::POLICY_NETWORK_ERROR,
+ PolicyNotifier::POLICY_CONTROLLER);
break;
}
diff --git a/chrome/browser/policy/cloud_policy_controller.h b/chrome/browser/policy/cloud_policy_controller.h
index 1bc316b..61ff3bb 100644
--- a/chrome/browser/policy/cloud_policy_controller.h
+++ b/chrome/browser/policy/cloud_policy_controller.h
@@ -35,15 +35,20 @@ class CloudPolicyController
public CloudPolicyIdentityStrategy::Observer {
public:
// Takes ownership of |backend|; the other parameters are weak pointers.
- CloudPolicyController(CloudPolicyCacheBase* cache,
- DeviceManagementBackend* backend,
+ CloudPolicyController(DeviceManagementService* service,
+ CloudPolicyCacheBase* cache,
DeviceTokenFetcher* token_fetcher,
- CloudPolicyIdentityStrategy* identity_strategy);
+ CloudPolicyIdentityStrategy* identity_strategy,
+ PolicyNotifier* notifier);
virtual ~CloudPolicyController();
// Sets the refresh rate at which to re-fetch policy information.
void SetRefreshRate(int64 refresh_rate_milliseconds);
+ // Stops all auto-retrying error handling behavior inside the policy
+ // subsystem.
+ void StopAutoRetry();
+
// DevicePolicyResponseDelegate implementation:
virtual void HandlePolicyResponse(
const em::DevicePolicyResponse& response);
@@ -78,20 +83,22 @@ class CloudPolicyController
friend class CloudPolicyControllerTest;
// More configurable constructor for use by test cases.
- CloudPolicyController(CloudPolicyCacheBase* cache,
- DeviceManagementBackend* backend,
+ CloudPolicyController(DeviceManagementService* service,
+ CloudPolicyCacheBase* cache,
DeviceTokenFetcher* token_fetcher,
CloudPolicyIdentityStrategy* identity_strategy,
+ PolicyNotifier* notifier,
int64 policy_refresh_rate_ms,
int policy_refresh_deviation_factor_percent,
int64 policy_refresh_deviation_max_ms,
int64 policy_refresh_error_delay_ms);
// Called by constructors to perform shared initialization.
- void Initialize(CloudPolicyCacheBase* cache,
- DeviceManagementBackend* backend,
+ void Initialize(DeviceManagementService* service,
+ CloudPolicyCacheBase* cache,
DeviceTokenFetcher* token_fetcher,
CloudPolicyIdentityStrategy* identity_strategy,
+ PolicyNotifier* notifier,
int64 policy_refresh_rate_ms,
int policy_refresh_deviation_factor_percent,
int64 policy_refresh_deviation_max_ms,
@@ -104,10 +111,13 @@ class CloudPolicyController
// isn't already outstanding.
void SendPolicyRequest();
- // Called back from the delayed work task. Performs whatever action is
- // required in the current state, e.g. refreshing policy.
+ // Called back from the delayed work task. Calls |DoWork()|.
void DoDelayedWork();
+ // Performs whatever action is required in the current state,
+ // e.g. refreshing policy.
+ void DoWork();
+
// Cancels the delayed work task.
void CancelDelayedWork();
@@ -117,12 +127,14 @@ class CloudPolicyController
// Computes the policy refresh delay to use.
int64 GetRefreshDelay();
+ DeviceManagementService* service_;
CloudPolicyCacheBase* cache_;
- scoped_ptr<DeviceManagementBackend> backend_;
CloudPolicyIdentityStrategy* identity_strategy_;
DeviceTokenFetcher* token_fetcher_;
+ scoped_ptr<DeviceManagementBackend> backend_;
ControllerState state_;
bool initial_fetch_done_;
+ PolicyNotifier* notifier_;
int64 policy_refresh_rate_ms_;
int policy_refresh_deviation_factor_percent_;
diff --git a/chrome/browser/policy/cloud_policy_controller_unittest.cc b/chrome/browser/policy/cloud_policy_controller_unittest.cc
index 6419521..e3569b9 100644
--- a/chrome/browser/policy/cloud_policy_controller_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_controller_unittest.cc
@@ -6,9 +6,12 @@
#include "base/memory/scoped_temp_dir.h"
#include "base/message_loop.h"
+#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/device_token_fetcher.h"
#include "chrome/browser/policy/mock_configuration_policy_store.h"
#include "chrome/browser/policy/mock_device_management_backend.h"
+#include "chrome/browser/policy/mock_device_management_service.h"
+#include "chrome/browser/policy/policy_notifier.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/user_policy_cache.h"
#include "content/browser/browser_thread.h"
@@ -55,7 +58,7 @@ ACTION_P2(MockCloudPolicyIdentityStrategyGetCredentials, username, auth_token) {
class MockDeviceTokenFetcher : public DeviceTokenFetcher {
public:
explicit MockDeviceTokenFetcher(CloudPolicyCacheBase* cache)
- : DeviceTokenFetcher(NULL, cache) {}
+ : DeviceTokenFetcher(NULL, cache, NULL) {}
virtual ~MockDeviceTokenFetcher() {}
MOCK_METHOD0(GetDeviceToken, const std::string&());
@@ -81,6 +84,7 @@ class CloudPolicyControllerTest : public testing::Test {
cache_.reset(new UserPolicyCache(
temp_user_data_dir_.path().AppendASCII("CloudPolicyControllerTest")));
token_fetcher_.reset(new MockDeviceTokenFetcher(cache_.get()));
+ service_.set_backend(&backend_);
}
virtual void TearDown() {
@@ -88,18 +92,19 @@ class CloudPolicyControllerTest : public testing::Test {
}
// Takes ownership of |backend|.
- void CreateNewController(DeviceManagementBackend* backend) {
+ void CreateNewController() {
controller_.reset(new CloudPolicyController(
- cache_.get(), backend, token_fetcher_.get(), &identity_strategy_));
+ &service_, cache_.get(), token_fetcher_.get(), &identity_strategy_,
+ &notifier_));
}
- void CreateNewController(DeviceManagementBackend* backend,
- int64 policy_refresh_rate_ms,
+ void CreateNewController(int64 policy_refresh_rate_ms,
int policy_refresh_deviation_factor_percent,
int64 policy_refresh_deviation_max_ms,
int64 policy_refresh_error_delay_ms) {
controller_.reset(new CloudPolicyController(
- cache_.get(), backend, token_fetcher_.get(), &identity_strategy_,
+ &service_, cache_.get(), token_fetcher_.get(), &identity_strategy_,
+ &notifier_,
policy_refresh_rate_ms,
policy_refresh_deviation_factor_percent,
policy_refresh_deviation_max_ms,
@@ -144,6 +149,9 @@ class CloudPolicyControllerTest : public testing::Test {
scoped_ptr<CloudPolicyController> controller_;
scoped_ptr<MockDeviceTokenFetcher> token_fetcher_;
MockCloudPolicyIdentityStrategy identity_strategy_;
+ MockDeviceManagementBackend backend_;
+ MockDeviceManagementService service_;
+ PolicyNotifier notifier_;
ScopedTempDir temp_user_data_dir_;
MessageLoop loop_;
@@ -160,10 +168,9 @@ TEST_F(CloudPolicyControllerTest, StartupWithDeviceToken) {
SetupIdentityStrategy("fake_device_token", "device_id", "machine_id",
"google/chromeos/user",
em::DeviceRegisterRequest::USER, "", "");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- CreateNewController(backend);
+ CreateNewController();
loop_.RunAllPending();
ExpectHasSpdyPolicy();
}
@@ -175,7 +182,7 @@ TEST_F(CloudPolicyControllerTest, StartupWithoutDeviceToken) {
em::DeviceRegisterRequest::USER,
"a@b.com", "auth_token");
EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
- CreateNewController(NULL);
+ CreateNewController();
loop_.RunAllPending();
}
@@ -186,7 +193,7 @@ TEST_F(CloudPolicyControllerTest, StartupUnmanagedUser) {
em::DeviceRegisterRequest::USER,
"DannoHelper@gmail.com", "auth_token");
EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(0);
- CreateNewController(NULL);
+ CreateNewController();
loop_.RunAllPending();
}
@@ -196,12 +203,11 @@ TEST_F(CloudPolicyControllerTest, RefreshAfterSuccessfulPolicy) {
SetupIdentityStrategy("device_token", "device_id", "machine_id",
"google/chromeos/user", em::DeviceRegisterRequest::USER,
"DannoHelperDelegate@b.com", "auth_token");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedSpdyCloudPolicy()).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorRequestFailed));
- CreateNewController(backend, 0, 0, 0, 1000 * 1000);
+ CreateNewController(0, 0, 0, 1000 * 1000);
loop_.RunAllPending();
ExpectHasSpdyPolicy();
}
@@ -211,12 +217,11 @@ TEST_F(CloudPolicyControllerTest, RefreshAfterError) {
SetupIdentityStrategy("device_token", "device_id", "machine_id",
"google/chromeos/user", em::DeviceRegisterRequest::USER,
"DannoHelperDelegateImpl@b.com", "auth_token");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorRequestFailed)).WillOnce(
MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- CreateNewController(backend, 1000 * 1000, 0, 0, 0);
+ CreateNewController(1000 * 1000, 0, 0, 0);
loop_.RunAllPending();
ExpectHasSpdyPolicy();
}
@@ -227,12 +232,11 @@ TEST_F(CloudPolicyControllerTest, InvalidToken) {
SetupIdentityStrategy("device_token", "device_id", "machine_id",
"google/chromeos/user", em::DeviceRegisterRequest::USER,
"standup@ten.am", "auth");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
- CreateNewController(backend, 1000 * 1000, 0, 0, 0);
+ CreateNewController(1000 * 1000, 0, 0, 0);
loop_.RunAllPending();
}
@@ -242,12 +246,11 @@ TEST_F(CloudPolicyControllerTest, DeviceNotFound) {
SetupIdentityStrategy("device_token", "device_id", "machine_id",
"google/chromeos/user", em::DeviceRegisterRequest::USER,
"me@you.com", "auth");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorServiceDeviceNotFound));
EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
- CreateNewController(backend, 1000 * 1000, 0, 0, 0);
+ CreateNewController(1000 * 1000, 0, 0, 0);
loop_.RunAllPending();
}
@@ -258,12 +261,11 @@ TEST_F(CloudPolicyControllerTest, NoLongerManaged) {
SetupIdentityStrategy("device_token", "device_id", "machine_id",
"google/chromeos/user", em::DeviceRegisterRequest::USER,
"who@what.com", "auth");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorServiceManagementNotSupported));
EXPECT_CALL(*token_fetcher_.get(), SetUnmanagedState()).Times(1);
- CreateNewController(backend, 0, 0, 0, 1000 * 1000);
+ CreateNewController(0, 0, 0, 1000 * 1000);
loop_.RunAllPending();
}
diff --git a/chrome/browser/policy/cloud_policy_subsystem.cc b/chrome/browser/policy/cloud_policy_subsystem.cc
index 59bc04f..031dab2 100644
--- a/chrome/browser/policy/cloud_policy_subsystem.cc
+++ b/chrome/browser/policy/cloud_policy_subsystem.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/device_token_fetcher.h"
+#include "chrome/browser/policy/policy_notifier.h"
#include "chrome/common/chrome_switches.h"
#include "content/common/notification_details.h"
#include "content/common/notification_source.h"
@@ -29,26 +30,43 @@ const int64 kPolicyRefreshRateMaxMs = 24 * 60 * 60 * 1000; // 1 day
namespace policy {
+CloudPolicySubsystem::ObserverRegistrar::ObserverRegistrar(
+ CloudPolicySubsystem* cloud_policy_subsystem,
+ CloudPolicySubsystem::Observer* observer)
+ : observer_(observer) {
+ policy_notifier_ = cloud_policy_subsystem->notifier();
+ policy_notifier_->AddObserver(observer);
+}
+
+CloudPolicySubsystem::ObserverRegistrar::~ObserverRegistrar() {
+ if (policy_notifier_)
+ policy_notifier_->RemoveObserver(observer_);
+}
+
CloudPolicySubsystem::CloudPolicySubsystem(
CloudPolicyIdentityStrategy* identity_strategy,
CloudPolicyCacheBase* policy_cache)
: prefs_(NULL) {
+ notifier_.reset(new PolicyNotifier());
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
device_management_service_.reset(new DeviceManagementService(
command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl)));
cloud_policy_cache_.reset(policy_cache);
+ cloud_policy_cache_->set_policy_notifier(notifier_.get());
cloud_policy_cache_->Load();
device_token_fetcher_.reset(
new DeviceTokenFetcher(device_management_service_.get(),
- cloud_policy_cache_.get()));
+ cloud_policy_cache_.get(),
+ notifier_.get()));
cloud_policy_controller_.reset(
- new CloudPolicyController(cloud_policy_cache_.get(),
- device_management_service_->CreateBackend(),
+ new CloudPolicyController(device_management_service_.get(),
+ cloud_policy_cache_.get(),
device_token_fetcher_.get(),
- identity_strategy));
+ identity_strategy,
+ notifier_.get()));
}
}
@@ -83,6 +101,19 @@ void CloudPolicySubsystem::Shutdown() {
prefs_ = NULL;
}
+CloudPolicySubsystem::PolicySubsystemState CloudPolicySubsystem::state() {
+ return notifier_->state();
+}
+
+CloudPolicySubsystem::ErrorDetails CloudPolicySubsystem::error_details() {
+ return notifier_->error_details();
+}
+
+void CloudPolicySubsystem::StopAutoRetry() {
+ cloud_policy_controller_->StopAutoRetry();
+ device_token_fetcher_->StopAutoRetry();
+}
+
ConfigurationPolicyProvider* CloudPolicySubsystem::GetManagedPolicyProvider() {
if (cloud_policy_cache_.get())
return cloud_policy_cache_->GetManagedPolicyProvider();
diff --git a/chrome/browser/policy/cloud_policy_subsystem.h b/chrome/browser/policy/cloud_policy_subsystem.h
index 3b49339..ab1744c 100644
--- a/chrome/browser/policy/cloud_policy_subsystem.h
+++ b/chrome/browser/policy/cloud_policy_subsystem.h
@@ -24,12 +24,50 @@ class CloudPolicyIdentityStrategy;
class ConfigurationPolicyProvider;
class DeviceManagementService;
class DeviceTokenFetcher;
+class PolicyNotifier;
// This class is a container for the infrastructure required to support cloud
// policy. It glues together the backend, the policy controller and manages the
// life cycle of the policy providers.
class CloudPolicySubsystem : public NotificationObserver {
public:
+ enum PolicySubsystemState {
+ UNENROLLED, // No enrollment attempt has been performed yet.
+ BAD_GAIA_TOKEN, // The server rejected the GAIA auth token.
+ UNMANAGED, // This device is unmanaged.
+ NETWORK_ERROR, // A network error occurred, retrying makes sense.
+ LOCAL_ERROR, // Retrying is futile.
+ SUCCESS // Policy has been fetched successfully and is in effect.
+ };
+
+ enum ErrorDetails {
+ NO_DETAILS, // No error, so no error details either.
+ DMTOKEN_NETWORK_ERROR, // DeviceTokenFetcher encountered a network error.
+ POLICY_NETWORK_ERROR, // CloudPolicyController encountered a network error.
+ BAD_DMTOKEN, // The server rejected the DMToken.
+ POLICY_LOCAL_ERROR, // The policy cache encountered a local error.
+ SIGNATURE_MISMATCH, // The policy cache detected a signature mismatch.
+ };
+
+ class Observer {
+ public:
+ virtual ~Observer() {}
+ virtual void OnPolicyStateChanged(PolicySubsystemState state,
+ ErrorDetails error_details) = 0;
+ };
+
+ class ObserverRegistrar {
+ public:
+ ObserverRegistrar(CloudPolicySubsystem* cloud_policy_subsystem,
+ CloudPolicySubsystem::Observer* observer);
+ ~ObserverRegistrar();
+
+ private:
+ PolicyNotifier* policy_notifier_;
+ CloudPolicySubsystem::Observer* observer_;
+ DISALLOW_COPY_AND_ASSIGN(ObserverRegistrar);
+ };
+
CloudPolicySubsystem(CloudPolicyIdentityStrategy* identity_strategy,
CloudPolicyCacheBase* policy_cache);
virtual ~CloudPolicySubsystem();
@@ -43,6 +81,14 @@ class CloudPolicySubsystem : public NotificationObserver {
// infrastructure goes away.
void Shutdown();
+ // Returns the externally visible state and corresponding error details.
+ PolicySubsystemState state();
+ ErrorDetails error_details();
+
+ // Stops all auto-retrying error handling behavior inside the policy
+ // subsystem.
+ void StopAutoRetry();
+
ConfigurationPolicyProvider* GetManagedPolicyProvider();
ConfigurationPolicyProvider* GetRecommendedPolicyProvider();
@@ -50,6 +96,11 @@ class CloudPolicySubsystem : public NotificationObserver {
// Updates the policy controller with a new refresh rate value.
void UpdatePolicyRefreshRate();
+ // Returns a weak pointer to this subsystem's PolicyNotifier.
+ PolicyNotifier* notifier() {
+ return notifier_.get();
+ }
+
// NotificationObserver overrides.
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -62,6 +113,7 @@ class CloudPolicySubsystem : public NotificationObserver {
IntegerPrefMember policy_refresh_rate_;
// Cloud policy infrastructure stuff.
+ scoped_ptr<PolicyNotifier> notifier_;
scoped_ptr<DeviceManagementService> device_management_service_;
scoped_ptr<DeviceTokenFetcher> device_token_fetcher_;
scoped_ptr<CloudPolicyCacheBase> cloud_policy_cache_;
diff --git a/chrome/browser/policy/device_management_backend_impl.cc b/chrome/browser/policy/device_management_backend_impl.cc
index bc95c12..7accf7b 100644
--- a/chrome/browser/policy/device_management_backend_impl.cc
+++ b/chrome/browser/policy/device_management_backend_impl.cc
@@ -48,7 +48,7 @@ const int kDeviceManagementNotAllowed = 403;
const int kInvalidURL = 404; // This error is not coming from the GFE.
const int kPendingApproval = 491;
const int kInternalServerError = 500;
-const int kServiceUnavaiable = 503;
+const int kServiceUnavailable = 503;
const int kDeviceNotFound = 901;
const int kPolicyNotFound = 902; // This error is not sent as HTTP status code.
@@ -215,7 +215,7 @@ void DeviceManagementJobBase::HandleResponse(
}
case kInvalidURL:
case kInternalServerError:
- case kServiceUnavaiable: {
+ case kServiceUnavailable: {
OnError(DeviceManagementBackend::kErrorTemporaryUnavailable);
return;
}
diff --git a/chrome/browser/policy/device_policy_cache.cc b/chrome/browser/policy/device_policy_cache.cc
index 39381dc..bbd780f 100644
--- a/chrome/browser/policy/device_policy_cache.cc
+++ b/chrome/browser/policy/device_policy_cache.cc
@@ -9,6 +9,7 @@
#include "base/task.h"
#include "base/values.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/device_policy_identity_strategy.h"
#include "chrome/browser/policy/policy_map.h"
#include "chrome/browser/policy/proto/cloud_policy.pb.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
@@ -20,13 +21,19 @@ using google::protobuf::RepeatedPtrField;
namespace policy {
-DevicePolicyCache::DevicePolicyCache()
- : signed_settings_helper_(chromeos::SignedSettingsHelper::Get()) {
+DevicePolicyCache::DevicePolicyCache(
+ DevicePolicyIdentityStrategy* identity_strategy)
+ : identity_strategy_(identity_strategy),
+ signed_settings_helper_(chromeos::SignedSettingsHelper::Get()),
+ starting_up_(true) {
}
DevicePolicyCache::DevicePolicyCache(
+ DevicePolicyIdentityStrategy* identity_strategy,
chromeos::SignedSettingsHelper* signed_settings_helper)
- : signed_settings_helper_(signed_settings_helper) {
+ : identity_strategy_(identity_strategy),
+ signed_settings_helper_(signed_settings_helper),
+ starting_up_(true) {
}
DevicePolicyCache::~DevicePolicyCache() {
@@ -34,13 +41,11 @@ DevicePolicyCache::~DevicePolicyCache() {
}
void DevicePolicyCache::Load() {
- // TODO(jkummerow): check if we're unmanaged; if so, set is_unmanaged_ = true
- // and return immediately.
-
signed_settings_helper_->StartRetrievePolicyOp(this);
}
void DevicePolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) {
+ DCHECK(!starting_up_);
set_last_policy_refresh_time(base::Time::NowFromSystemTime());
signed_settings_helper_->StartStorePolicyOp(policy, this);
}
@@ -54,23 +59,71 @@ void DevicePolicyCache::OnRetrievePolicyCompleted(
chromeos::SignedSettings::ReturnCode code,
const em::PolicyFetchResponse& policy) {
DCHECK(CalledOnValidThread());
- if (code != chromeos::SignedSettings::SUCCESS) {
- // TODO(jkummerow): We can't really do anything about this error, but
- // we may want to notify the user that something is wrong.
- return;
+ if (starting_up_) {
+ starting_up_ = false;
+ if (code == chromeos::SignedSettings::NOT_FOUND ||
+ code == chromeos::SignedSettings::KEY_UNAVAILABLE ||
+ !policy.has_policy_data()) {
+ InformNotifier(CloudPolicySubsystem::UNENROLLED,
+ CloudPolicySubsystem::NO_DETAILS);
+ return;
+ }
+ em::PolicyData policy_data;
+ if (!policy_data.ParseFromString(policy.policy_data())) {
+ LOG(WARNING) << "Failed to parse PolicyData protobuf.";
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ return;
+ }
+ if (!policy_data.has_request_token() ||
+ policy_data.request_token().empty()) {
+ SetUnmanagedInternal(base::Time::NowFromSystemTime());
+ InformNotifier(CloudPolicySubsystem::UNMANAGED,
+ CloudPolicySubsystem::NO_DETAILS);
+ // TODO(jkummerow): Reminder: When we want to feed device-wide settings
+ // made by a local owner into this cache, we need to call
+ // SetPolicyInternal() here.
+ return;
+ }
+ if (!policy_data.has_username() || !policy_data.has_device_id()) {
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ return;
+ }
+ identity_strategy_->SetDeviceManagementCredentials(
+ policy_data.username(),
+ policy_data.device_id(),
+ policy_data.request_token());
+ SetPolicyInternal(policy, NULL, false);
+ } else { // In other words, starting_up_ == false.
+ if (code != chromeos::SignedSettings::SUCCESS) {
+ if (code == chromeos::SignedSettings::BAD_SIGNATURE) {
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::SIGNATURE_MISMATCH);
+ } else {
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ }
+ return;
+ }
+ SetPolicyInternal(policy, NULL, false);
}
- SetPolicyInternal(policy, NULL, false);
}
void DevicePolicyCache::OnStorePolicyCompleted(
chromeos::SignedSettings::ReturnCode code) {
DCHECK(CalledOnValidThread());
if (code != chromeos::SignedSettings::SUCCESS) {
- // TODO(jkummerow): We can't really do anything about this error, but
- // we may want to notify the user that something is wrong.
+ if (code == chromeos::SignedSettings::BAD_SIGNATURE) {
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::SIGNATURE_MISMATCH);
+ } else {
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ }
return;
}
- Load();
+ signed_settings_helper_->StartRetrievePolicyOp(this);
}
bool DevicePolicyCache::DecodePolicyData(const em::PolicyData& policy_data,
diff --git a/chrome/browser/policy/device_policy_cache.h b/chrome/browser/policy/device_policy_cache.h
index f6a9514..021cffc 100644
--- a/chrome/browser/policy/device_policy_cache.h
+++ b/chrome/browser/policy/device_policy_cache.h
@@ -15,6 +15,7 @@
namespace policy {
+class DevicePolicyIdentityStrategy;
class PolicyMap;
namespace em = enterprise_management;
@@ -24,7 +25,7 @@ namespace em = enterprise_management;
class DevicePolicyCache : public CloudPolicyCacheBase,
public chromeos::SignedSettingsHelper::Callback {
public:
- DevicePolicyCache();
+ explicit DevicePolicyCache(DevicePolicyIdentityStrategy* identity_strategy);
virtual ~DevicePolicyCache();
// CloudPolicyCacheBase implementation:
@@ -44,7 +45,8 @@ class DevicePolicyCache : public CloudPolicyCacheBase,
// Alternate c'tor allowing tests to mock out the SignedSettingsHelper
// singleton.
- explicit DevicePolicyCache(
+ DevicePolicyCache(
+ DevicePolicyIdentityStrategy* identity_strategy,
chromeos::SignedSettingsHelper* signed_settings_helper);
// CloudPolicyCacheBase implementation:
@@ -56,8 +58,12 @@ class DevicePolicyCache : public CloudPolicyCacheBase,
PolicyMap* mandatory,
PolicyMap* recommended);
+ DevicePolicyIdentityStrategy* identity_strategy_;
+
chromeos::SignedSettingsHelper* signed_settings_helper_;
+ bool starting_up_;
+
DISALLOW_COPY_AND_ASSIGN(DevicePolicyCache);
};
diff --git a/chrome/browser/policy/device_policy_cache_unittest.cc b/chrome/browser/policy/device_policy_cache_unittest.cc
index 79c2c82..4228470 100644
--- a/chrome/browser/policy/device_policy_cache_unittest.cc
+++ b/chrome/browser/policy/device_policy_cache_unittest.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/policy/device_policy_cache.h"
+#include "chrome/browser/policy/device_policy_identity_strategy.h"
#include "policy/configuration_policy_type.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -77,7 +78,8 @@ class DevicePolicyCacheTest : public testing::Test {
}
virtual void SetUp() {
- cache_.reset(new DevicePolicyCache(&signed_settings_helper_));
+ cache_.reset(new DevicePolicyCache(&identity_strategy_,
+ &signed_settings_helper_));
}
virtual void TearDown() {
@@ -90,6 +92,7 @@ class DevicePolicyCacheTest : public testing::Test {
}
scoped_ptr<DevicePolicyCache> cache_;
+ DevicePolicyIdentityStrategy identity_strategy_;
MockSignedSettingsHelper signed_settings_helper_;
private:
diff --git a/chrome/browser/policy/device_policy_identity_strategy.cc b/chrome/browser/policy/device_policy_identity_strategy.cc
index 82b5303..010ca90 100644
--- a/chrome/browser/policy/device_policy_identity_strategy.cc
+++ b/chrome/browser/policy/device_policy_identity_strategy.cc
@@ -18,105 +18,12 @@
namespace policy {
-// Responsible for querying device ownership on the FILE thread.
-class DevicePolicyIdentityStrategy::OwnershipChecker
- : public base::RefCountedThreadSafe<
- DevicePolicyIdentityStrategy::OwnershipChecker> {
- public:
- explicit OwnershipChecker(
- const base::WeakPtr<DevicePolicyIdentityStrategy>& strategy)
- : strategy_(strategy) {}
-
- // Initiates a query on the file thread to check if the currently logged in
- // user is the owner.
- void CheckCurrentUserIsOwner();
-
- private:
- void CheckOnFileThread();
- void CallbackOnUIThread(bool current_user_is_owner);
-
- private:
- friend class base::RefCountedThreadSafe<OwnershipChecker>;
-
- ~OwnershipChecker() {}
-
- // The object to be called back with the result.
- base::WeakPtr<DevicePolicyIdentityStrategy> strategy_;
-
- DISALLOW_COPY_AND_ASSIGN(OwnershipChecker);
-};
-
-void DevicePolicyIdentityStrategy::OwnershipChecker::CheckCurrentUserIsOwner() {
- if (!strategy_.get())
- return;
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- NewRunnableMethod(
- this,
- &DevicePolicyIdentityStrategy::OwnershipChecker::CheckOnFileThread));
-}
-
-void DevicePolicyIdentityStrategy::OwnershipChecker::CheckOnFileThread() {
- bool current_user_is_owner =
- chromeos::OwnershipService::GetSharedInstance()->CurrentUserIsOwner();
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- NewRunnableMethod(
- this,
- &DevicePolicyIdentityStrategy::OwnershipChecker::CallbackOnUIThread,
- current_user_is_owner));
-}
-
-void DevicePolicyIdentityStrategy::OwnershipChecker::CallbackOnUIThread(
- bool current_user_is_owner) {
- if (strategy_.get()) {
- strategy_->OnOwnershipInformationAvailable(current_user_is_owner);
- strategy_.reset();
- }
-}
-
-DevicePolicyIdentityStrategy::DevicePolicyIdentityStrategy()
- : current_user_is_owner_(false),
- ownership_checker_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
- registrar_.Add(this,
- NotificationType::TOKEN_AVAILABLE,
- NotificationService::AllSources());
- registrar_.Add(this,
- NotificationType::LOGIN_USER_CHANGED,
- NotificationService::AllSources());
- registrar_.Add(this,
- NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
- NotificationService::AllSources());
-
- // TODO(mnissler): Figure out how to read the machine id.
- machine_id_ = "dummy-cros-machine-ID";
+DevicePolicyIdentityStrategy::DevicePolicyIdentityStrategy() {
}
DevicePolicyIdentityStrategy::~DevicePolicyIdentityStrategy() {
}
-void DevicePolicyIdentityStrategy::OnOwnershipInformationAvailable(
- bool current_user_is_owner) {
- current_user_is_owner_ = current_user_is_owner;
- CheckAndTriggerFetch();
-}
-
-void DevicePolicyIdentityStrategy::CheckOwnershipAndTriggerFetch() {
- // TODO(gfeher): Avoid firing a new query if the answer is already known.
-
- // Cancel any pending queries.
- weak_ptr_factory_.InvalidateWeakPtrs();
- // Set to false until we know that the current user is the owner.
- current_user_is_owner_ = false;
- // Issue a new query.
- ownership_checker_ = new OwnershipChecker(weak_ptr_factory_.GetWeakPtr());
- // The following will call back to CheckTriggerFetch().
- ownership_checker_->CheckCurrentUserIsOwner();
-}
-
std::string DevicePolicyIdentityStrategy::GetDeviceToken() {
return device_token_;
}
@@ -138,27 +45,35 @@ std::string DevicePolicyIdentityStrategy::GetPolicyType() {
return kChromeDevicePolicyType;
}
+void DevicePolicyIdentityStrategy::SetAuthCredentials(
+ const std::string& username,
+ const std::string& auth_token,
+ const std::string& machine_id) {
+ username_ = username;
+ auth_token_ = auth_token;
+ machine_id_ = machine_id;
+ device_id_ = guid::GenerateGUID();
+ NotifyAuthChanged();
+}
+
+void DevicePolicyIdentityStrategy::SetDeviceManagementCredentials(
+ const std::string& owner_email,
+ const std::string& device_id,
+ const std::string& device_token) {
+ username_ = owner_email;
+ device_id_ = device_id;
+ device_token_ = device_token;
+ NotifyDeviceTokenChanged();
+}
+
bool DevicePolicyIdentityStrategy::GetCredentials(std::string* username,
std::string* auth_token) {
// Need to know the machine id.
if (machine_id_.empty())
return false;
- // Only fetch credentials (and, subsequently, token/policy) when the owner
- // is logged in.
- if (!current_user_is_owner_)
- return false;
-
- // We need to know about the profile of the logged in user.
- Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
- if (!profile) {
- NOTREACHED() << "Current user profile inaccessible";
- return false;
- }
-
- *username = chromeos::UserManager::Get()->logged_in_user().email();
- *auth_token = profile->GetTokenService()->GetTokenForService(
- GaiaConstants::kDeviceManagementService);
+ *username = username_;
+ *auth_token = auth_token_;
return !username->empty() && !auth_token->empty();
}
@@ -171,30 +86,4 @@ void DevicePolicyIdentityStrategy::OnDeviceTokenAvailable(
NotifyDeviceTokenChanged();
}
-void DevicePolicyIdentityStrategy::CheckAndTriggerFetch() {
- std::string username;
- std::string auth_token;
- if (GetCredentials(&username, &auth_token)) {
- device_id_ = guid::GenerateGUID();
- NotifyAuthChanged();
- }
-}
-
-void DevicePolicyIdentityStrategy::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (type == NotificationType::TOKEN_AVAILABLE) {
- const TokenService::TokenAvailableDetails* token_details =
- Details<const TokenService::TokenAvailableDetails>(details).ptr();
- if (token_details->service() == GaiaConstants::kDeviceManagementService)
- CheckOwnershipAndTriggerFetch();
- } else if (type == NotificationType::LOGIN_USER_CHANGED) {
- CheckOwnershipAndTriggerFetch();
- } else if (type == NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
- CheckOwnershipAndTriggerFetch();
- } else {
- NOTREACHED();
- }
-}
-
} // namespace policy
diff --git a/chrome/browser/policy/device_policy_identity_strategy.h b/chrome/browser/policy/device_policy_identity_strategy.h
index 365ed0f..2c172c3 100644
--- a/chrome/browser/policy/device_policy_identity_strategy.h
+++ b/chrome/browser/policy/device_policy_identity_strategy.h
@@ -8,51 +8,46 @@
#include <string>
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
+#include "base/compiler_specific.h"
#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
-#include "content/common/notification_observer.h"
-#include "content/common/notification_registrar.h"
class TokenService;
namespace policy {
// DM token provider that stores the token in CrOS signed settings.
-class DevicePolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
- public NotificationObserver {
+class DevicePolicyIdentityStrategy : public CloudPolicyIdentityStrategy {
public:
DevicePolicyIdentityStrategy();
virtual ~DevicePolicyIdentityStrategy();
- // Called by DevicePolicyIdentityStrategy::OwnershipChecker:
- virtual void OnOwnershipInformationAvailable(bool current_user_is_owner);
+ // Sets (GAIA) auth credentials of the owner of the device during device
+ // enrollment. This automatically triggers fetching a DMToken that can
+ // be used for future authentication with DMServer.
+ void SetAuthCredentials(const std::string& username,
+ const std::string& auth_token,
+ const std::string& machine_id);
+
+ // Sets the device's credentials when they have been read from disk after
+ // a reboot.
+ void SetDeviceManagementCredentials(const std::string& owner_email,
+ const std::string& device_id,
+ const std::string& device_token);
// CloudPolicyIdentityStrategy implementation:
- virtual std::string GetDeviceToken();
- virtual std::string GetDeviceID();
- virtual std::string GetMachineID();
- virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType();
- virtual std::string GetPolicyType();
+ virtual std::string GetDeviceToken() OVERRIDE;
+ virtual std::string GetDeviceID() OVERRIDE;
+ virtual std::string GetMachineID() OVERRIDE;
+ virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType() OVERRIDE;
+ virtual std::string GetPolicyType() OVERRIDE;
virtual bool GetCredentials(std::string* username,
- std::string* auth_token);
- virtual void OnDeviceTokenAvailable(const std::string& token);
+ std::string* auth_token) OVERRIDE;
+ virtual void OnDeviceTokenAvailable(const std::string& token) OVERRIDE;
private:
- class OwnershipChecker;
-
- // Recheck whether all parameters are available and if so, trigger a
- // credentials changed notification.
- void CheckAndTriggerFetch();
-
- // Updates the ownership information and then passes control to
- // |CheckAndTriggerFetch|.
- void CheckOwnershipAndTriggerFetch();
-
- // NotificationObserver method overrides:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
+ // The e-mail and auth token of the device owner. Set by |SetCredentials()|.
+ std::string username_;
+ std::string auth_token_;
// The machine identifier.
std::string machine_id_;
@@ -65,19 +60,6 @@ class DevicePolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
// Current token. Empty if not available.
std::string device_token_;
- // Whether the currently logged in user is the device's owner. This variable
- // is owned by the UI thread but updated from the FILE thread. Therefore
- // after an owner login it will take some time before it turns to true.
- bool current_user_is_owner_;
-
- // Registers the provider for notification of successful Gaia logins.
- NotificationRegistrar registrar_;
-
- scoped_refptr<OwnershipChecker> ownership_checker_;
-
- // Allows to construct weak ptrs.
- base::WeakPtrFactory<DevicePolicyIdentityStrategy> weak_ptr_factory_;
-
DISALLOW_COPY_AND_ASSIGN(DevicePolicyIdentityStrategy);
};
diff --git a/chrome/browser/policy/device_token_fetcher.cc b/chrome/browser/policy/device_token_fetcher.cc
index 3db1334..c1739a8 100644
--- a/chrome/browser/policy/device_token_fetcher.cc
+++ b/chrome/browser/policy/device_token_fetcher.cc
@@ -29,10 +29,12 @@ namespace em = enterprise_management;
DeviceTokenFetcher::DeviceTokenFetcher(
DeviceManagementService* service,
- CloudPolicyCacheBase* cache)
+ CloudPolicyCacheBase* cache,
+ PolicyNotifier* notifier)
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
Initialize(service,
cache,
+ notifier,
kTokenFetchErrorDelayMilliseconds,
kTokenFetchErrorMaxDelayMilliseconds,
kUnmanagedDeviceRefreshRateMilliseconds);
@@ -41,12 +43,14 @@ DeviceTokenFetcher::DeviceTokenFetcher(
DeviceTokenFetcher::DeviceTokenFetcher(
DeviceManagementService* service,
CloudPolicyCacheBase* cache,
+ PolicyNotifier* notifier,
int64 token_fetch_error_delay_ms,
int64 token_fetch_error_max_delay_ms,
int64 unmanaged_device_refresh_rate_ms)
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
Initialize(service,
cache,
+ notifier,
token_fetch_error_delay_ms,
token_fetch_error_max_delay_ms,
unmanaged_device_refresh_rate_ms);
@@ -98,6 +102,14 @@ const std::string& DeviceTokenFetcher::GetDeviceToken() {
return device_token_;
}
+void DeviceTokenFetcher::StopAutoRetry() {
+ CancelRetryTask();
+ backend_.reset();
+ device_token_.clear();
+ auth_token_.clear();
+ device_id_.clear();
+}
+
void DeviceTokenFetcher::AddObserver(DeviceTokenFetcher::Observer* observer) {
observer_list_.AddObserver(observer);
}
@@ -132,7 +144,7 @@ void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
case DeviceManagementBackend::kErrorServiceManagementTokenInvalid:
// Most probably the GAIA auth cookie has expired. We can not do anything
// until the user logs-in again.
- SetState(STATE_INACTIVE);
+ SetState(STATE_BAD_AUTH);
break;
default:
SetState(STATE_ERROR);
@@ -141,11 +153,13 @@ void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
CloudPolicyCacheBase* cache,
+ PolicyNotifier* notifier,
int64 token_fetch_error_delay_ms,
int64 token_fetch_error_max_delay_ms,
int64 unmanaged_device_refresh_rate_ms) {
service_ = service;
cache_ = cache;
+ notifier_ = notifier;
token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
token_fetch_error_max_delay_ms_ = token_fetch_error_max_delay_ms;
effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
@@ -168,13 +182,22 @@ void DeviceTokenFetcher::SetState(FetcherState state) {
device_token_.clear();
auth_token_.clear();
device_id_.clear();
+ notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
+ CloudPolicySubsystem::NO_DETAILS,
+ PolicyNotifier::TOKEN_FETCHER);
break;
case STATE_TOKEN_AVAILABLE:
FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenAvailable());
+ notifier_->Inform(CloudPolicySubsystem::SUCCESS,
+ CloudPolicySubsystem::NO_DETAILS,
+ PolicyNotifier::TOKEN_FETCHER);
break;
case STATE_UNMANAGED:
delayed_work_at = cache_->last_policy_refresh_time() +
base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
+ notifier_->Inform(CloudPolicySubsystem::UNMANAGED,
+ CloudPolicySubsystem::NO_DETAILS,
+ PolicyNotifier::TOKEN_FETCHER);
break;
case STATE_TEMPORARY_ERROR:
delayed_work_at = base::Time::Now() +
@@ -183,12 +206,24 @@ void DeviceTokenFetcher::SetState(FetcherState state) {
effective_token_fetch_error_delay_ms_ =
std::min(effective_token_fetch_error_delay_ms_ * 2,
token_fetch_error_max_delay_ms_);
+ notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
+ CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
+ PolicyNotifier::TOKEN_FETCHER);
break;
case STATE_ERROR:
effective_token_fetch_error_delay_ms_ = token_fetch_error_max_delay_ms_;
delayed_work_at = base::Time::Now() +
base::TimeDelta::FromMilliseconds(
effective_token_fetch_error_delay_ms_);
+ notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
+ CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
+ PolicyNotifier::TOKEN_FETCHER);
+ break;
+ case STATE_BAD_AUTH:
+ // Can't do anything, need to wait for new credentials.
+ notifier_->Inform(CloudPolicySubsystem::BAD_GAIA_TOKEN,
+ CloudPolicySubsystem::NO_DETAILS,
+ PolicyNotifier::TOKEN_FETCHER);
break;
}
@@ -214,6 +249,7 @@ void DeviceTokenFetcher::ExecuteRetryTask() {
case STATE_UNMANAGED:
case STATE_ERROR:
case STATE_TEMPORARY_ERROR:
+ case STATE_BAD_AUTH:
FetchTokenInternal();
break;
}
diff --git a/chrome/browser/policy/device_token_fetcher.h b/chrome/browser/policy/device_token_fetcher.h
index e010de8..cd5ddee 100644
--- a/chrome/browser/policy/device_token_fetcher.h
+++ b/chrome/browser/policy/device_token_fetcher.h
@@ -12,6 +12,7 @@
#include "base/observer_list.h"
#include "base/task.h"
#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/policy_notifier.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
namespace policy {
@@ -38,10 +39,12 @@ class DeviceTokenFetcher
// |service| is used to talk to the device management service and |cache| is
// used to persist whether the device is unmanaged.
DeviceTokenFetcher(DeviceManagementService* service,
- CloudPolicyCacheBase* cache);
- // Version for tests that allows to set timing paramters.
+ CloudPolicyCacheBase* cache,
+ PolicyNotifier* notifier);
+ // Version for tests that allows to set timing parameters.
DeviceTokenFetcher(DeviceManagementService* service,
CloudPolicyCacheBase* cache,
+ PolicyNotifier* notifier,
int64 token_fetch_error_delay_ms,
int64 token_fetch_error_max_delay_ms,
int64 unmanaged_device_refresh_rate_ms);
@@ -60,6 +63,9 @@ class DeviceTokenFetcher
// Declared virtual so it can be overridden by mocks.
virtual const std::string& GetDeviceToken();
+ // Disables the auto-retry-on-error behavior of this token fetcher.
+ void StopAutoRetry();
+
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
@@ -88,12 +94,15 @@ class DeviceTokenFetcher
// Error, retry later.
STATE_ERROR,
// Temporary error. Retry sooner.
- STATE_TEMPORARY_ERROR
+ STATE_TEMPORARY_ERROR,
+ // Server rejected the auth token.
+ STATE_BAD_AUTH
};
// Common initialization helper.
void Initialize(DeviceManagementService* service,
CloudPolicyCacheBase* cache,
+ PolicyNotifier* notifier,
int64 token_fetch_error_delay_ms,
int64 token_fetch_error_max_delay_ms,
int64 unmanaged_device_refresh_rate_ms);
@@ -119,6 +128,8 @@ class DeviceTokenFetcher
// Reference to the cache. Used to persist and read unmanaged state.
CloudPolicyCacheBase* cache_;
+ PolicyNotifier* notifier_;
+
// Refresh parameters.
int64 token_fetch_error_delay_ms_;
int64 token_fetch_error_max_delay_ms_;
diff --git a/chrome/browser/policy/device_token_fetcher_unittest.cc b/chrome/browser/policy/device_token_fetcher_unittest.cc
index 2a7f9bc..2fb305e 100644
--- a/chrome/browser/policy/device_token_fetcher_unittest.cc
+++ b/chrome/browser/policy/device_token_fetcher_unittest.cc
@@ -11,6 +11,8 @@
#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/mock_device_management_backend.h"
+#include "chrome/browser/policy/mock_device_management_service.h"
+#include "chrome/browser/policy/policy_notifier.h"
#include "chrome/browser/policy/user_policy_cache.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/test/testing_profile.h"
@@ -36,67 +38,6 @@ class MockTokenAvailableObserver : public DeviceTokenFetcher::Observer {
DISALLOW_COPY_AND_ASSIGN(MockTokenAvailableObserver);
};
-class MockDeviceManagementService : public DeviceManagementService {
- public:
- MockDeviceManagementService()
- : DeviceManagementService(""),
- backend_(NULL) {}
- virtual ~MockDeviceManagementService() {}
-
- void set_backend(DeviceManagementBackend* backend) {
- backend_ = backend;
- }
- virtual DeviceManagementBackend* CreateBackend();
-
- private:
- DeviceManagementBackend* backend_; // weak
- DISALLOW_COPY_AND_ASSIGN(MockDeviceManagementService);
-};
-
-// This proxy class is used so that expectations can be defined for a single
-// persistant instance of DMBackend while the DeviceTokenFetcher under test
-// merrily creates and destroys proxies.
-class ProxyDeviceManagementBackend : public DeviceManagementBackend {
- public:
- explicit ProxyDeviceManagementBackend(DeviceManagementBackend* backend)
- : backend_(backend) {
- }
- virtual ~ProxyDeviceManagementBackend() {}
-
- virtual void ProcessRegisterRequest(
- const std::string& auth_token,
- const std::string& device_id,
- const em::DeviceRegisterRequest& request,
- DeviceRegisterResponseDelegate* delegate) {
- backend_->ProcessRegisterRequest(auth_token, device_id, request, delegate);
- }
- virtual void ProcessUnregisterRequest(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::DeviceUnregisterRequest& request,
- DeviceUnregisterResponseDelegate* delegate) {
- backend_->ProcessUnregisterRequest(device_management_token, device_id,
- request, delegate);
- }
- virtual void ProcessPolicyRequest(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::DevicePolicyRequest& request,
- DevicePolicyResponseDelegate* delegate) {
- backend_->ProcessPolicyRequest(device_management_token, device_id,
- request, delegate);
- }
-
- private:
- DeviceManagementBackend* backend_; // weak
- DISALLOW_COPY_AND_ASSIGN(ProxyDeviceManagementBackend);
-};
-
-DeviceManagementBackend*
- MockDeviceManagementService::CreateBackend() {
- return new ProxyDeviceManagementBackend(backend_);
-}
-
class DeviceTokenFetcherTest : public testing::Test {
protected:
DeviceTokenFetcherTest()
@@ -119,6 +60,7 @@ class DeviceTokenFetcherTest : public testing::Test {
MockDeviceManagementBackend backend_;
MockDeviceManagementService service_;
scoped_ptr<CloudPolicyCacheBase> cache_;
+ PolicyNotifier notifier_;
ScopedTempDir temp_user_data_dir_;
private:
@@ -130,7 +72,7 @@ TEST_F(DeviceTokenFetcherTest, FetchToken) {
testing::InSequence s;
EXPECT_CALL(backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedRegister());
- DeviceTokenFetcher fetcher(&service_, cache_.get());
+ DeviceTokenFetcher fetcher(&service_, cache_.get(), &notifier_);
MockTokenAvailableObserver observer;
EXPECT_CALL(observer, OnDeviceTokenAvailable());
fetcher.AddObserver(&observer);
@@ -162,7 +104,7 @@ TEST_F(DeviceTokenFetcherTest, RetryOnError) {
MockDeviceManagementBackendFailRegister(
DeviceManagementBackend::kErrorRequestFailed)).WillOnce(
MockDeviceManagementBackendSucceedRegister());
- DeviceTokenFetcher fetcher(&service_, cache_.get(), 0, 0, 0);
+ DeviceTokenFetcher fetcher(&service_, cache_.get(), &notifier_, 0, 0, 0);
MockTokenAvailableObserver observer;
EXPECT_CALL(observer, OnDeviceTokenAvailable());
fetcher.AddObserver(&observer);
@@ -179,7 +121,7 @@ TEST_F(DeviceTokenFetcherTest, UnmanagedDevice) {
MockDeviceManagementBackendFailRegister(
DeviceManagementBackend::kErrorServiceManagementNotSupported));
EXPECT_FALSE(cache_->is_unmanaged());
- DeviceTokenFetcher fetcher(&service_, cache_.get());
+ DeviceTokenFetcher fetcher(&service_, cache_.get(), &notifier_);
MockTokenAvailableObserver observer;
EXPECT_CALL(observer, OnDeviceTokenAvailable()).Times(0);
fetcher.AddObserver(&observer);
diff --git a/chrome/browser/policy/mock_device_management_backend.h b/chrome/browser/policy/mock_device_management_backend.h
index 8134e49..4828fdb 100644
--- a/chrome/browser/policy/mock_device_management_backend.h
+++ b/chrome/browser/policy/mock_device_management_backend.h
@@ -62,20 +62,6 @@ ACTION(MockDeviceManagementBackendSucceedRegister) {
arg3->HandleRegisterResponse(response);
}
-ACTION_P2(MockDeviceManagementBackendSucceedBooleanPolicy, name, value) {
- em::DevicePolicyResponse response;
- em::DevicePolicySetting* setting = response.add_setting();
- setting->set_policy_key(kChromeDevicePolicySettingKey);
- setting->set_watermark("fresh");
- em::GenericSetting* policy_value = setting->mutable_policy_value();
- em::GenericNamedValue* named_value = policy_value->add_named_value();
- named_value->set_name(name);
- named_value->mutable_value()->set_value_type(
- em::GenericValue::VALUE_TYPE_BOOL);
- named_value->mutable_value()->set_bool_value(value);
- arg3->HandlePolicyResponse(response);
-}
-
ACTION(MockDeviceManagementBackendSucceedSpdyCloudPolicy) {
em::PolicyData signed_response;
em::CloudPolicySettings settings;
diff --git a/chrome/browser/policy/mock_device_management_service.cc b/chrome/browser/policy/mock_device_management_service.cc
new file mode 100644
index 0000000..f524644
--- /dev/null
+++ b/chrome/browser/policy/mock_device_management_service.cc
@@ -0,0 +1,50 @@
+// 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/policy/mock_device_management_service.h"
+
+namespace policy {
+
+ProxyDeviceManagementBackend::ProxyDeviceManagementBackend(
+ DeviceManagementBackend* backend)
+ : backend_(backend) {
+}
+ProxyDeviceManagementBackend::~ProxyDeviceManagementBackend() {}
+
+void ProxyDeviceManagementBackend::ProcessRegisterRequest(
+ const std::string& auth_token,
+ const std::string& device_id,
+ const em::DeviceRegisterRequest& request,
+ DeviceRegisterResponseDelegate* delegate) {
+ backend_->ProcessRegisterRequest(auth_token, device_id, request, delegate);
+}
+
+void ProxyDeviceManagementBackend::ProcessUnregisterRequest(
+ const std::string& device_management_token,
+ const std::string& device_id,
+ const em::DeviceUnregisterRequest& request,
+ DeviceUnregisterResponseDelegate* delegate) {
+ backend_->ProcessUnregisterRequest(device_management_token, device_id,
+ request, delegate);
+}
+void ProxyDeviceManagementBackend::ProcessPolicyRequest(
+ const std::string& device_management_token,
+ const std::string& device_id,
+ const em::DevicePolicyRequest& request,
+ DevicePolicyResponseDelegate* delegate) {
+ backend_->ProcessPolicyRequest(device_management_token, device_id,
+ request, delegate);
+}
+
+MockDeviceManagementService::MockDeviceManagementService()
+ : DeviceManagementService(""),
+ backend_(NULL) {}
+
+MockDeviceManagementService::~MockDeviceManagementService() {}
+
+DeviceManagementBackend* MockDeviceManagementService::CreateBackend() {
+ return new ProxyDeviceManagementBackend(backend_);
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/mock_device_management_service.h b/chrome/browser/policy/mock_device_management_service.h
new file mode 100644
index 0000000..e481f1e
--- /dev/null
+++ b/chrome/browser/policy/mock_device_management_service.h
@@ -0,0 +1,66 @@
+// 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.
+
+#ifndef CHROME_BROWSER_POLICY_MOCK_DEVICE_MANAGEMENT_SERVICE_H_
+#define CHROME_BROWSER_POLICY_MOCK_DEVICE_MANAGEMENT_SERVICE_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/device_management_service.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+
+namespace policy {
+
+// This proxy class is used so that expectations can be defined for a single
+// persistent instance of DMBackend while the DeviceTokenFetcher under test
+// merrily creates and destroys proxies.
+class ProxyDeviceManagementBackend : public DeviceManagementBackend {
+ public:
+ explicit ProxyDeviceManagementBackend(DeviceManagementBackend* backend);
+ virtual ~ProxyDeviceManagementBackend();
+
+ virtual void ProcessRegisterRequest(
+ const std::string& auth_token,
+ const std::string& device_id,
+ const em::DeviceRegisterRequest& request,
+ DeviceRegisterResponseDelegate* delegate);
+
+ virtual void ProcessUnregisterRequest(
+ const std::string& device_management_token,
+ const std::string& device_id,
+ const em::DeviceUnregisterRequest& request,
+ DeviceUnregisterResponseDelegate* delegate);
+
+ virtual void ProcessPolicyRequest(
+ const std::string& device_management_token,
+ const std::string& device_id,
+ const em::DevicePolicyRequest& request,
+ DevicePolicyResponseDelegate* delegate);
+
+ private:
+ DeviceManagementBackend* backend_; // weak
+ DISALLOW_COPY_AND_ASSIGN(ProxyDeviceManagementBackend);
+};
+
+class MockDeviceManagementService : public DeviceManagementService {
+ public:
+ MockDeviceManagementService();
+ virtual ~MockDeviceManagementService();
+
+ void set_backend(DeviceManagementBackend* backend) {
+ backend_ = backend;
+ }
+
+ virtual DeviceManagementBackend* CreateBackend();
+
+ private:
+ DeviceManagementBackend* backend_; // weak
+ DISALLOW_COPY_AND_ASSIGN(MockDeviceManagementService);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_MOCK_DEVICE_MANAGEMENT_SERVICE_H_
diff --git a/chrome/browser/policy/policy_notifier.cc b/chrome/browser/policy/policy_notifier.cc
new file mode 100644
index 0000000..23829de
--- /dev/null
+++ b/chrome/browser/policy/policy_notifier.cc
@@ -0,0 +1,69 @@
+// 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/policy/policy_notifier.h"
+
+namespace policy {
+
+void PolicyNotifier::AddObserver(CloudPolicySubsystem::Observer* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void PolicyNotifier::RemoveObserver(CloudPolicySubsystem::Observer* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+PolicyNotifier::PolicyNotifier()
+ : state_(CloudPolicySubsystem::UNENROLLED),
+ error_details_(CloudPolicySubsystem::NO_DETAILS) {
+ for (int i = 0; i < NUM_SOURCES; ++i) {
+ component_states_[i] = CloudPolicySubsystem::UNENROLLED;
+ component_error_details_[i] = CloudPolicySubsystem::NO_DETAILS;
+ }
+}
+
+PolicyNotifier::~PolicyNotifier() {
+}
+
+void PolicyNotifier::Inform(PolicySubsystemState state,
+ ErrorDetails error_details,
+ StatusSource source) {
+ component_states_[source] = state;
+ component_error_details_[source] = error_details;
+ RecomputeState();
+}
+
+void PolicyNotifier::RecomputeState() {
+ // Define shortcuts.
+ PolicySubsystemState* s = component_states_;
+ ErrorDetails* e = component_error_details_;
+
+ // Compute overall state. General idea: If any component knows we're
+ // unmanaged, set that as global state. Otherwise, ask components in the
+ // order they normally do work in. If anyone reports 'SUCCESS' or 'UNENROLLED'
+ // (which can also be read as 'undefined/unknown', ask the next component.
+ if (s[TOKEN_FETCHER] == CloudPolicySubsystem::UNMANAGED ||
+ s[POLICY_CONTROLLER] == CloudPolicySubsystem::UNMANAGED ||
+ s[POLICY_CACHE] == CloudPolicySubsystem::UNMANAGED) {
+ state_ = CloudPolicySubsystem::UNMANAGED;
+ error_details_ = CloudPolicySubsystem::NO_DETAILS;
+ } else if (s[TOKEN_FETCHER] == CloudPolicySubsystem::NETWORK_ERROR) {
+ state_ = s[TOKEN_FETCHER];
+ error_details_ = e[TOKEN_FETCHER];
+ } else if (s[TOKEN_FETCHER] == CloudPolicySubsystem::BAD_GAIA_TOKEN) {
+ state_ = s[TOKEN_FETCHER];
+ error_details_ = e[TOKEN_FETCHER];
+ } else if (s[POLICY_CONTROLLER] == CloudPolicySubsystem::NETWORK_ERROR) {
+ state_ = s[POLICY_CONTROLLER];
+ error_details_ = e[TOKEN_FETCHER];
+ } else {
+ state_ = s[POLICY_CACHE];
+ error_details_ = e[POLICY_CACHE];
+ }
+
+ FOR_EACH_OBSERVER(CloudPolicySubsystem::Observer, observer_list_,
+ OnPolicyStateChanged(state_, error_details_));
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/policy_notifier.h b/chrome/browser/policy/policy_notifier.h
new file mode 100644
index 0000000..a0e1062
--- /dev/null
+++ b/chrome/browser/policy/policy_notifier.h
@@ -0,0 +1,69 @@
+// 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.
+
+#ifndef CHROME_BROWSER_POLICY_POLICY_NOTIFIER_H_
+#define CHROME_BROWSER_POLICY_POLICY_NOTIFIER_H_
+#pragma once
+
+#include "base/observer_list.h"
+#include "chrome/browser/policy/cloud_policy_subsystem.h"
+
+namespace policy {
+
+// Keeps track of the state of the policy subsystem components as far as it's
+// relevant to the outside world. Is informed by components about status
+// changes (failures and successes), determines the overall state and
+// communicates it.
+class PolicyNotifier {
+ public:
+ typedef CloudPolicySubsystem::PolicySubsystemState PolicySubsystemState;
+ typedef CloudPolicySubsystem::ErrorDetails ErrorDetails;
+
+ enum StatusSource {
+ TOKEN_FETCHER,
+ POLICY_CONTROLLER,
+ POLICY_CACHE,
+ NUM_SOURCES // This must be the last element in the enum.
+ };
+
+ PolicyNotifier();
+ ~PolicyNotifier();
+
+ // Called by components of the policy subsystem. Determines the new overall
+ // state and triggers observer notifications as necessary.
+ void Inform(PolicySubsystemState state,
+ ErrorDetails error_details,
+ StatusSource source);
+
+ CloudPolicySubsystem::PolicySubsystemState state() const {
+ return state_;
+ }
+
+ CloudPolicySubsystem::ErrorDetails error_details() const {
+ return error_details_;
+ }
+
+ private:
+ friend class CloudPolicyController;
+ friend class CloudPolicySubsystem::ObserverRegistrar;
+
+ void AddObserver(CloudPolicySubsystem::Observer* observer);
+ void RemoveObserver(CloudPolicySubsystem::Observer* observer);
+
+ void RecomputeState();
+
+ PolicySubsystemState state_;
+ ErrorDetails error_details_;
+
+ PolicySubsystemState component_states_[NUM_SOURCES];
+ ErrorDetails component_error_details_[NUM_SOURCES];
+
+ ObserverList<CloudPolicySubsystem::Observer, true> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyNotifier);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_POLICY_NOTIFIER_H_
diff --git a/chrome/browser/policy/proto/device_management_backend.proto b/chrome/browser/policy/proto/device_management_backend.proto
index cf6b76b..4b45f7b 100644
--- a/chrome/browser/policy/proto/device_management_backend.proto
+++ b/chrome/browser/policy/proto/device_management_backend.proto
@@ -204,6 +204,14 @@ message PolicyData {
// was used to sign this response. Numbering should start at 1 and be
// increased by 1 at each key rotation.)
optional int32 public_key_version = 6;
+
+ // The user this policy is intended for. In case of device policy, the name
+ // of the owner (who registered the device).
+ optional string username = 7;
+
+ // In this field the DMServer should echo back the "deviceid" HTTP parameter
+ // from the request.
+ optional string device_id = 8;
}
message PolicyFetchResponse {
diff --git a/chrome/browser/policy/user_policy_identity_strategy.cc b/chrome/browser/policy/user_policy_identity_strategy.cc
index d569cd5..28bce10 100644
--- a/chrome/browser/policy/user_policy_identity_strategy.cc
+++ b/chrome/browser/policy/user_policy_identity_strategy.cc
@@ -178,7 +178,6 @@ std::string UserPolicyIdentityStrategy::GetPolicyType() {
return kChromeUserPolicyType;
}
-
bool UserPolicyIdentityStrategy::GetCredentials(std::string* username,
std::string* auth_token) {
*username = GetCurrentUser();
diff --git a/chrome/browser/policy/user_policy_identity_strategy.h b/chrome/browser/policy/user_policy_identity_strategy.h
index 5c32c22..7887ade 100644
--- a/chrome/browser/policy/user_policy_identity_strategy.h
+++ b/chrome/browser/policy/user_policy_identity_strategy.h
@@ -31,15 +31,14 @@ class UserPolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
virtual ~UserPolicyIdentityStrategy();
// CloudPolicyIdentityStrategy implementation:
- virtual std::string GetDeviceToken();
- virtual std::string GetDeviceID();
- virtual std::string GetMachineID();
- virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType();
- virtual std::string GetPolicyType();
-
+ virtual std::string GetDeviceToken() OVERRIDE;
+ virtual std::string GetDeviceID() OVERRIDE;
+ virtual std::string GetMachineID() OVERRIDE;
+ virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType() OVERRIDE;
+ virtual std::string GetPolicyType() OVERRIDE;
virtual bool GetCredentials(std::string* username,
- std::string* auth_token);
- virtual void OnDeviceTokenAvailable(const std::string& token);
+ std::string* auth_token) OVERRIDE;
+ virtual void OnDeviceTokenAvailable(const std::string& token) OVERRIDE;
private:
class TokenCache;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 26c9e2c..f7e135d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1529,6 +1529,8 @@
'browser/policy/file_based_policy_provider.h',
'browser/policy/managed_prefs_banner_base.cc',
'browser/policy/managed_prefs_banner_base.h',
+ 'browser/policy/policy_notifier.cc',
+ 'browser/policy/policy_notifier.h',
'browser/policy/policy_path_parser.h',
'browser/policy/policy_path_parser_mac.mm',
'browser/policy/policy_path_parser_posix.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ecfeb38..5bc01a4 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1451,6 +1451,8 @@
'browser/policy/mock_configuration_policy_store.h',
'browser/policy/mock_device_management_backend.cc',
'browser/policy/mock_device_management_backend.h',
+ 'browser/policy/mock_device_management_service.cc',
+ 'browser/policy/mock_device_management_service.h',
'browser/policy/policy_map_unittest.cc',
'browser/policy/policy_path_parser_unittest.cc',
'browser/policy/user_policy_cache_unittest.cc',