summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjkummerow@chromium.org <jkummerow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-23 09:54:25 +0000
committerjkummerow@chromium.org <jkummerow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-23 09:54:25 +0000
commit985655a307077dc9385fa4ed00bed3b8a64a805a (patch)
tree44b6ef8af1970224f900cf4da7fca9a35d414526 /chrome
parentd63c6fc43c28f3153b3c6b758796e7d15c44bdd0 (diff)
downloadchromium_src-985655a307077dc9385fa4ed00bed3b8a64a805a.zip
chromium_src-985655a307077dc9385fa4ed00bed3b8a64a805a.tar.gz
chromium_src-985655a307077dc9385fa4ed00bed3b8a64a805a.tar.bz2
Device policy infrastructure
This continues the work of http://codereview.chromium.org/6312121/. Description of that CL: This refactors the cloud policy-related code to support device policy that gets associated with the whole browser session. Device policy information will show up in g_browser_process->local_state(). Also, start supporting recommended policy from the cloud. BUG=chromium-os:11259, chromium-os:11257, chromium-os:11256 TEST=Enable device policy by passing --device-policy-cache-dir, claim a device and verify that policy gets downloaded. Review URL: http://codereview.chromium.org/6520008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75732 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_process.h5
-rw-r--r--chrome/browser/browser_process_impl.cc30
-rw-r--r--chrome/browser/browser_process_impl.h10
-rw-r--r--chrome/browser/policy/browser_policy_connector.cc179
-rw-r--r--chrome/browser/policy/browser_policy_connector.h77
-rw-r--r--chrome/browser/policy/cloud_policy_cache.cc188
-rw-r--r--chrome/browser/policy/cloud_policy_cache.h53
-rw-r--r--chrome/browser/policy/cloud_policy_cache_unittest.cc168
-rw-r--r--chrome/browser/policy/cloud_policy_controller.cc309
-rw-r--r--chrome/browser/policy/cloud_policy_controller.h138
-rw-r--r--chrome/browser/policy/cloud_policy_controller_unittest.cc258
-rw-r--r--chrome/browser/policy/cloud_policy_identity_strategy.h83
-rw-r--r--chrome/browser/policy/cloud_policy_subsystem.cc124
-rw-r--r--chrome/browser/policy/cloud_policy_subsystem.h73
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store.cc45
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store_unittest.cc2
-rw-r--r--chrome/browser/policy/configuration_policy_provider_keeper.cc100
-rw-r--r--chrome/browser/policy/configuration_policy_provider_keeper.h46
-rw-r--r--chrome/browser/policy/device_management_policy_provider.cc416
-rw-r--r--chrome/browser/policy/device_management_policy_provider.h174
-rw-r--r--chrome/browser/policy/device_management_policy_provider_unittest.cc382
-rw-r--r--chrome/browser/policy/device_management_service.h3
-rw-r--r--chrome/browser/policy/device_policy_identity_strategy.cc114
-rw-r--r--chrome/browser/policy/device_policy_identity_strategy.h62
-rw-r--r--chrome/browser/policy/device_token_fetcher.cc396
-rw-r--r--chrome/browser/policy/device_token_fetcher.h213
-rw-r--r--chrome/browser/policy/device_token_fetcher_unittest.cc305
-rw-r--r--chrome/browser/policy/profile_policy_connector.cc100
-rw-r--r--chrome/browser/policy/profile_policy_connector.h56
-rw-r--r--chrome/browser/policy/profile_policy_context.cc96
-rw-r--r--chrome/browser/policy/profile_policy_context.h70
-rw-r--r--chrome/browser/policy/user_policy_identity_strategy.cc236
-rw-r--r--chrome/browser/policy/user_policy_identity_strategy.h81
-rw-r--r--chrome/browser/prefs/browser_prefs.cc6
-rw-r--r--chrome/browser/prefs/pref_member.h7
-rw-r--r--chrome/browser/profiles/profile.cc2
-rw-r--r--chrome/browser/profiles/profile.h6
-rw-r--r--chrome/browser/profiles/profile_impl.cc16
-rw-r--r--chrome/browser/profiles/profile_impl.h4
-rw-r--r--chrome/chrome_browser.gypi21
-rw-r--r--chrome/chrome_tests.gypi4
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h2
-rw-r--r--chrome/common/pref_names.cc12
-rw-r--r--chrome/common/pref_names.h4
-rw-r--r--chrome/test/testing_browser_process.cc20
-rw-r--r--chrome/test/testing_browser_process.h9
-rw-r--r--chrome/test/testing_device_token_fetcher.cc45
-rw-r--r--chrome/test/testing_device_token_fetcher.h46
-rw-r--r--chrome/test/testing_profile.cc2
-rw-r--r--chrome/test/testing_profile.h2
51 files changed, 2582 insertions, 2222 deletions
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index 5c7d33d..3dbd8e6 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -52,7 +52,7 @@ class PrintPreviewTabController;
}
namespace policy {
-class ConfigurationPolicyProviderKeeper;
+class BrowserPolicyConnector;
}
namespace ui {
@@ -119,8 +119,7 @@ class BrowserProcess {
// Returns the thread that is used for health check of all browser threads.
virtual WatchDogThread* watchdog_thread() = 0;
- virtual policy::ConfigurationPolicyProviderKeeper*
- configuration_policy_provider_keeper() = 0;
+ virtual policy::BrowserPolicyConnector* browser_policy_connector() = 0;
virtual IconManager* icon_manager() = 0;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 780169a..0984234 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -9,10 +9,10 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
+#include "base/synchronization/waitable_event.h"
#include "base/task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
-#include "base/synchronization/waitable_event.h"
#include "chrome/browser/automation/automation_provider_list.h"
#include "chrome/browser/browser_child_process_host.h"
#include "chrome/browser/browser_list.h"
@@ -40,7 +40,7 @@
#include "chrome/browser/plugin_data_remover.h"
#include "chrome/browser/plugin_service.h"
#include "chrome/browser/plugin_updater.h"
-#include "chrome/browser/policy/configuration_policy_provider_keeper.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/print_preview_tab_controller.h"
@@ -55,13 +55,13 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/extensions/extension_l10n_util.h"
+#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/json_pref_store.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
#include "chrome/common/switch_utils.h"
+#include "chrome/common/url_constants.h"
#include "chrome/installer/util/google_update_constants.h"
#include "ipc/ipc_logging.h"
#include "ui/base/clipboard/clipboard.h"
@@ -104,7 +104,7 @@ BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line)
created_icon_manager_(false),
created_devtools_manager_(false),
created_sidebar_manager_(false),
- created_configuration_policy_provider_keeper_(false),
+ created_browser_policy_connector_(false),
created_notification_ui_manager_(false),
created_safe_browsing_detection_service_(false),
module_ref_count_(0),
@@ -189,9 +189,9 @@ BrowserProcessImpl::~BrowserProcessImpl() {
resource_dispatcher_host()->Shutdown();
}
- // The policy providers managed by |configuration_policy_provider_keeper_|
- // need to shut down while the file thread is still alive.
- configuration_policy_provider_keeper_.reset();
+ // The policy providers managed by |browser_policy_connector_| need to shut
+ // down while the IO and FILE threads are still alive.
+ browser_policy_connector_.reset();
#if defined(USE_X11)
// The IO thread must outlive the BACKGROUND_X11 thread.
@@ -443,16 +443,14 @@ NotificationUIManager* BrowserProcessImpl::notification_ui_manager() {
return notification_ui_manager_.get();
}
-policy::ConfigurationPolicyProviderKeeper*
- BrowserProcessImpl::configuration_policy_provider_keeper() {
+policy::BrowserPolicyConnector* BrowserProcessImpl::browser_policy_connector() {
DCHECK(CalledOnValidThread());
- if (!created_configuration_policy_provider_keeper_) {
- DCHECK(configuration_policy_provider_keeper_.get() == NULL);
- created_configuration_policy_provider_keeper_ = true;
- configuration_policy_provider_keeper_.reset(
- new policy::ConfigurationPolicyProviderKeeper());
+ if (!created_browser_policy_connector_) {
+ DCHECK(browser_policy_connector_.get() == NULL);
+ created_browser_policy_connector_ = true;
+ browser_policy_connector_.reset(new policy::BrowserPolicyConnector());
}
- return configuration_policy_provider_keeper_.get();
+ return browser_policy_connector_.get();
}
IconManager* BrowserProcessImpl::icon_manager() {
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index a3e0a36..06e56b7 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -15,9 +15,9 @@
#include "base/basictypes.h"
#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/timer.h"
-#include "base/scoped_ptr.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_status_updater.h"
#include "chrome/browser/prefs/pref_change_registrar.h"
@@ -63,8 +63,7 @@ class BrowserProcessImpl : public BrowserProcess,
virtual SidebarManager* sidebar_manager();
virtual ui::Clipboard* clipboard();
virtual NotificationUIManager* notification_ui_manager();
- virtual policy::ConfigurationPolicyProviderKeeper*
- configuration_policy_provider_keeper();
+ virtual policy::BrowserPolicyConnector* browser_policy_connector();
virtual IconManager* icon_manager();
virtual ThumbnailGenerator* GetThumbnailGenerator();
virtual AutomationProviderList* InitAutomationProviderList();
@@ -193,9 +192,8 @@ class BrowserProcessImpl : public BrowserProcess,
bool created_sidebar_manager_;
scoped_refptr<SidebarManager> sidebar_manager_;
- bool created_configuration_policy_provider_keeper_;
- scoped_ptr<policy::ConfigurationPolicyProviderKeeper>
- configuration_policy_provider_keeper_;
+ bool created_browser_policy_connector_;
+ scoped_ptr<policy::BrowserPolicyConnector> browser_policy_connector_;
scoped_refptr<printing::PrintPreviewTabController>
print_preview_tab_controller_;
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
new file mode 100644
index 0000000..33c7c3e
--- /dev/null
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -0,0 +1,179 @@
+// 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/browser_policy_connector.h"
+
+#include "base/command_line.h"
+#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"
+#include "chrome/browser/policy/dummy_configuration_policy_provider.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/policy/configuration_policy_provider_win.h"
+#elif defined(OS_MACOSX)
+#include "chrome/browser/policy/configuration_policy_provider_mac.h"
+#elif defined(OS_POSIX)
+#include "chrome/browser/policy/config_dir_policy_provider.h"
+#endif
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/policy/device_policy_identity_strategy.h"
+#endif
+
+namespace {
+
+const FilePath::CharType kDevicePolicyCacheFile[] =
+ FILE_PATH_LITERAL("Policy");
+
+} // namespace
+
+namespace policy {
+
+BrowserPolicyConnector::BrowserPolicyConnector() {
+ managed_platform_provider_.reset(CreateManagedPlatformProvider());
+ recommended_platform_provider_.reset(CreateRecommendedPlatformProvider());
+ registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
+ NotificationService::AllSources());
+
+#if defined(OS_CHROMEOS)
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kDevicePolicyCacheDir)) {
+ FilePath cache_dir(command_line->GetSwitchValuePath(
+ switches::kDevicePolicyCacheDir));
+
+ if (!file_util::CreateDirectory(cache_dir)) {
+ LOG(WARNING) << "Device policy cache directory "
+ << cache_dir.value()
+ << " is not accessible, skipping initialization.";
+ } else {
+ identity_strategy_.reset(new DevicePolicyIdentityStrategy());
+ cloud_policy_subsystem_.reset(
+ new CloudPolicySubsystem(cache_dir.Append(kDevicePolicyCacheFile),
+ identity_strategy_.get()));
+ }
+ }
+#endif
+}
+
+BrowserPolicyConnector::BrowserPolicyConnector(
+ ConfigurationPolicyProvider* managed_platform_provider,
+ ConfigurationPolicyProvider* recommended_platform_provider)
+ : managed_platform_provider_(managed_platform_provider),
+ recommended_platform_provider_(recommended_platform_provider) {}
+
+BrowserPolicyConnector::~BrowserPolicyConnector() {
+ if (cloud_policy_subsystem_.get())
+ cloud_policy_subsystem_->Shutdown();
+ cloud_policy_subsystem_.reset();
+ identity_strategy_.reset();
+}
+
+ConfigurationPolicyProvider*
+ BrowserPolicyConnector::GetManagedPlatformProvider() const {
+ return managed_platform_provider_.get();
+}
+
+ConfigurationPolicyProvider*
+ BrowserPolicyConnector::GetManagedCloudProvider() const {
+ if (cloud_policy_subsystem_.get())
+ return cloud_policy_subsystem_->GetManagedPolicyProvider();
+
+ return NULL;
+}
+
+ConfigurationPolicyProvider*
+ BrowserPolicyConnector::GetRecommendedPlatformProvider() const {
+ return recommended_platform_provider_.get();
+}
+
+ConfigurationPolicyProvider*
+ BrowserPolicyConnector::GetRecommendedCloudProvider() const {
+ if (cloud_policy_subsystem_.get())
+ return cloud_policy_subsystem_->GetRecommendedPolicyProvider();
+
+ return NULL;
+}
+
+ConfigurationPolicyProvider*
+ BrowserPolicyConnector::CreateManagedPlatformProvider() {
+ const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list =
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
+#if defined(OS_WIN)
+ return new ConfigurationPolicyProviderWin(policy_list);
+#elif defined(OS_MACOSX)
+ return new ConfigurationPolicyProviderMac(policy_list);
+#elif defined(OS_POSIX)
+ FilePath config_dir_path;
+ if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
+ return new ConfigDirPolicyProvider(
+ policy_list,
+ config_dir_path.Append(FILE_PATH_LITERAL("managed")));
+ } else {
+ return new DummyConfigurationPolicyProvider(policy_list);
+ }
+#else
+ return new DummyConfigurationPolicyProvider(policy_list);
+#endif
+}
+
+ConfigurationPolicyProvider*
+ BrowserPolicyConnector::CreateRecommendedPlatformProvider() {
+ const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list =
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ FilePath config_dir_path;
+ if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
+ return new ConfigDirPolicyProvider(
+ policy_list,
+ config_dir_path.Append(FILE_PATH_LITERAL("recommended")));
+ } else {
+ return new DummyConfigurationPolicyProvider(policy_list);
+ }
+#else
+ return new DummyConfigurationPolicyProvider(policy_list);
+#endif
+}
+
+// static
+void BrowserPolicyConnector::RegisterPrefs(PrefService* local_state) {
+ local_state->RegisterIntegerPref(prefs::kPolicyDevicePolicyRefreshRate,
+ kDefaultPolicyRefreshRateInMilliseconds);
+}
+
+void BrowserPolicyConnector::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE) {
+ Initialize(g_browser_process->local_state(),
+ Profile::GetDefaultRequestContext());
+ } else {
+ NOTREACHED();
+ }
+}
+
+void BrowserPolicyConnector::Initialize(
+ PrefService* local_state,
+ URLRequestContextGetter* request_context) {
+ // TODO(jkummerow, mnissler): Move this out of the browser startup path.
+ DCHECK(local_state);
+ DCHECK(request_context);
+ if (cloud_policy_subsystem_.get()) {
+ cloud_policy_subsystem_->Initialize(local_state,
+ prefs::kPolicyDevicePolicyRefreshRate,
+ request_context);
+ }
+}
+
+} // namespace
diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h
new file mode 100644
index 0000000..17e8c14
--- /dev/null
+++ b/chrome/browser/policy/browser_policy_connector.h
@@ -0,0 +1,77 @@
+// 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_BROWSER_POLICY_CONNECTOR_H_
+#define CHROME_BROWSER_POLICY_BROWSER_POLICY_CONNECTOR_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class PrefService;
+class TestingBrowserProcess;
+class TokenService;
+class URLRequestContextGetter;
+
+namespace policy {
+
+class CloudPolicyIdentityStrategy;
+class CloudPolicySubsystem;
+class ConfigurationPolicyProvider;
+
+// Manages the lifecycle of browser-global policy infrastructure, such as the
+// platform policy providers.
+class BrowserPolicyConnector : public NotificationObserver {
+ public:
+ static const int kDefaultPolicyRefreshRateInMilliseconds =
+ 3 * 60 * 60 * 1000; // 3 hours.
+
+ BrowserPolicyConnector();
+ ~BrowserPolicyConnector();
+
+ ConfigurationPolicyProvider* GetManagedPlatformProvider() const;
+ ConfigurationPolicyProvider* GetManagedCloudProvider() const;
+ ConfigurationPolicyProvider* GetRecommendedPlatformProvider() const;
+ ConfigurationPolicyProvider* GetRecommendedCloudProvider() const;
+
+ static void RegisterPrefs(PrefService* user_prefs);
+
+ // NotificationObserver implementation:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ friend class ::TestingBrowserProcess;
+
+ static ConfigurationPolicyProvider* CreateManagedPlatformProvider();
+ static ConfigurationPolicyProvider* CreateRecommendedPlatformProvider();
+
+ // Constructor for tests that allows tests to use fake platform policy
+ // providers instead of using the actual ones.
+ BrowserPolicyConnector(
+ ConfigurationPolicyProvider* managed_platform_provider,
+ ConfigurationPolicyProvider* recommended_platform_provider);
+
+ // Activates the cloud policy subsystem. Called when the default request
+ // context is available.
+ void Initialize(PrefService* local_state,
+ URLRequestContextGetter* request_context);
+
+ scoped_ptr<ConfigurationPolicyProvider> managed_platform_provider_;
+ scoped_ptr<ConfigurationPolicyProvider> recommended_platform_provider_;
+
+ scoped_ptr<CloudPolicyIdentityStrategy> identity_strategy_;
+ scoped_ptr<CloudPolicySubsystem> cloud_policy_subsystem_;
+
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserPolicyConnector);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_BROWSER_POLICY_CONNECTOR_H_
diff --git a/chrome/browser/policy/cloud_policy_cache.cc b/chrome/browser/policy/cloud_policy_cache.cc
index b81fb81..c7b96b8 100644
--- a/chrome/browser/policy/cloud_policy_cache.cc
+++ b/chrome/browser/policy/cloud_policy_cache.cc
@@ -11,8 +11,8 @@
#include "base/task.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/proto/cloud_policy.pb.h"
-#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"
@@ -33,6 +33,51 @@ namespace policy {
void DecodePolicy(const em::CloudPolicySettings& policy,
PolicyMap* mandatory, PolicyMap* recommended);
+// A thin ConfigurationPolicyProvider implementation sitting on top of
+// CloudPolicyCache for hooking up with ConfigurationPolicyPrefStore.
+class CloudPolicyCache::CloudPolicyProvider
+ : public ConfigurationPolicyProvider {
+ public:
+ CloudPolicyProvider(const PolicyDefinitionList* policy_list,
+ CloudPolicyCache* cache,
+ CloudPolicyCache::PolicyLevel level)
+ : ConfigurationPolicyProvider(policy_list),
+ cache_(cache),
+ level_(level) {}
+ virtual ~CloudPolicyProvider() {}
+
+ virtual bool Provide(ConfigurationPolicyStoreInterface* store) {
+ if (!cache_->has_device_policy()) {
+ if (level_ == POLICY_LEVEL_MANDATORY)
+ ApplyPolicyMap(&cache_->mandatory_policy_, store);
+ else if (level_ == POLICY_LEVEL_RECOMMENDED)
+ ApplyPolicyMap(&cache_->recommended_policy_, store);
+ } else {
+ ApplyPolicyValueTree(cache_->device_policy_.get(), store);
+ }
+ return true;
+ }
+
+ virtual bool IsInitializationComplete() const {
+ return cache_->initialization_complete_;
+ }
+
+ virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer) {
+ cache_->observer_list_.AddObserver(observer);
+ }
+ virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer) {
+ cache_->observer_list_.RemoveObserver(observer);
+ }
+
+ private:
+ // The underlying policy cache.
+ CloudPolicyCache* cache_;
+ // Policy level this provider will handle.
+ CloudPolicyCache::PolicyLevel level_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider);
+};
+
// Saves policy information to a file.
class PersistPolicyTask : public Task {
public:
@@ -85,17 +130,30 @@ CloudPolicyCache::CloudPolicyCache(
const FilePath& backing_file_path)
: backing_file_path_(backing_file_path),
device_policy_(new DictionaryValue),
- fresh_policy_(false),
+ initialization_complete_(false),
is_unmanaged_(false),
has_device_policy_(false) {
+ managed_policy_provider_.reset(
+ new CloudPolicyProvider(
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
+ this,
+ POLICY_LEVEL_MANDATORY));
+ recommended_policy_provider_.reset(
+ new CloudPolicyProvider(
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
+ this,
+ POLICY_LEVEL_RECOMMENDED));
}
-CloudPolicyCache::~CloudPolicyCache() {}
+CloudPolicyCache::~CloudPolicyCache() {
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
+ observer_list_, OnProviderGoingAway());
+}
-void CloudPolicyCache::LoadPolicyFromFile() {
+void CloudPolicyCache::LoadFromFile() {
// TODO(jkummerow): This method is doing file IO during browser startup. In
// the long run it would be better to delay this until the FILE thread exists.
- if (!file_util::PathExists(backing_file_path_) || fresh_policy_) {
+ if (!file_util::PathExists(backing_file_path_) || initialization_complete_) {
return;
}
@@ -136,55 +194,47 @@ void CloudPolicyCache::LoadPolicyFromFile() {
return;
}
// Swap in the new policy information.
- if (is_unmanaged_) {
- base::AutoLock lock(lock_);
- last_policy_refresh_time_ = timestamp;
- return;
- } else if (cached_response.has_cloud_policy()) {
- if (!fresh_policy_) {
- base::AutoLock lock(lock_);
- // The use of |Swap()| here makes sure that the old value in
- // |mandatory_policy_| is deleted when |mandatory_policy| goes out of
- // scope. (The same applies to |SetPolicy()| below.)
- mandatory_policy_.Swap(&mandatory_policy);
- recommended_policy_.Swap(&recommended_policy);
- last_policy_refresh_time_ = timestamp;
- has_device_policy_ = false;
- }
+ if (cached_response.has_cloud_policy()) {
+ mandatory_policy_.Swap(&mandatory_policy);
+ recommended_policy_.Swap(&recommended_policy);
+ has_device_policy_ = false;
} else if (cached_response.has_device_policy()) {
scoped_ptr<DictionaryValue> value(
DecodeDevicePolicy(cached_response.device_policy()));
- if (!fresh_policy_) {
- base::AutoLock lock(lock_);
- device_policy_.reset(value.release());
- last_policy_refresh_time_ = timestamp;
- has_device_policy_ = true;
- }
+ device_policy_.reset(value.release());
+ has_device_policy_ = true;
}
+ last_policy_refresh_time_ = timestamp;
+ initialization_complete_ = true;
+
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
+ observer_list_, OnUpdatePolicy());
}
-bool CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) {
+ DCHECK(CalledOnValidThread());
+ bool initialization_was_not_complete = !initialization_complete_;
is_unmanaged_ = false;
base::Time timestamp;
PolicyMap mandatory_policy;
PolicyMap recommended_policy;
bool ok = DecodePolicyResponse(policy, &mandatory_policy, &recommended_policy,
&timestamp);
- if (!ok) {
- // TODO(jkummerow): Signal error to PolicyProvider.
- return false;
- }
+ if (!ok)
+ return;
+
const bool new_policy_differs =
- !mandatory_policy.Equals(mandatory_policy_) ||
- !recommended_policy.Equals(recommended_policy_);
- {
- base::AutoLock lock(lock_);
- mandatory_policy_.Swap(&mandatory_policy);
- recommended_policy_.Swap(&recommended_policy);
- fresh_policy_ = true;
- last_policy_refresh_time_ = timestamp;
- has_device_policy_ = false;
+ !mandatory_policy_.Equals(mandatory_policy) ||
+ !recommended_policy_.Equals(recommended_policy);
+ mandatory_policy_.Swap(&mandatory_policy);
+ recommended_policy_.Swap(&recommended_policy);
+ initialization_complete_ = true;
+ last_policy_refresh_time_ = timestamp;
+ has_device_policy_ = false;
+
+ if (new_policy_differs || initialization_was_not_complete) {
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
+ observer_list_, OnUpdatePolicy());
}
if (timestamp > base::Time::NowFromSystemTime() +
@@ -199,21 +249,23 @@ bool CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) {
FROM_HERE,
new PersistPolicyTask(backing_file_path_, policy_copy, NULL, false));
}
- return new_policy_differs;
}
-bool CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) {
+ DCHECK(CalledOnValidThread());
+ bool initialization_was_not_complete = !initialization_complete_;
is_unmanaged_ = false;
DictionaryValue* value = DecodeDevicePolicy(policy);
const bool new_policy_differs = !(value->Equals(device_policy_.get()));
base::Time now(base::Time::NowFromSystemTime());
- {
- base::AutoLock lock(lock_);
- device_policy_.reset(value);
- fresh_policy_ = true;
- last_policy_refresh_time_ = now;
- has_device_policy_ = true;
+ device_policy_.reset(value);
+ initialization_complete_ = true;
+ last_policy_refresh_time_ = now;
+ has_device_policy_ = true;
+
+ if (new_policy_differs || initialization_was_not_complete) {
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
+ observer_list_, OnUpdatePolicy());
}
em::DevicePolicyResponse* policy_copy = new em::DevicePolicyResponse;
@@ -222,35 +274,29 @@ bool CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) {
BrowserThread::FILE,
FROM_HERE,
new PersistPolicyTask(backing_file_path_, NULL, policy_copy, false));
- return new_policy_differs;
}
-DictionaryValue* CloudPolicyCache::GetDevicePolicy() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- base::AutoLock lock(lock_);
- return device_policy_->DeepCopy();
+ConfigurationPolicyProvider* CloudPolicyCache::GetManagedPolicyProvider() {
+ DCHECK(CalledOnValidThread());
+ return managed_policy_provider_.get();
}
-const PolicyMap* CloudPolicyCache::GetMandatoryPolicy() const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return &mandatory_policy_;
-}
-
-const PolicyMap* CloudPolicyCache::GetRecommendedPolicy() const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return &recommended_policy_;
+ConfigurationPolicyProvider* CloudPolicyCache::GetRecommendedPolicyProvider() {
+ DCHECK(CalledOnValidThread());
+ return recommended_policy_provider_.get();
}
void CloudPolicyCache::SetUnmanaged() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(CalledOnValidThread());
is_unmanaged_ = true;
- {
- base::AutoLock lock(lock_);
- mandatory_policy_.Clear();
- recommended_policy_.Clear();
- device_policy_.reset(new DictionaryValue);
- last_policy_refresh_time_ = base::Time::NowFromSystemTime();
- }
+ mandatory_policy_.Clear();
+ recommended_policy_.Clear();
+ device_policy_.reset(new DictionaryValue);
+ last_policy_refresh_time_ = base::Time::NowFromSystemTime();
+
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
+ observer_list_, OnUpdatePolicy());
+
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
diff --git a/chrome/browser/policy/cloud_policy_cache.h b/chrome/browser/policy/cloud_policy_cache.h
index 518e3f0..5e7745a 100644
--- a/chrome/browser/policy/cloud_policy_cache.h
+++ b/chrome/browser/policy/cloud_policy_cache.h
@@ -9,9 +9,10 @@
#include "base/file_path.h"
#include "base/gtest_prod_util.h"
+#include "base/observer_list.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
-#include "base/synchronization/lock.h"
+#include "base/threading/non_thread_safe.h"
#include "base/time.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/policy_map.h"
@@ -33,25 +34,29 @@ namespace em = enterprise_management;
// to the service directly, but receives updated policy information through
// SetPolicy() calls, which is then persisted and decoded into the internal
// Value representation chrome uses.
-class CloudPolicyCache {
+class CloudPolicyCache : public base::NonThreadSafe {
public:
+ // Used to distinguish mandatory from recommended policies.
+ enum PolicyLevel {
+ // Policy is forced upon the user and should always take effect.
+ POLICY_LEVEL_MANDATORY,
+ // The value is just a recommendation that the user may override.
+ POLICY_LEVEL_RECOMMENDED,
+ };
+
explicit CloudPolicyCache(const FilePath& backing_file_path);
~CloudPolicyCache();
// Loads policy information from the backing file. Non-existing or erroneous
// cache files are ignored.
- void LoadPolicyFromFile();
+ void LoadFromFile();
- // Resets the policy information. Returns true if the new policy is different
- // from the previously stored policy.
- bool SetPolicy(const em::CloudPolicyResponse& policy);
- bool SetDevicePolicy(const em::DevicePolicyResponse& policy);
+ // Resets the policy information.
+ void SetPolicy(const em::CloudPolicyResponse& policy);
+ void SetDevicePolicy(const em::DevicePolicyResponse& policy);
- // Gets the policy information. Ownership of the return value is transferred
- // to the caller.
- DictionaryValue* GetDevicePolicy();
- const PolicyMap* GetMandatoryPolicy() const;
- const PolicyMap* GetRecommendedPolicy() const;
+ ConfigurationPolicyProvider* GetManagedPolicyProvider();
+ ConfigurationPolicyProvider* GetRecommendedPolicyProvider();
void SetUnmanaged();
bool is_unmanaged() const {
@@ -70,7 +75,10 @@ class CloudPolicyCache {
}
private:
+ class CloudPolicyProvider;
+
friend class CloudPolicyCacheTest;
+ friend class DeviceManagementPolicyCacheTest;
friend class DeviceManagementPolicyCacheDecodeTest;
// Decodes a CloudPolicyResponse into two (ConfigurationPolicyType -> Value*)
@@ -106,19 +114,17 @@ class CloudPolicyCache {
// The file in which we store a cached version of the policy information.
const FilePath backing_file_path_;
- // Protects both |mandatory_policy_| and |recommended_policy_| as well as
- // |device_policy_|.
- base::Lock lock_;
-
// Policy key-value information.
PolicyMap mandatory_policy_;
PolicyMap recommended_policy_;
scoped_ptr<DictionaryValue> device_policy_;
- // Tracks whether the store received a SetPolicy() call, which overrides any
- // information loaded from the file.
- bool fresh_policy_;
+ // Whether initialization has been completed. This is the case when we have
+ // valid policy, learned that the device is unmanaged or ran into
+ // unrecoverable errors.
+ bool initialization_complete_;
+ // Whether the the server has indicated this device is unmanaged.
bool is_unmanaged_;
// Tracks whether the cache currently stores |device_policy_| that should be
@@ -127,6 +133,15 @@ class CloudPolicyCache {
// The time at which the policy was last refreshed.
base::Time last_policy_refresh_time_;
+
+ // Policy providers.
+ scoped_ptr<ConfigurationPolicyProvider> managed_policy_provider_;
+ scoped_ptr<ConfigurationPolicyProvider> recommended_policy_provider_;
+
+ // Provider observers that are registered with this cache's providers.
+ ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPolicyCache);
};
} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_cache_unittest.cc b/chrome/browser/policy/cloud_policy_cache_unittest.cc
index d9fc768..158ab36 100644
--- a/chrome/browser/policy/cloud_policy_cache_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_cache_unittest.cc
@@ -12,11 +12,13 @@
#include "base/scoped_temp_dir.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/proto/cloud_policy.pb.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
// TODO(jkummerow): remove this import when removing old DMPC test cases.
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
@@ -31,6 +33,15 @@ void DecodePolicy(const em::CloudPolicySettings& policy,
Value* DecodeIntegerValue(google::protobuf::int64 value);
ListValue* DecodeStringList(const em::StringList& string_list);
+class MockConfigurationPolicyProviderObserver
+ : public ConfigurationPolicyProvider::Observer {
+ public:
+ MockConfigurationPolicyProviderObserver() {}
+ virtual ~MockConfigurationPolicyProviderObserver() {}
+ MOCK_METHOD0(OnUpdatePolicy, void());
+ void OnProviderGoingAway() {}
+};
+
// Tests the device management policy cache.
class CloudPolicyCacheTest : public testing::Test {
protected:
@@ -85,11 +96,35 @@ class CloudPolicyCacheTest : public testing::Test {
EXPECT_EQ(size, file_util::WriteFile(test_file(), data.c_str(), size));
}
+ // Takes ownership of |policy_response|.
+ void SetPolicy(CloudPolicyCache* cache,
+ em::CloudPolicyResponse* policy_response,
+ bool expect_changed_policy) {
+ scoped_ptr<em::CloudPolicyResponse> policy(policy_response);
+ ConfigurationPolicyObserverRegistrar registrar;
+ registrar.Init(cache->GetManagedPolicyProvider(), &observer);
+ if (expect_changed_policy)
+ EXPECT_CALL(observer, OnUpdatePolicy()).Times(1);
+ else
+ EXPECT_CALL(observer, OnUpdatePolicy()).Times(0);
+ cache->SetPolicy(*policy);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ }
+
FilePath test_file() {
return temp_dir_.path().AppendASCII("CloudPolicyCacheTest");
}
+ const PolicyMap& mandatory_policy(const CloudPolicyCache& cache) {
+ return cache.mandatory_policy_;
+ }
+
+ const PolicyMap& recommended_policy(const CloudPolicyCache& cache) {
+ return cache.recommended_policy_;
+ }
+
MessageLoop loop_;
+ MockConfigurationPolicyProviderObserver observer;
private:
ScopedTempDir temp_dir_;
@@ -157,16 +192,16 @@ TEST_F(CloudPolicyCacheTest, DecodeStringList) {
TEST_F(CloudPolicyCacheTest, Empty) {
CloudPolicyCache cache(test_file());
PolicyMap empty;
- EXPECT_TRUE(empty.Equals(*cache.GetMandatoryPolicy()));
- EXPECT_TRUE(empty.Equals(*cache.GetRecommendedPolicy()));
+ EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
+ EXPECT_TRUE(empty.Equals(recommended_policy(cache)));
EXPECT_EQ(base::Time(), cache.last_policy_refresh_time());
}
TEST_F(CloudPolicyCacheTest, LoadNoFile) {
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
PolicyMap empty;
- EXPECT_TRUE(empty.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
EXPECT_EQ(base::Time(), cache.last_policy_refresh_time());
}
@@ -177,9 +212,9 @@ TEST_F(CloudPolicyCacheTest, RejectFuture) {
em::PolicyOptions::MANDATORY));
WritePolicy(*policy_response);
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
PolicyMap empty;
- EXPECT_TRUE(empty.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
EXPECT_EQ(base::Time(), cache.last_policy_refresh_time());
}
@@ -189,9 +224,9 @@ TEST_F(CloudPolicyCacheTest, LoadWithFile) {
em::PolicyOptions::MANDATORY));
WritePolicy(*policy_response);
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
PolicyMap empty;
- EXPECT_TRUE(empty.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
EXPECT_NE(base::Time(), cache.last_policy_refresh_time());
EXPECT_GE(base::Time::Now(), cache.last_policy_refresh_time());
}
@@ -203,58 +238,58 @@ TEST_F(CloudPolicyCacheTest, LoadWithData) {
em::PolicyOptions::MANDATORY));
WritePolicy(*policy);
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
PolicyMap expected;
expected.Set(kPolicyHomepageLocation,
Value::CreateStringValue("http://www.example.com"));
- EXPECT_TRUE(expected.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
}
TEST_F(CloudPolicyCacheTest, SetPolicy) {
CloudPolicyCache cache(test_file());
- scoped_ptr<em::CloudPolicyResponse> policy(
+ em::CloudPolicyResponse* policy =
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
- em::PolicyOptions::MANDATORY));
- EXPECT_TRUE(cache.SetPolicy(*policy));
- scoped_ptr<em::CloudPolicyResponse> policy2(
+ em::PolicyOptions::MANDATORY);
+ SetPolicy(&cache, policy, true);
+ em::CloudPolicyResponse* policy2 =
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
- em::PolicyOptions::MANDATORY));
- EXPECT_FALSE(cache.SetPolicy(*policy2));
+ em::PolicyOptions::MANDATORY);
+ SetPolicy(&cache, policy2, false);
PolicyMap expected;
expected.Set(kPolicyHomepageLocation,
Value::CreateStringValue("http://www.example.com"));
PolicyMap empty;
- EXPECT_TRUE(expected.Equals(*cache.GetMandatoryPolicy()));
- EXPECT_TRUE(empty.Equals(*cache.GetRecommendedPolicy()));
- policy.reset(CreateHomepagePolicy("http://www.example.com",
+ EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
+ EXPECT_TRUE(empty.Equals(recommended_policy(cache)));
+ policy = CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
- em::PolicyOptions::RECOMMENDED));
- EXPECT_TRUE(cache.SetPolicy(*policy));
- EXPECT_TRUE(expected.Equals(*cache.GetRecommendedPolicy()));
- EXPECT_TRUE(empty.Equals(*cache.GetMandatoryPolicy()));
+ em::PolicyOptions::RECOMMENDED);
+ SetPolicy(&cache, policy, true);
+ EXPECT_TRUE(expected.Equals(recommended_policy(cache)));
+ EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
}
TEST_F(CloudPolicyCacheTest, ResetPolicy) {
CloudPolicyCache cache(test_file());
- scoped_ptr<em::CloudPolicyResponse> policy(
+ em::CloudPolicyResponse* policy =
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
- em::PolicyOptions::MANDATORY));
- EXPECT_TRUE(cache.SetPolicy(*policy));
+ em::PolicyOptions::MANDATORY);
+ SetPolicy(&cache, policy, true);
PolicyMap expected;
expected.Set(kPolicyHomepageLocation,
Value::CreateStringValue("http://www.example.com"));
- EXPECT_TRUE(expected.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
- scoped_ptr<em::CloudPolicyResponse> empty_policy(
+ em::CloudPolicyResponse* empty_policy =
CreateHomepagePolicy("", base::Time::NowFromSystemTime(),
- em::PolicyOptions::MANDATORY));
- EXPECT_TRUE(cache.SetPolicy(*empty_policy));
+ em::PolicyOptions::MANDATORY);
+ SetPolicy(&cache, empty_policy, true);
PolicyMap empty;
- EXPECT_TRUE(empty.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
}
TEST_F(CloudPolicyCacheTest, PersistPolicy) {
@@ -271,11 +306,11 @@ TEST_F(CloudPolicyCacheTest, PersistPolicy) {
EXPECT_TRUE(file_util::PathExists(test_file()));
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
PolicyMap expected;
expected.Set(kPolicyHomepageLocation,
Value::CreateStringValue("http://www.example.com"));
- EXPECT_TRUE(expected.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
}
TEST_F(CloudPolicyCacheTest, FreshPolicyOverride) {
@@ -286,17 +321,17 @@ TEST_F(CloudPolicyCacheTest, FreshPolicyOverride) {
WritePolicy(*policy);
CloudPolicyCache cache(test_file());
- scoped_ptr<em::CloudPolicyResponse> updated_policy(
+ em::CloudPolicyResponse* updated_policy =
CreateHomepagePolicy("http://www.chromium.org",
base::Time::NowFromSystemTime(),
- em::PolicyOptions::MANDATORY));
- EXPECT_TRUE(cache.SetPolicy(*updated_policy));
+ em::PolicyOptions::MANDATORY);
+ SetPolicy(&cache, updated_policy, true);
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
PolicyMap expected;
expected.Set(kPolicyHomepageLocation,
Value::CreateStringValue("http://www.chromium.org"));
- EXPECT_TRUE(expected.Equals(*cache.GetMandatoryPolicy()));
+ EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
}
} // namespace policy
@@ -363,7 +398,10 @@ class DeviceManagementPolicyCacheTest
return temp_dir_.path().AppendASCII("DeviceManagementPolicyCacheTest");
}
- protected:
+ const DictionaryValue* device_policy(const CloudPolicyCache& cache) {
+ return cache.device_policy_.get();
+ }
+
MessageLoop loop_;
private:
@@ -375,17 +413,15 @@ class DeviceManagementPolicyCacheTest
TEST_F(DeviceManagementPolicyCacheTest, Empty) {
CloudPolicyCache cache(test_file());
DictionaryValue empty;
- scoped_ptr<Value> policy(cache.GetDevicePolicy());
- EXPECT_TRUE(empty.Equals(policy.get()));
+ EXPECT_TRUE(empty.Equals(device_policy(cache)));
EXPECT_EQ(base::Time(), cache.last_policy_refresh_time());
}
TEST_F(DeviceManagementPolicyCacheTest, LoadNoFile) {
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
DictionaryValue empty;
- scoped_ptr<Value> policy(cache.GetDevicePolicy());
- EXPECT_TRUE(empty.Equals(policy.get()));
+ EXPECT_TRUE(empty.Equals(device_policy(cache)));
EXPECT_EQ(base::Time(), cache.last_policy_refresh_time());
}
@@ -394,10 +430,9 @@ TEST_F(DeviceManagementPolicyCacheTest, RejectFuture) {
WritePolicy(policy_response, base::Time::NowFromSystemTime() +
base::TimeDelta::FromMinutes(5));
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
DictionaryValue empty;
- scoped_ptr<Value> policy(cache.GetDevicePolicy());
- EXPECT_TRUE(empty.Equals(policy.get()));
+ EXPECT_TRUE(empty.Equals(device_policy(cache)));
EXPECT_EQ(base::Time(), cache.last_policy_refresh_time());
}
@@ -405,10 +440,9 @@ TEST_F(DeviceManagementPolicyCacheTest, LoadWithFile) {
em::DevicePolicyResponse policy_response;
WritePolicy(policy_response, base::Time::NowFromSystemTime());
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
DictionaryValue empty;
- scoped_ptr<Value> policy(cache.GetDevicePolicy());
- EXPECT_TRUE(empty.Equals(policy.get()));
+ EXPECT_TRUE(empty.Equals(device_policy(cache)));
EXPECT_NE(base::Time(), cache.last_policy_refresh_time());
EXPECT_GE(base::Time::Now(), cache.last_policy_refresh_time());
}
@@ -418,27 +452,25 @@ TEST_F(DeviceManagementPolicyCacheTest, LoadWithData) {
AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com");
WritePolicy(policy, base::Time::NowFromSystemTime());
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
DictionaryValue expected;
expected.Set("HomepageLocation",
Value::CreateStringValue("http://www.example.com"));
- scoped_ptr<Value> policy_value(cache.GetDevicePolicy());
- EXPECT_TRUE(expected.Equals(policy_value.get()));
+ EXPECT_TRUE(expected.Equals(device_policy(cache)));
}
TEST_F(DeviceManagementPolicyCacheTest, SetDevicePolicy) {
CloudPolicyCache cache(test_file());
em::DevicePolicyResponse policy;
AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com");
- EXPECT_TRUE(cache.SetDevicePolicy(policy));
+ cache.SetDevicePolicy(policy);
em::DevicePolicyResponse policy2;
AddStringPolicy(&policy2, "HomepageLocation", "http://www.example.com");
- EXPECT_FALSE(cache.SetDevicePolicy(policy2));
+ cache.SetDevicePolicy(policy2); // Does not notify observers.
DictionaryValue expected;
expected.Set("HomepageLocation",
Value::CreateStringValue("http://www.example.com"));
- scoped_ptr<Value> policy_value(cache.GetDevicePolicy());
- EXPECT_TRUE(expected.Equals(policy_value.get()));
+ EXPECT_TRUE(expected.Equals(device_policy(cache)));
}
TEST_F(DeviceManagementPolicyCacheTest, ResetPolicy) {
@@ -446,17 +478,15 @@ TEST_F(DeviceManagementPolicyCacheTest, ResetPolicy) {
em::DevicePolicyResponse policy;
AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com");
- EXPECT_TRUE(cache.SetDevicePolicy(policy));
+ cache.SetDevicePolicy(policy);
DictionaryValue expected;
expected.Set("HomepageLocation",
Value::CreateStringValue("http://www.example.com"));
- scoped_ptr<Value> policy_value(cache.GetDevicePolicy());
- EXPECT_TRUE(expected.Equals(policy_value.get()));
+ EXPECT_TRUE(expected.Equals(device_policy(cache)));
- EXPECT_TRUE(cache.SetDevicePolicy(em::DevicePolicyResponse()));
- policy_value.reset(cache.GetDevicePolicy());
+ cache.SetDevicePolicy(em::DevicePolicyResponse());
DictionaryValue empty;
- EXPECT_TRUE(empty.Equals(policy_value.get()));
+ EXPECT_TRUE(empty.Equals(device_policy(cache)));
}
TEST_F(DeviceManagementPolicyCacheTest, PersistPolicy) {
@@ -471,12 +501,11 @@ TEST_F(DeviceManagementPolicyCacheTest, PersistPolicy) {
EXPECT_TRUE(file_util::PathExists(test_file()));
CloudPolicyCache cache(test_file());
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
DictionaryValue expected;
expected.Set("HomepageLocation",
Value::CreateStringValue("http://www.example.com"));
- scoped_ptr<Value> policy_value(cache.GetDevicePolicy());
- EXPECT_TRUE(expected.Equals(policy_value.get()));
+ EXPECT_TRUE(expected.Equals(device_policy(cache)));
}
TEST_F(DeviceManagementPolicyCacheTest, FreshPolicyOverride) {
@@ -488,14 +517,13 @@ TEST_F(DeviceManagementPolicyCacheTest, FreshPolicyOverride) {
em::DevicePolicyResponse updated_policy;
AddStringPolicy(&updated_policy, "HomepageLocation",
"http://www.chromium.org");
- EXPECT_TRUE(cache.SetDevicePolicy(updated_policy));
+ cache.SetDevicePolicy(updated_policy);
- cache.LoadPolicyFromFile();
+ cache.LoadFromFile();
DictionaryValue expected;
expected.Set("HomepageLocation",
Value::CreateStringValue("http://www.chromium.org"));
- scoped_ptr<Value> policy_value(cache.GetDevicePolicy());
- EXPECT_TRUE(expected.Equals(policy_value.get()));
+ EXPECT_TRUE(expected.Equals(device_policy(cache)));
}
// Tests proper decoding of policy values.
diff --git a/chrome/browser/policy/cloud_policy_controller.cc b/chrome/browser/policy/cloud_policy_controller.cc
new file mode 100644
index 0000000..7ace406
--- /dev/null
+++ b/chrome/browser/policy/cloud_policy_controller.cc
@@ -0,0 +1,309 @@
+// 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/cloud_policy_controller.h"
+
+#include <algorithm>
+
+#include "base/message_loop.h"
+#include "base/rand_util.h"
+#include "base/string_util.h"
+#include "chrome/browser/policy/cloud_policy_cache.h"
+#include "chrome/browser/policy/cloud_policy_subsystem.h"
+#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/proto/device_management_constants.h"
+
+// Domain names that are known not to be managed.
+// We don't register the device when such a user logs in.
+static const char* kNonManagedDomains[] = {
+ "@googlemail.com",
+ "@gmail.com"
+};
+
+// Checks the domain part of the given username against the list of known
+// non-managed domain names. Returns false if |username| is empty or
+// in a domain known not to be managed.
+static bool CanBeInManagedDomain(const std::string& username) {
+ if (username.empty()) {
+ // This means incognito user in case of ChromiumOS and
+ // no logged-in user in case of Chromium (SigninService).
+ return false;
+ }
+ for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) {
+ if (EndsWith(username, kNonManagedDomains[i], true)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+namespace policy {
+
+namespace em = enterprise_management;
+
+// The maximum ratio in percent of the policy refresh rate we use for adjusting
+// the policy refresh time instant. The rationale is to avoid load spikes from
+// many devices that were set up in sync for some reason.
+static const int kPolicyRefreshDeviationFactorPercent = 10;
+// Maximum deviation we are willing to accept.
+static const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000;
+
+// These are the base values for delays before retrying after an error. They
+// will be doubled each time they are used.
+static const int64 kPolicyRefreshErrorDelayInMilliseconds =
+ 3 * 1000; // 3 seconds
+
+// Default value for the policy refresh rate.
+static const int kPolicyRefreshRateInMilliseconds =
+ 3 * 60 * 60 * 1000; // 3 hours.
+
+CloudPolicyController::CloudPolicyController(
+ CloudPolicyCache* cache,
+ DeviceManagementBackend* backend,
+ DeviceTokenFetcher* token_fetcher,
+ CloudPolicyIdentityStrategy* identity_strategy)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ Initialize(cache,
+ backend,
+ token_fetcher,
+ identity_strategy,
+ kPolicyRefreshRateInMilliseconds,
+ kPolicyRefreshDeviationFactorPercent,
+ kPolicyRefreshDeviationMaxInMilliseconds,
+ kPolicyRefreshErrorDelayInMilliseconds);
+}
+
+CloudPolicyController::~CloudPolicyController() {
+ token_fetcher_->RemoveObserver(this);
+ identity_strategy_->RemoveObserver(this);
+ CancelDelayedWork();
+}
+
+void CloudPolicyController::SetRefreshRate(int64 refresh_rate_milliseconds) {
+ policy_refresh_rate_ms_ = refresh_rate_milliseconds;
+
+ // Reschedule the refresh task if necessary.
+ if (state_ == STATE_POLICY_VALID)
+ SetState(STATE_POLICY_VALID);
+}
+
+void CloudPolicyController::HandlePolicyResponse(
+ const em::DevicePolicyResponse& response) {
+ if (state_ == STATE_TOKEN_UNAVAILABLE)
+ return;
+
+ cache_->SetDevicePolicy(response);
+ SetState(STATE_POLICY_VALID);
+}
+
+void CloudPolicyController::HandleCloudPolicyResponse(
+ const em::CloudPolicyResponse& response) {
+ if (state_ == STATE_TOKEN_UNAVAILABLE)
+ return;
+
+ cache_->SetPolicy(response);
+ SetState(STATE_POLICY_VALID);
+}
+
+void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) {
+ if (state_ == STATE_TOKEN_UNAVAILABLE)
+ return;
+
+ if (code == DeviceManagementBackend::kErrorServiceDeviceNotFound ||
+ code == DeviceManagementBackend::kErrorServiceManagementTokenInvalid) {
+ LOG(WARNING) << "The device token was either invalid or unknown to the "
+ << "device manager, re-registering device.";
+ SetState(STATE_TOKEN_UNAVAILABLE);
+ } else if (code ==
+ DeviceManagementBackend::kErrorServiceManagementNotSupported) {
+ VLOG(1) << "The device is no longer managed, resetting device token.";
+ SetState(STATE_TOKEN_UNAVAILABLE);
+ } else if (!fallback_to_old_protocol_ &&
+ code == DeviceManagementBackend::kErrorRequestInvalid) {
+ LOG(WARNING) << "Device manager doesn't understand new protocol, falling "
+ << "back to old request.";
+ fallback_to_old_protocol_ = true;
+ SetState(STATE_TOKEN_VALID); // Triggers SendPolicyRequest() immediately.
+ } else {
+ LOG(WARNING) << "Could not provide policy from the device manager (error = "
+ << code << "), will retry in "
+ << (effective_policy_refresh_error_delay_ms_ / 1000)
+ << " seconds.";
+ SetState(STATE_POLICY_ERROR);
+ }
+}
+
+void CloudPolicyController::OnDeviceTokenAvailable() {
+ identity_strategy_->OnDeviceTokenAvailable(token_fetcher_->GetDeviceToken());
+}
+
+void CloudPolicyController::OnDeviceTokenChanged() {
+ if (identity_strategy_->GetDeviceToken().empty())
+ SetState(STATE_TOKEN_UNAVAILABLE);
+ else
+ SetState(STATE_TOKEN_VALID);
+}
+
+void CloudPolicyController::OnCredentialsChanged() {
+ SetState(STATE_TOKEN_UNAVAILABLE);
+}
+
+CloudPolicyController::CloudPolicyController(
+ CloudPolicyCache* cache,
+ DeviceManagementBackend* backend,
+ DeviceTokenFetcher* token_fetcher,
+ CloudPolicyIdentityStrategy* identity_strategy,
+ 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,
+ token_fetcher,
+ identity_strategy,
+ policy_refresh_rate_ms,
+ policy_refresh_deviation_factor_percent,
+ policy_refresh_deviation_max_ms,
+ policy_refresh_error_delay_ms);
+}
+
+void CloudPolicyController::Initialize(
+ CloudPolicyCache* cache,
+ DeviceManagementBackend* backend,
+ DeviceTokenFetcher* token_fetcher,
+ CloudPolicyIdentityStrategy* identity_strategy,
+ 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);
+
+ cache_ = cache;
+ backend_.reset(backend);
+ token_fetcher_ = token_fetcher;
+ identity_strategy_ = identity_strategy;
+ state_ = STATE_TOKEN_UNAVAILABLE;
+ fallback_to_old_protocol_ = false;
+ delayed_work_task_ = NULL;
+ policy_refresh_rate_ms_ = policy_refresh_rate_ms;
+ policy_refresh_deviation_factor_percent_ =
+ policy_refresh_deviation_factor_percent;
+ policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms;
+ policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
+ effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
+
+ token_fetcher_->AddObserver(this);
+ identity_strategy_->AddObserver(this);
+ if (!identity_strategy_->GetDeviceToken().empty())
+ SetState(STATE_TOKEN_VALID);
+ else
+ SetState(STATE_TOKEN_UNAVAILABLE);
+}
+
+void CloudPolicyController::FetchToken() {
+ std::string username;
+ std::string auth_token;
+ std::string device_id = identity_strategy_->GetDeviceID();
+ if (identity_strategy_->GetCredentials(&username, &auth_token) &&
+ CanBeInManagedDomain(username)) {
+ token_fetcher_->FetchToken(auth_token, device_id);
+ }
+}
+
+void CloudPolicyController::SendPolicyRequest() {
+ DCHECK(!identity_strategy_->GetDeviceToken().empty());
+ if (!fallback_to_old_protocol_) {
+ em::CloudPolicyRequest policy_request;
+ policy_request.set_policy_scope(kChromePolicyScope);
+ backend_->ProcessCloudPolicyRequest(identity_strategy_->GetDeviceToken(),
+ identity_strategy_->GetDeviceID(),
+ policy_request, this);
+ } else {
+ em::DevicePolicyRequest policy_request;
+ policy_request.set_policy_scope(kChromePolicyScope);
+ em::DevicePolicySettingRequest* setting =
+ policy_request.add_setting_request();
+ setting->set_key(kChromeDevicePolicySettingKey);
+ setting->set_watermark("");
+ backend_->ProcessPolicyRequest(identity_strategy_->GetDeviceToken(),
+ identity_strategy_->GetDeviceID(),
+ policy_request, this);
+ }
+}
+
+void CloudPolicyController::DoDelayedWork() {
+ DCHECK(delayed_work_task_);
+ delayed_work_task_ = NULL;
+
+ switch (state_) {
+ case STATE_TOKEN_UNAVAILABLE:
+ FetchToken();
+ return;
+ case STATE_TOKEN_VALID:
+ case STATE_POLICY_VALID:
+ case STATE_POLICY_ERROR:
+ SendPolicyRequest();
+ return;
+ }
+
+ NOTREACHED() << "Unhandled state" << state_;
+}
+
+void CloudPolicyController::CancelDelayedWork() {
+ if (delayed_work_task_) {
+ delayed_work_task_->Cancel();
+ delayed_work_task_ = NULL;
+ }
+}
+
+void CloudPolicyController::SetState(
+ CloudPolicyController::ControllerState new_state) {
+ state_ = new_state;
+
+ base::Time now(base::Time::NowFromSystemTime());
+ base::Time refresh_at;
+ base::Time last_refresh(cache_->last_policy_refresh_time());
+ if (last_refresh.is_null())
+ last_refresh = now;
+
+ // Determine when to take the next step.
+ switch (state_) {
+ case STATE_TOKEN_UNAVAILABLE:
+ case STATE_TOKEN_VALID:
+ refresh_at = now;
+ break;
+ case STATE_POLICY_VALID:
+ effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
+ refresh_at =
+ last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay());
+ break;
+ case STATE_POLICY_ERROR:
+ refresh_at = now + base::TimeDelta::FromMilliseconds(
+ effective_policy_refresh_error_delay_ms_);
+ effective_policy_refresh_error_delay_ms_ *= 2;
+ if (effective_policy_refresh_error_delay_ms_ > policy_refresh_rate_ms_)
+ effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
+ break;
+ }
+
+ // Update the delayed work task.
+ CancelDelayedWork();
+ if (!refresh_at.is_null()) {
+ int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0);
+ delayed_work_task_ = method_factory_.NewRunnableMethod(
+ &CloudPolicyController::DoDelayedWork);
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, delayed_work_task_,
+ delay);
+ }
+}
+
+int64 CloudPolicyController::GetRefreshDelay() {
+ int64 deviation = (policy_refresh_deviation_factor_percent_ *
+ policy_refresh_rate_ms_) / 100;
+ deviation = std::min(deviation, policy_refresh_deviation_max_ms_);
+ return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1);
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_controller.h b/chrome/browser/policy/cloud_policy_controller.h
new file mode 100644
index 0000000..3375981
--- /dev/null
+++ b/chrome/browser/policy/cloud_policy_controller.h
@@ -0,0 +1,138 @@
+// 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_CLOUD_POLICY_CONTROLLER_H_
+#define CHROME_BROWSER_POLICY_CLOUD_POLICY_CONTROLLER_H_
+#pragma once
+
+#include <string>
+
+#include "base/file_path.h"
+#include "base/observer_list.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "base/time.h"
+#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/device_token_fetcher.h"
+
+class Profile;
+class TokenService;
+
+namespace policy {
+
+class CloudPolicyCache;
+class DeviceManagementBackend;
+
+// Coordinates the actions of DeviceTokenFetcher, CloudPolicyIdentityStrategy,
+// DeviceManagementBackend, and CloudPolicyCache: calls their methods and
+// listens to their callbacks/notifications.
+class CloudPolicyController
+ : public DeviceManagementBackend::DevicePolicyResponseDelegate,
+ public DeviceTokenFetcher::Observer,
+ public CloudPolicyIdentityStrategy::Observer {
+ public:
+ // Takes ownership of |backend|; the other parameters are weak pointers.
+ CloudPolicyController(CloudPolicyCache* cache,
+ DeviceManagementBackend* backend,
+ DeviceTokenFetcher* token_fetcher,
+ CloudPolicyIdentityStrategy* identity_strategy);
+ virtual ~CloudPolicyController();
+
+ // Sets the refresh rate at which to re-fetch policy information.
+ void SetRefreshRate(int64 refresh_rate_milliseconds);
+
+ // DevicePolicyResponseDelegate implementation:
+ virtual void HandlePolicyResponse(
+ const em::DevicePolicyResponse& response);
+ virtual void HandleCloudPolicyResponse(
+ const em::CloudPolicyResponse& response);
+ virtual void OnError(DeviceManagementBackend::ErrorCode code);
+
+ // DeviceTokenFetcher::Observer implementation:
+ virtual void OnDeviceTokenAvailable();
+
+ // CloudPolicyIdentityStrategy::Observer implementation:
+ virtual void OnDeviceTokenChanged();
+ virtual void OnCredentialsChanged();
+
+ private:
+ // Indicates the current state the controller is in.
+ enum ControllerState {
+ // The controller is initializing, policy information not yet available.
+ STATE_TOKEN_UNAVAILABLE,
+ // The token is valid, but policy is yet to be fetched.
+ STATE_TOKEN_VALID,
+ // Policy information is available and valid.
+ STATE_POLICY_VALID,
+ // The service returned an error when requesting policy, ask again later.
+ STATE_POLICY_ERROR,
+ };
+
+ friend class CloudPolicyControllerTest;
+
+ // More configurable constructor for use by test cases.
+ CloudPolicyController(CloudPolicyCache* cache,
+ DeviceManagementBackend* backend,
+ DeviceTokenFetcher* token_fetcher,
+ CloudPolicyIdentityStrategy* identity_strategy,
+ 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(CloudPolicyCache* cache,
+ DeviceManagementBackend* backend,
+ DeviceTokenFetcher* token_fetcher,
+ CloudPolicyIdentityStrategy* identity_strategy,
+ int64 policy_refresh_rate_ms,
+ int policy_refresh_deviation_factor_percent,
+ int64 policy_refresh_deviation_max_ms,
+ int64 policy_refresh_error_delay_ms);
+
+ // Asks the token fetcher to fetch a new token.
+ void FetchToken();
+
+ // Sends a request to the device management backend to fetch policy if one
+ // 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.
+ void DoDelayedWork();
+
+ // Cancels the delayed work task.
+ void CancelDelayedWork();
+
+ // Switches to a new state and triggers any appropriate actions.
+ void SetState(ControllerState new_state);
+
+ // Computes the policy refresh delay to use.
+ int64 GetRefreshDelay();
+
+ CloudPolicyCache* cache_;
+ scoped_ptr<DeviceManagementBackend> backend_;
+ CloudPolicyIdentityStrategy* identity_strategy_;
+ DeviceTokenFetcher* token_fetcher_;
+ ControllerState state_;
+ bool initial_fetch_done_;
+ bool fallback_to_old_protocol_;
+
+ int64 policy_refresh_rate_ms_;
+ int policy_refresh_deviation_factor_percent_;
+ int64 policy_refresh_deviation_max_ms_;
+ int64 policy_refresh_error_delay_ms_;
+ int64 effective_policy_refresh_error_delay_ms_;
+
+ CancelableTask* delayed_work_task_;
+ ScopedRunnableMethodFactory<CloudPolicyController> method_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPolicyController);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_CONTROLLER_H_
diff --git a/chrome/browser/policy/cloud_policy_controller_unittest.cc b/chrome/browser/policy/cloud_policy_controller_unittest.cc
new file mode 100644
index 0000000..b5181c9
--- /dev/null
+++ b/chrome/browser/policy/cloud_policy_controller_unittest.cc
@@ -0,0 +1,258 @@
+// 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/cloud_policy_controller.h"
+
+#include "base/message_loop.h"
+#include "base/scoped_temp_dir.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/policy/cloud_policy_cache.h"
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
+#include "chrome/browser/policy/mock_device_management_backend.h"
+#include "policy/policy_constants.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const char kTestToken[] = "cloud_policy_controller_test_auth_token";
+
+namespace policy {
+
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::InSequence;
+using ::testing::Mock;
+using ::testing::Return;
+
+class MockCloudPolicyIdentityStrategy : public CloudPolicyIdentityStrategy {
+ public:
+ MockCloudPolicyIdentityStrategy() {}
+ virtual ~MockCloudPolicyIdentityStrategy() {}
+
+ MOCK_METHOD0(GetDeviceToken, std::string());
+ MOCK_METHOD0(GetDeviceID, std::string());
+ MOCK_METHOD2(GetCredentials, bool(std::string*, std::string*));
+ virtual void OnDeviceTokenAvailable(const std::string&) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyIdentityStrategy);
+};
+
+ACTION_P2(MockCloudPolicyIdentityStrategyGetCredentials, username, auth_token) {
+ *arg0 = username;
+ *arg1 = auth_token;
+ return true;
+}
+
+class MockDeviceTokenFetcher : public DeviceTokenFetcher {
+ public:
+ explicit MockDeviceTokenFetcher(CloudPolicyCache* cache)
+ : DeviceTokenFetcher(NULL, cache) {}
+ virtual ~MockDeviceTokenFetcher() {}
+
+ MOCK_METHOD0(GetDeviceToken, std::string&());
+ MOCK_METHOD2(FetchToken, void(const std::string&, const std::string&));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDeviceTokenFetcher);
+};
+
+class CloudPolicyControllerTest : public testing::Test {
+ public:
+ CloudPolicyControllerTest()
+ : ui_thread_(BrowserThread::UI, &loop_),
+ file_thread_(BrowserThread::FILE, &loop_) {}
+
+ virtual ~CloudPolicyControllerTest() {}
+
+ virtual void SetUp() {
+ ASSERT_TRUE(temp_user_data_dir_.CreateUniqueTempDir());
+ cache_.reset(new CloudPolicyCache(
+ temp_user_data_dir_.path().AppendASCII("CloudPolicyControllerTest")));
+ token_fetcher_.reset(new MockDeviceTokenFetcher(cache_.get()));
+ }
+
+ virtual void TearDown() {
+ controller_.reset(); // Unregisters observers.
+ }
+
+ // Takes ownership of |backend|.
+ void CreateNewController(DeviceManagementBackend* backend) {
+ controller_.reset(new CloudPolicyController(
+ cache_.get(), backend, token_fetcher_.get(), &identity_strategy_));
+ }
+
+ void CreateNewController(DeviceManagementBackend* backend,
+ 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_,
+ policy_refresh_rate_ms,
+ policy_refresh_deviation_factor_percent,
+ policy_refresh_deviation_max_ms,
+ policy_refresh_error_delay_ms));
+ }
+
+ void ExpectHasSpdyPolicy() {
+ MockConfigurationPolicyStore store;
+ EXPECT_CALL(store, Apply(_, _)).Times(AtLeast(1));
+ cache_->GetManagedPolicyProvider()->Provide(&store);
+ FundamentalValue expected(true);
+ ASSERT_TRUE(store.Get(kPolicyDisableSpdy) != NULL);
+ EXPECT_TRUE(store.Get(kPolicyDisableSpdy)->Equals(&expected));
+ }
+
+ void SetupIdentityStrategy(const std::string& device_token,
+ const std::string& device_id,
+ const std::string& user_name,
+ const std::string& auth_token) {
+ EXPECT_CALL(identity_strategy_, GetDeviceToken()).WillRepeatedly(
+ Return(device_token));
+ EXPECT_CALL(identity_strategy_, GetDeviceID()).WillRepeatedly(
+ Return(device_id));
+ if (!user_name.empty()) {
+ EXPECT_CALL(identity_strategy_, GetCredentials(_, _)).WillRepeatedly(
+ MockCloudPolicyIdentityStrategyGetCredentials(user_name, auth_token));
+ }
+ }
+
+ protected:
+ scoped_ptr<CloudPolicyCache> cache_;
+ scoped_ptr<CloudPolicyController> controller_;
+ scoped_ptr<MockDeviceTokenFetcher> token_fetcher_;
+ MockCloudPolicyIdentityStrategy identity_strategy_;
+ ScopedTempDir temp_user_data_dir_;
+ MessageLoop loop_;
+
+ private:
+ BrowserThread ui_thread_;
+ BrowserThread file_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPolicyControllerTest);
+};
+
+// If a device token is present when the controller starts up, it should
+// fetch and apply policy.
+TEST_F(CloudPolicyControllerTest, StartupWithDeviceToken) {
+ SetupIdentityStrategy("fake_device_token", "device_id", "", "");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendSucceedSpdyCloudPolicy());
+ CreateNewController(backend);
+ loop_.RunAllPending();
+ ExpectHasSpdyPolicy();
+}
+
+// If no device token is present when the controller starts up, it should
+// instruct the token_fetcher_ to fetch one.
+TEST_F(CloudPolicyControllerTest, StartupWithoutDeviceToken) {
+ SetupIdentityStrategy("", "device_id", "a@b.com", "auth_token");
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ CreateNewController(NULL);
+ loop_.RunAllPending();
+}
+
+// If the current user belongs to a known non-managed domain, no token fetch
+// should be initiated.
+TEST_F(CloudPolicyControllerTest, StartupUnmanagedUser) {
+ SetupIdentityStrategy("", "device_id", "DannoHelper@gmail.com", "auth_token");
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(0);
+ CreateNewController(NULL);
+ loop_.RunAllPending();
+}
+
+// After policy has been fetched successfully, a new fetch should be triggered
+// after the refresh interval has timed out.
+TEST_F(CloudPolicyControllerTest, RefreshAfterSuccessfulPolicy) {
+ SetupIdentityStrategy("device_token", "device_id",
+ "DannoHelperDelegate@b.com", "auth_token");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendSucceedSpdyCloudPolicy()).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorRequestFailed));
+ CreateNewController(backend, 0, 0, 0, 1000 * 1000);
+ loop_.RunAllPending();
+ ExpectHasSpdyPolicy();
+}
+
+// If poliy fetching failed, it should be retried.
+TEST_F(CloudPolicyControllerTest, RefreshAfterError) {
+ SetupIdentityStrategy("device_token", "device_id",
+ "DannoHelperDelegateImpl@b.com", "auth_token");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorRequestFailed)).WillOnce(
+ MockDeviceManagementBackendSucceedSpdyCloudPolicy());
+ CreateNewController(backend, 1000 * 1000, 0, 0, 0);
+ loop_.RunAllPending();
+ ExpectHasSpdyPolicy();
+}
+
+// If the backend reports that the device token was invalid, the controller
+// should instruct the token fetcher to fetch a new token.
+TEST_F(CloudPolicyControllerTest, InvalidToken) {
+ SetupIdentityStrategy("device_token", "device_id", "standup@ten.am", "auth");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ CreateNewController(backend);
+ loop_.RunAllPending();
+}
+
+// If the backend reports that the device is unknown to the server, the
+// controller should instruct the token fetcher to fetch a new token.
+TEST_F(CloudPolicyControllerTest, DeviceNotFound) {
+ SetupIdentityStrategy("device_token", "device_id", "me@you.com", "auth");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorServiceDeviceNotFound));
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ CreateNewController(backend);
+ loop_.RunAllPending();
+}
+
+// If the backend reports that the device is no longer managed, the controller
+// shoud instruct the token fetcher to fetch a new token (which will in turn
+// set and persist the correct 'unmanaged' state).
+TEST_F(CloudPolicyControllerTest, NoLongerManaged) {
+ SetupIdentityStrategy("device_token", "device_id", "who@what.com", "auth");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorServiceManagementNotSupported));
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ CreateNewController(backend);
+ loop_.RunAllPending();
+}
+
+// If the server doesn't support the new protocol, the controller should fall
+// back to the old protocol.
+TEST_F(CloudPolicyControllerTest, FallbackToOldProtocol) {
+ SetupIdentityStrategy("device_token", "device_id", "a@b.com", "auth");
+ MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
+ // If the CloudPolicyRequest fails with kErrorRequestInvalid...
+ EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorRequestInvalid));
+ // ...the client should fall back to a classic PolicyRequest,
+ // and remember this fallback for any future request,
+ // both after successful fetches and after errors.
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
+ MockDeviceManagementBackendSucceedBooleanPolicy(
+ key::kDisableSpdy, true)).WillOnce(
+ MockDeviceManagementBackendFailPolicy(
+ DeviceManagementBackend::kErrorHttpStatus)).WillOnce(
+ Return());
+ CreateNewController(backend, 0, 0, 0, 0);
+ loop_.RunAllPending();
+ ExpectHasSpdyPolicy();
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_identity_strategy.h b/chrome/browser/policy/cloud_policy_identity_strategy.h
new file mode 100644
index 0000000..681d80a
--- /dev/null
+++ b/chrome/browser/policy/cloud_policy_identity_strategy.h
@@ -0,0 +1,83 @@
+// 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_CLOUD_POLICY_IDENTITY_STRATEGY_H_
+#define CHROME_BROWSER_POLICY_CLOUD_POLICY_IDENTITY_STRATEGY_H_
+#pragma once
+
+#include <string>
+
+#include "base/observer_list.h"
+
+namespace policy {
+
+// Manages a device management token, i.e. an identifier that represents a
+// registration with the device management service, and the associated
+// credentials. Responsibilities include storing and loading the token from
+// disk, observing and triggering relevant notifications.
+class CloudPolicyIdentityStrategy {
+ public:
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ // Notifies observers that the effective token for fetching policy has
+ // changed. The token can be queried by calling GetDeviceToken().
+ virtual void OnDeviceTokenChanged() = 0;
+
+ // Authentication credentials for talking to the device management service
+ // changed. New auth data is available through GetCredentials().
+ virtual void OnCredentialsChanged() = 0;
+ };
+
+ CloudPolicyIdentityStrategy() {}
+ virtual ~CloudPolicyIdentityStrategy() {}
+
+ void AddObserver(Observer* obs) {
+ observer_list_.AddObserver(obs);
+ }
+
+ void RemoveObserver(Observer* obs) {
+ observer_list_.RemoveObserver(obs);
+ }
+
+ // Returns the device management token, if available. Returns the empty string
+ // if the device token is currently unavailable.
+ virtual std::string GetDeviceToken() = 0;
+
+ // Returns the device ID for this device.
+ virtual std::string GetDeviceID() = 0;
+
+ // Retrieves authentication credentials to use when talking to the device
+ // management service. Returns true if the data is available and writes the
+ // values to the provided pointers.
+ virtual bool GetCredentials(std::string* username,
+ std::string* auth_token) = 0;
+
+ // Notifies the identity strategy that a new token has been fetched. It is up
+ // to the identity strategy to store the token, decide whether it is going
+ // to be used, send out an appropriate OnDeviceTokenChanged() notification
+ // and return the new token in GetDeviceToken() calls.
+ virtual void OnDeviceTokenAvailable(const std::string& token) = 0;
+
+ protected:
+ // Notify observers that the effective token has changed.
+ void NotifyDeviceTokenChanged() {
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenChanged());
+ }
+
+ // Notify observers about authentication data change.
+ void NotifyAuthChanged() {
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnCredentialsChanged());
+ }
+
+ private:
+ ObserverList<Observer, true> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPolicyIdentityStrategy);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_IDENTITY_STRATEGY_H_
diff --git a/chrome/browser/policy/cloud_policy_subsystem.cc b/chrome/browser/policy/cloud_policy_subsystem.cc
new file mode 100644
index 0000000..3b8291a
--- /dev/null
+++ b/chrome/browser/policy/cloud_policy_subsystem.cc
@@ -0,0 +1,124 @@
+// 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/cloud_policy_subsystem.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/command_line.h"
+#include "chrome/browser/policy/cloud_policy_cache.h"
+#include "chrome/browser/policy/cloud_policy_controller.h"
+#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
+#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/common/chrome_switches.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+
+namespace {
+
+// Refresh rate sanity interval bounds.
+const int64 kPolicyRefreshRateMinMs = 30 * 60 * 1000; // 30 minutes
+const int64 kPolicyRefreshRateMaxMs = 24 * 60 * 60 * 1000; // 1 day
+
+} // namespace
+
+namespace policy {
+
+CloudPolicySubsystem::CloudPolicySubsystem(
+ const FilePath& policy_cache_file,
+ CloudPolicyIdentityStrategy* identity_strategy)
+ : prefs_(NULL) {
+ 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(new CloudPolicyCache(policy_cache_file));
+ cloud_policy_cache_->LoadFromFile();
+
+ device_token_fetcher_.reset(
+ new DeviceTokenFetcher(device_management_service_.get(),
+ cloud_policy_cache_.get()));
+
+ cloud_policy_controller_.reset(
+ new CloudPolicyController(cloud_policy_cache_.get(),
+ device_management_service_->CreateBackend(),
+ device_token_fetcher_.get(),
+ identity_strategy));
+ }
+}
+
+CloudPolicySubsystem::~CloudPolicySubsystem() {
+ DCHECK(!prefs_);
+ cloud_policy_controller_.reset();
+ device_token_fetcher_.reset();
+ cloud_policy_cache_.reset();
+ device_management_service_.reset();
+}
+
+void CloudPolicySubsystem::Initialize(
+ PrefService* prefs,
+ const char* refresh_rate_pref_name,
+ URLRequestContextGetter* request_context) {
+ DCHECK(!prefs_);
+ prefs_ = prefs;
+
+ if (device_management_service_.get())
+ device_management_service_->Initialize(request_context);
+
+ policy_refresh_rate_.Init(refresh_rate_pref_name, prefs_, this);
+ UpdatePolicyRefreshRate();
+}
+
+void CloudPolicySubsystem::Shutdown() {
+ if (device_management_service_.get())
+ device_management_service_->Shutdown();
+ cloud_policy_controller_.reset();
+ cloud_policy_cache_.reset();
+ policy_refresh_rate_.Destroy();
+ prefs_ = NULL;
+}
+
+ConfigurationPolicyProvider* CloudPolicySubsystem::GetManagedPolicyProvider() {
+ if (cloud_policy_cache_.get())
+ return cloud_policy_cache_->GetManagedPolicyProvider();
+
+ return NULL;
+}
+
+ConfigurationPolicyProvider*
+ CloudPolicySubsystem::GetRecommendedPolicyProvider() {
+ if (cloud_policy_cache_.get())
+ return cloud_policy_cache_->GetRecommendedPolicyProvider();
+
+ return NULL;
+}
+
+void CloudPolicySubsystem::UpdatePolicyRefreshRate() {
+ if (cloud_policy_controller_.get()) {
+ // Clamp to sane values.
+ int64 refresh_rate = policy_refresh_rate_.GetValue();
+ refresh_rate = std::max(kPolicyRefreshRateMinMs, refresh_rate);
+ refresh_rate = std::min(kPolicyRefreshRateMaxMs, refresh_rate);
+ cloud_policy_controller_->SetRefreshRate(refresh_rate);
+ }
+}
+
+void CloudPolicySubsystem::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::PREF_CHANGED &&
+ policy_refresh_rate_.GetPrefName() ==
+ *(Details<std::string>(details).ptr()) &&
+ prefs_ == Source<PrefService>(source).ptr()) {
+ UpdatePolicyRefreshRate();
+ } else {
+ NOTREACHED();
+ }
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_subsystem.h b/chrome/browser/policy/cloud_policy_subsystem.h
new file mode 100644
index 0000000..503e607
--- /dev/null
+++ b/chrome/browser/policy/cloud_policy_subsystem.h
@@ -0,0 +1,73 @@
+// 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_CLOUD_POLICY_SUBSYSTEM_H_
+#define CHROME_BROWSER_POLICY_CLOUD_POLICY_SUBSYSTEM_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/common/notification_observer.h"
+
+class FilePath;
+class PrefService;
+class URLRequestContextGetter;
+
+namespace policy {
+
+class CloudPolicyCache;
+class CloudPolicyController;
+class CloudPolicyIdentityStrategy;
+class ConfigurationPolicyProvider;
+class DeviceManagementService;
+class DeviceTokenFetcher;
+
+// 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:
+ CloudPolicySubsystem(const FilePath& policy_cache_file,
+ CloudPolicyIdentityStrategy* identity_strategy);
+ virtual ~CloudPolicySubsystem();
+
+ // Initializes the subsystem.
+ void Initialize(PrefService* prefs,
+ const char* refresh_rate_pref_name,
+ URLRequestContextGetter* request_context);
+
+ // Shuts the subsystem down. This must be called before threading and network
+ // infrastructure goes away.
+ void Shutdown();
+
+ ConfigurationPolicyProvider* GetManagedPolicyProvider();
+ ConfigurationPolicyProvider* GetRecommendedPolicyProvider();
+
+ private:
+ // Updates the policy controller with a new refresh rate value.
+ void UpdatePolicyRefreshRate();
+
+ // NotificationObserver overrides.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // The pref service that controls the refresh rate.
+ PrefService* prefs_;
+
+ // Tracks the pref value for the policy refresh rate.
+ IntegerPrefMember policy_refresh_rate_;
+
+ // Cloud policy infrastructure stuff.
+ scoped_ptr<DeviceManagementService> device_management_service_;
+ scoped_ptr<DeviceTokenFetcher> device_token_fetcher_;
+ scoped_ptr<CloudPolicyCache> cloud_policy_cache_;
+ scoped_ptr<CloudPolicyController> cloud_policy_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPolicySubsystem);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_SUBSYSTEM_H_
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index 0b8445f..a60b45d 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -18,10 +18,9 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
-#include "chrome/browser/policy/configuration_policy_provider_keeper.h"
-#include "chrome/browser/policy/device_management_policy_provider.h"
-#include "chrome/browser/policy/profile_policy_context.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/prefs/pref_value_map.h"
#include "chrome/browser/prefs/proxy_config_dictionary.h"
#include "chrome/browser/profiles/profile.h"
@@ -228,7 +227,7 @@ const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
{ Value::TYPE_BOOLEAN, kPolicyDisable3DAPIs,
prefs::kDisable3DAPIs },
{ Value::TYPE_INTEGER, kPolicyPolicyRefreshRate,
- prefs::kPolicyRefreshRate },
+ prefs::kPolicyUserPolicyRefreshRate },
{ Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled },
{ Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled,
prefs::kDefaultBrowserSettingEnabled },
@@ -738,35 +737,53 @@ void ConfigurationPolicyPrefStore::OnProviderGoingAway() {
// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() {
- ConfigurationPolicyProviderKeeper* keeper =
- g_browser_process->configuration_policy_provider_keeper();
- return new ConfigurationPolicyPrefStore(keeper->managed_platform_provider());
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ return new ConfigurationPolicyPrefStore(
+ connector->GetManagedPlatformProvider());
}
// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(
Profile* profile) {
+ ConfigurationPolicyProvider* provider = NULL;
if (profile) {
- return new ConfigurationPolicyPrefStore(
- profile->GetPolicyContext()->GetDeviceManagementPolicyProvider());
+ // For user policy, return the profile's policy provider.
+ provider = profile->GetPolicyConnector()->GetManagedCloudProvider();
+ } else {
+ // For device policy, return the provider of the browser process.
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ provider = connector->GetManagedCloudProvider();
}
- return new ConfigurationPolicyPrefStore(NULL);
+ return new ConfigurationPolicyPrefStore(provider);
}
// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() {
- ConfigurationPolicyProviderKeeper* keeper =
- g_browser_process->configuration_policy_provider_keeper();
- return new ConfigurationPolicyPrefStore(keeper->recommended_provider());
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ return new ConfigurationPolicyPrefStore(
+ connector->GetRecommendedPlatformProvider());
}
// static
ConfigurationPolicyPrefStore*
ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
Profile* profile) {
- return new ConfigurationPolicyPrefStore(NULL);
+ ConfigurationPolicyProvider* provider = NULL;
+ if (profile) {
+ // For user policy, return the profile's policy provider.
+ provider = profile->GetPolicyConnector()->GetRecommendedCloudProvider();
+ } else {
+ // For device policy, return the provider of the browser process.
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ provider = connector->GetRecommendedCloudProvider();
+ }
+ return new ConfigurationPolicyPrefStore(provider);
}
/* static */
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index be89d98..a29922d 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -229,7 +229,7 @@ INSTANTIATE_TEST_CASE_P(
TypeAndName(kPolicyRestoreOnStartup,
prefs::kRestoreOnStartup),
TypeAndName(kPolicyPolicyRefreshRate,
- prefs::kPolicyRefreshRate)));
+ prefs::kPolicyUserPolicyRefreshRate)));
// Test cases for the proxy policy settings.
class ConfigurationPolicyPrefStoreProxyTest : public testing::Test {
diff --git a/chrome/browser/policy/configuration_policy_provider_keeper.cc b/chrome/browser/policy/configuration_policy_provider_keeper.cc
deleted file mode 100644
index 9959f74..0000000
--- a/chrome/browser/policy/configuration_policy_provider_keeper.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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/configuration_policy_provider_keeper.h"
-
-#include "base/path_service.h"
-#include "chrome/browser/policy/configuration_policy_pref_store.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
-#if defined(OS_WIN)
-#include "chrome/browser/policy/configuration_policy_provider_win.h"
-#elif defined(OS_MACOSX)
-#include "chrome/browser/policy/configuration_policy_provider_mac.h"
-#elif defined(OS_POSIX)
-#include "chrome/browser/policy/config_dir_policy_provider.h"
-#endif
-#include "chrome/browser/policy/dummy_configuration_policy_provider.h"
-#include "chrome/common/chrome_paths.h"
-
-namespace policy {
-
-ConfigurationPolicyProviderKeeper::ConfigurationPolicyProviderKeeper()
- : managed_platform_provider_(CreateManagedPlatformProvider()),
- device_management_provider_(CreateDeviceManagementProvider()),
- recommended_provider_(CreateRecommendedProvider()) {
-}
-
-ConfigurationPolicyProviderKeeper::ConfigurationPolicyProviderKeeper(
- ConfigurationPolicyProvider* managed_platform_provider,
- ConfigurationPolicyProvider* device_management_provider,
- ConfigurationPolicyProvider* recommended_provider)
- : managed_platform_provider_(managed_platform_provider),
- device_management_provider_(device_management_provider),
- recommended_provider_(recommended_provider) {
-}
-
-ConfigurationPolicyProviderKeeper::~ConfigurationPolicyProviderKeeper() {}
-
-ConfigurationPolicyProvider*
- ConfigurationPolicyProviderKeeper::managed_platform_provider() const {
- return managed_platform_provider_.get();
-}
-
-ConfigurationPolicyProvider*
- ConfigurationPolicyProviderKeeper::device_management_provider() const {
- return device_management_provider_.get();
-}
-
-ConfigurationPolicyProvider*
- ConfigurationPolicyProviderKeeper::recommended_provider() const {
- return recommended_provider_.get();
-}
-
-ConfigurationPolicyProvider*
- ConfigurationPolicyProviderKeeper::CreateManagedPlatformProvider() {
- const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list =
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
-#if defined(OS_WIN)
- return new ConfigurationPolicyProviderWin(policy_list);
-#elif defined(OS_MACOSX)
- return new ConfigurationPolicyProviderMac(policy_list);
-#elif defined(OS_POSIX)
- FilePath config_dir_path;
- if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
- return new ConfigDirPolicyProvider(
- policy_list,
- config_dir_path.Append(FILE_PATH_LITERAL("managed")));
- } else {
- return new DummyConfigurationPolicyProvider(policy_list);
- }
-#else
- return new DummyConfigurationPolicyProvider(policy_list);
-#endif
-}
-
-ConfigurationPolicyProvider*
- ConfigurationPolicyProviderKeeper::CreateDeviceManagementProvider() {
- return new DummyConfigurationPolicyProvider(
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList());
-}
-
-ConfigurationPolicyProvider*
- ConfigurationPolicyProviderKeeper::CreateRecommendedProvider() {
- const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list =
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
- FilePath config_dir_path;
- if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
- return new ConfigDirPolicyProvider(
- policy_list,
- config_dir_path.Append(FILE_PATH_LITERAL("recommended")));
- } else {
- return new DummyConfigurationPolicyProvider(policy_list);
- }
-#else
- return new DummyConfigurationPolicyProvider(policy_list);
-#endif
-}
-
-} // namespace
diff --git a/chrome/browser/policy/configuration_policy_provider_keeper.h b/chrome/browser/policy/configuration_policy_provider_keeper.h
deleted file mode 100644
index 1156cb4..0000000
--- a/chrome/browser/policy/configuration_policy_provider_keeper.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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_CONFIGURATION_POLICY_PROVIDER_KEEPER_H_
-#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_KEEPER_H_
-#pragma once
-
-#include "base/scoped_ptr.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
-
-namespace policy {
-
-// Manages the lifecycle of the shared platform-specific policy providers for
-// managed platform, device management and recommended policy.
-class ConfigurationPolicyProviderKeeper {
- public:
- ConfigurationPolicyProviderKeeper();
- // Tests can pass in their own (dummy) providers using this c'tor.
- ConfigurationPolicyProviderKeeper(
- ConfigurationPolicyProvider* managed_platform_provider,
- ConfigurationPolicyProvider* device_management_provider,
- ConfigurationPolicyProvider* recommended_provider);
- virtual ~ConfigurationPolicyProviderKeeper();
-
- ConfigurationPolicyProvider* managed_platform_provider() const;
-
- ConfigurationPolicyProvider* device_management_provider() const;
-
- ConfigurationPolicyProvider* recommended_provider() const;
-
- private:
- scoped_ptr<ConfigurationPolicyProvider> managed_platform_provider_;
- scoped_ptr<ConfigurationPolicyProvider> device_management_provider_;
- scoped_ptr<ConfigurationPolicyProvider> recommended_provider_;
-
- static ConfigurationPolicyProvider* CreateManagedPlatformProvider();
- static ConfigurationPolicyProvider* CreateDeviceManagementProvider();
- static ConfigurationPolicyProvider* CreateRecommendedProvider();
-
- DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderKeeper);
-};
-
-} // namespace policy
-
-#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_KEEPER_H_
diff --git a/chrome/browser/policy/device_management_policy_provider.cc b/chrome/browser/policy/device_management_policy_provider.cc
deleted file mode 100644
index eaaf4d4..0000000
--- a/chrome/browser/policy/device_management_policy_provider.cc
+++ /dev/null
@@ -1,416 +0,0 @@
-// 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/device_management_policy_provider.h"
-
-#include <algorithm>
-
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/rand_util.h"
-#include "base/task.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/policy/cloud_policy_cache.h"
-#include "chrome/browser/policy/device_management_backend.h"
-#include "chrome/browser/policy/profile_policy_context.h"
-#include "chrome/browser/policy/proto/device_management_constants.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-
-namespace policy {
-
-namespace em = enterprise_management;
-
-// The maximum ratio in percent of the policy refresh rate we use for adjusting
-// the policy refresh time instant. The rationale is to avoid load spikes from
-// many devices that were set up in sync for some reason.
-const int kPolicyRefreshDeviationFactorPercent = 10;
-// Maximum deviation we are willing to accept.
-const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000;
-
-// These are the base values for delays before retrying after an error. They
-// will be doubled each time they are used.
-const int64 kPolicyRefreshErrorDelayInMilliseconds = 3 * 1000; // 3 seconds
-const int64 kDeviceTokenRefreshErrorDelayInMilliseconds = 3 * 1000;
-// For unmanaged devices, check once per day whether they're still unmanaged.
-const int64 kPolicyRefreshUnmanagedDeviceInMilliseconds = 24 * 60 * 60 * 1000;
-
-const FilePath::StringType kDeviceTokenFilename = FILE_PATH_LITERAL("Token");
-const FilePath::StringType kPolicyFilename = FILE_PATH_LITERAL("Policy");
-
-// Calls back into the provider to refresh policy.
-class DeviceManagementPolicyProvider::RefreshTask : public CancelableTask {
- public:
- explicit RefreshTask(DeviceManagementPolicyProvider* provider)
- : provider_(provider) {}
-
- // Task implementation:
- virtual void Run() {
- if (provider_)
- provider_->RefreshTaskExecute();
- }
-
- // CancelableTask implementation:
- virtual void Cancel() {
- provider_ = NULL;
- }
-
- private:
- DeviceManagementPolicyProvider* provider_;
-};
-
-DeviceManagementPolicyProvider::DeviceManagementPolicyProvider(
- const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list,
- DeviceManagementBackend* backend,
- Profile* profile)
- : ConfigurationPolicyProvider(policy_list) {
- Initialize(backend,
- profile,
- ProfilePolicyContext::kDefaultPolicyRefreshRateInMilliseconds,
- kPolicyRefreshDeviationFactorPercent,
- kPolicyRefreshDeviationMaxInMilliseconds,
- kPolicyRefreshErrorDelayInMilliseconds,
- kDeviceTokenRefreshErrorDelayInMilliseconds,
- kPolicyRefreshUnmanagedDeviceInMilliseconds);
-}
-
-DeviceManagementPolicyProvider::~DeviceManagementPolicyProvider() {
- FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
- observer_list_,
- OnProviderGoingAway());
- CancelRefreshTask();
-}
-
-bool DeviceManagementPolicyProvider::Provide(
- ConfigurationPolicyStoreInterface* policy_store) {
- if (cache_->has_device_policy()) {
- scoped_ptr<DictionaryValue> policies(cache_->GetDevicePolicy());
- ApplyPolicyValueTree(policies.get(), policy_store);
- } else {
- ApplyPolicyMap(cache_->GetMandatoryPolicy(), policy_store);
- // TODO(jkummerow, mnissler): provide recommended policy.
- }
- return true;
-}
-
-bool DeviceManagementPolicyProvider::IsInitializationComplete() const {
- return !cache_->last_policy_refresh_time().is_null();
-}
-
-void DeviceManagementPolicyProvider::HandlePolicyResponse(
- const em::DevicePolicyResponse& response) {
- DCHECK(TokenAvailable());
- if (cache_->SetDevicePolicy(response)) {
- initial_fetch_done_ = true;
- NotifyCloudPolicyUpdate();
- }
- SetState(STATE_POLICY_VALID);
-}
-
-void DeviceManagementPolicyProvider::HandleCloudPolicyResponse(
- const em::CloudPolicyResponse& response) {
- DCHECK(TokenAvailable());
- if (cache_->SetPolicy(response)) {
- initial_fetch_done_ = true;
- NotifyCloudPolicyUpdate();
- }
- SetState(STATE_POLICY_VALID);
-}
-
-void DeviceManagementPolicyProvider::OnError(
- DeviceManagementBackend::ErrorCode code) {
- DCHECK(TokenAvailable());
- if (code == DeviceManagementBackend::kErrorServiceDeviceNotFound ||
- code == DeviceManagementBackend::kErrorServiceManagementTokenInvalid) {
- LOG(WARNING) << "The device token was either invalid or unknown to the "
- << "device manager, re-registering device.";
- SetState(STATE_TOKEN_RESET);
- } else if (code ==
- DeviceManagementBackend::kErrorServiceManagementNotSupported) {
- VLOG(1) << "The device is no longer managed, resetting device token.";
- SetState(STATE_TOKEN_RESET);
- } else if (!fallback_to_old_protocol_ &&
- code == DeviceManagementBackend::kErrorRequestInvalid) {
- LOG(WARNING) << "Device management server doesn't understand new protocol,"
- << " falling back to old request.";
- fallback_to_old_protocol_ = true;
- SetState(STATE_TOKEN_VALID); // Triggers SendPolicyRequest() immediately.
- } else {
- LOG(WARNING) << "Could not provide policy from the device manager (error = "
- << code << "), will retry in "
- << (effective_policy_refresh_error_delay_ms_ / 1000)
- << " seconds.";
- SetState(STATE_POLICY_ERROR);
- }
-}
-
-void DeviceManagementPolicyProvider::OnTokenSuccess() {
- DCHECK(!TokenAvailable());
- SetState(STATE_TOKEN_VALID);
-}
-
-void DeviceManagementPolicyProvider::OnTokenError() {
- DCHECK(!TokenAvailable());
- LOG(WARNING) << "Could not retrieve device token.";
- SetState(STATE_TOKEN_ERROR);
-}
-
-void DeviceManagementPolicyProvider::OnNotManaged() {
- DCHECK(!TokenAvailable());
- VLOG(1) << "This device is not managed.";
- cache_->SetUnmanaged();
- SetState(STATE_UNMANAGED);
-}
-
-void DeviceManagementPolicyProvider::SetRefreshRate(
- int64 refresh_rate_milliseconds) {
- policy_refresh_rate_ms_ = refresh_rate_milliseconds;
-
- // Reschedule the refresh task if necessary.
- if (state_ == STATE_POLICY_VALID)
- SetState(STATE_POLICY_VALID);
-}
-
-DeviceManagementPolicyProvider::DeviceManagementPolicyProvider(
- const PolicyDefinitionList* policy_list,
- DeviceManagementBackend* backend,
- Profile* profile,
- int64 policy_refresh_rate_ms,
- int policy_refresh_deviation_factor_percent,
- int64 policy_refresh_deviation_max_ms,
- int64 policy_refresh_error_delay_ms,
- int64 token_fetch_error_delay_ms,
- int64 unmanaged_device_refresh_rate_ms)
- : ConfigurationPolicyProvider(policy_list) {
- Initialize(backend,
- profile,
- policy_refresh_rate_ms,
- policy_refresh_deviation_factor_percent,
- policy_refresh_deviation_max_ms,
- policy_refresh_error_delay_ms,
- token_fetch_error_delay_ms,
- unmanaged_device_refresh_rate_ms);
-}
-
-void DeviceManagementPolicyProvider::Initialize(
- DeviceManagementBackend* backend,
- Profile* profile,
- int64 policy_refresh_rate_ms,
- int policy_refresh_deviation_factor_percent,
- int64 policy_refresh_deviation_max_ms,
- int64 policy_refresh_error_delay_ms,
- int64 token_fetch_error_delay_ms,
- int64 unmanaged_device_refresh_rate_ms) {
- DCHECK(profile);
- backend_.reset(backend);
- profile_ = profile;
- fallback_to_old_protocol_ = false;
- storage_dir_ = GetOrCreateDeviceManagementDir(profile_->GetPath());
- state_ = STATE_INITIALIZING;
- initial_fetch_done_ = false;
- refresh_task_ = NULL;
- policy_refresh_rate_ms_ = policy_refresh_rate_ms;
- policy_refresh_deviation_factor_percent_ =
- policy_refresh_deviation_factor_percent;
- policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms;
- policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
- effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
- token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
- effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
- unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
-
- const FilePath policy_path = storage_dir_.Append(kPolicyFilename);
- cache_.reset(new CloudPolicyCache(policy_path));
- cache_->LoadPolicyFromFile();
-
- SetDeviceTokenFetcher(new DeviceTokenFetcher(backend_.get(), profile,
- GetTokenPath()));
-
- if (cache_->is_unmanaged()) {
- // This is a non-first login on an unmanaged device.
- SetState(STATE_UNMANAGED);
- } else {
- SetState(STATE_INITIALIZING);
- }
-}
-
-void DeviceManagementPolicyProvider::AddObserver(
- ConfigurationPolicyProvider::Observer* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void DeviceManagementPolicyProvider::RemoveObserver(
- ConfigurationPolicyProvider::Observer* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
-void DeviceManagementPolicyProvider::SendPolicyRequest() {
- if (!fallback_to_old_protocol_) {
- em::CloudPolicyRequest policy_request;
- policy_request.set_policy_scope(kChromePolicyScope);
- backend_->ProcessCloudPolicyRequest(token_fetcher_->GetDeviceToken(),
- token_fetcher_->GetDeviceID(),
- policy_request, this);
- } else {
- em::DevicePolicyRequest policy_request;
- policy_request.set_policy_scope(kChromePolicyScope);
- em::DevicePolicySettingRequest* setting =
- policy_request.add_setting_request();
- setting->set_key(kChromeDevicePolicySettingKey);
- setting->set_watermark("");
- backend_->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(),
- token_fetcher_->GetDeviceID(),
- policy_request, this);
- }
-}
-
-void DeviceManagementPolicyProvider::RefreshTaskExecute() {
- DCHECK(refresh_task_);
- refresh_task_ = NULL;
-
- switch (state_) {
- case STATE_INITIALIZING:
- token_fetcher_->StartFetching();
- return;
- case STATE_TOKEN_VALID:
- case STATE_POLICY_VALID:
- case STATE_POLICY_ERROR:
- SendPolicyRequest();
- return;
- case STATE_UNMANAGED:
- case STATE_TOKEN_ERROR:
- case STATE_TOKEN_RESET:
- token_fetcher_->Restart();
- return;
- }
-
- NOTREACHED() << "Unhandled state";
-}
-
-void DeviceManagementPolicyProvider::CancelRefreshTask() {
- if (refresh_task_) {
- refresh_task_->Cancel();
- refresh_task_ = NULL;
- }
-}
-
-void DeviceManagementPolicyProvider::NotifyCloudPolicyUpdate() {
- FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
- observer_list_,
- OnUpdatePolicy());
-}
-
-FilePath DeviceManagementPolicyProvider::GetTokenPath() {
- return storage_dir_.Append(kDeviceTokenFilename);
-}
-
-void DeviceManagementPolicyProvider::SetDeviceTokenFetcher(
- DeviceTokenFetcher* token_fetcher) {
- registrar_.Init(token_fetcher);
- registrar_.AddObserver(this);
- token_fetcher_ = token_fetcher;
-}
-
-void DeviceManagementPolicyProvider::SetState(
- DeviceManagementPolicyProvider::ProviderState new_state) {
- state_ = new_state;
-
- // If this state transition completes the initial policy fetch, let the
- // observers now.
- if (!initial_fetch_done_ &&
- new_state != STATE_INITIALIZING &&
- new_state != STATE_TOKEN_VALID) {
- initial_fetch_done_ = true;
- NotifyCloudPolicyUpdate();
- }
-
- base::Time now(base::Time::NowFromSystemTime());
- base::Time refresh_at;
- base::Time last_refresh(cache_->last_policy_refresh_time());
- if (last_refresh.is_null())
- last_refresh = now;
-
- // Determine when to take the next step.
- switch (state_) {
- case STATE_INITIALIZING:
- refresh_at = now;
- break;
- case STATE_TOKEN_VALID:
- effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;
- refresh_at = now;
- break;
- case STATE_TOKEN_RESET:
- refresh_at = now;
- break;
- case STATE_UNMANAGED:
- refresh_at = last_refresh +
- base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
- break;
- case STATE_POLICY_VALID:
- effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
- refresh_at =
- last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay());
- break;
- case STATE_TOKEN_ERROR:
- refresh_at = now + base::TimeDelta::FromMilliseconds(
- effective_token_fetch_error_delay_ms_);
- effective_token_fetch_error_delay_ms_ *= 2;
- if (effective_token_fetch_error_delay_ms_ > policy_refresh_rate_ms_)
- effective_token_fetch_error_delay_ms_ = policy_refresh_rate_ms_;
- break;
- case STATE_POLICY_ERROR:
- refresh_at = now + base::TimeDelta::FromMilliseconds(
- effective_policy_refresh_error_delay_ms_);
- effective_policy_refresh_error_delay_ms_ *= 2;
- if (effective_policy_refresh_error_delay_ms_ > policy_refresh_rate_ms_)
- effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
- break;
- }
-
- // Update the refresh task.
- CancelRefreshTask();
- if (!refresh_at.is_null()) {
- refresh_task_ = new RefreshTask(this);
- int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0);
- BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, refresh_task_,
- delay);
- }
-}
-
-int64 DeviceManagementPolicyProvider::GetRefreshDelay() {
- int64 deviation = (policy_refresh_deviation_factor_percent_ *
- policy_refresh_rate_ms_) / 100;
- deviation = std::min(deviation, policy_refresh_deviation_max_ms_);
- return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1);
-}
-
-bool DeviceManagementPolicyProvider::TokenAvailable() const {
- return state_ == STATE_TOKEN_VALID ||
- state_ == STATE_POLICY_VALID ||
- state_ == STATE_POLICY_ERROR;
-}
-
-// static
-std::string DeviceManagementPolicyProvider::GetDeviceManagementURL() {
- return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kDeviceManagementUrl);
-}
-
-// static
-FilePath DeviceManagementPolicyProvider::GetOrCreateDeviceManagementDir(
- const FilePath& user_data_dir) {
- const FilePath device_management_dir = user_data_dir.Append(
- FILE_PATH_LITERAL("Device Management"));
- if (!file_util::DirectoryExists(device_management_dir)) {
- if (!file_util::CreateDirectory(device_management_dir))
- NOTREACHED();
- }
- return device_management_dir;
-}
-
-} // namespace policy
diff --git a/chrome/browser/policy/device_management_policy_provider.h b/chrome/browser/policy/device_management_policy_provider.h
deleted file mode 100644
index dd09628..0000000
--- a/chrome/browser/policy/device_management_policy_provider.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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_DEVICE_MANAGEMENT_POLICY_PROVIDER_H_
-#define CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_PROVIDER_H_
-#pragma once
-
-#include <string>
-
-#include "base/file_path.h"
-#include "base/observer_list.h"
-#include "base/scoped_ptr.h"
-#include "base/time.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
-#include "chrome/browser/policy/device_management_backend.h"
-#include "chrome/browser/policy/device_token_fetcher.h"
-
-class Profile;
-class TokenService;
-
-namespace policy {
-
-class CloudPolicyCache;
-class DeviceManagementBackend;
-
-// Provides policy fetched from the device management server. With the exception
-// of the Provide method, which can be called on the FILE thread, all public
-// methods must be called on the UI thread.
-class DeviceManagementPolicyProvider
- : public ConfigurationPolicyProvider,
- public DeviceManagementBackend::DevicePolicyResponseDelegate,
- public DeviceTokenFetcher::Observer {
- public:
- DeviceManagementPolicyProvider(const PolicyDefinitionList* policy_list,
- DeviceManagementBackend* backend,
- Profile* profile);
-
- virtual ~DeviceManagementPolicyProvider();
-
- // ConfigurationPolicyProvider implementation:
- virtual bool Provide(ConfigurationPolicyStoreInterface* store);
- virtual bool IsInitializationComplete() const;
-
- // DevicePolicyResponseDelegate implementation:
- virtual void HandlePolicyResponse(
- const em::DevicePolicyResponse& response); // deprecated.
- virtual void HandleCloudPolicyResponse(
- const em::CloudPolicyResponse& response);
- virtual void OnError(DeviceManagementBackend::ErrorCode code);
-
- // DeviceTokenFetcher::Observer implementation:
- virtual void OnTokenSuccess();
- virtual void OnTokenError();
- virtual void OnNotManaged();
-
- // Sets the refresh rate at which to re-fetch policy information.
- void SetRefreshRate(int64 refresh_rate_milliseconds);
-
- private:
- // Indicates the current state the provider is in.
- enum ProviderState {
- // The provider is initializing, policy information not yet available.
- STATE_INITIALIZING,
- // This device is not managed through policy.
- STATE_UNMANAGED,
- // The token is valid, but policy is yet to be fetched.
- STATE_TOKEN_VALID,
- // Policy information is available and valid.
- STATE_POLICY_VALID,
- // The token was found to be invalid and needs to be obtained again.
- STATE_TOKEN_RESET,
- // There has been an error fetching the token, retry later.
- STATE_TOKEN_ERROR,
- // The service returned an error when requesting policy, ask again later.
- STATE_POLICY_ERROR,
- };
-
- class RefreshTask;
-
- friend class DeviceManagementPolicyProviderTest;
-
- // More configurable constructor for use by test cases.
- DeviceManagementPolicyProvider(const PolicyDefinitionList* policy_list,
- DeviceManagementBackend* backend,
- Profile* profile,
- int64 policy_refresh_rate_ms,
- int policy_refresh_deviation_factor_percent,
- int64 policy_refresh_deviation_max_ms,
- int64 policy_refresh_error_delay_ms,
- int64 token_fetch_error_delay_ms,
- int64 unmanaged_device_refresh_rate_ms);
-
- // Called by constructors to perform shared initialization. Initialization
- // requiring the IOThread must not be performed directly in this method,
- // rather must be deferred until the IOThread is fully initialized. This is
- // the case in InitializeAfterIOThreadExists.
- void Initialize(DeviceManagementBackend* backend,
- Profile* profile,
- int64 policy_refresh_rate_ms,
- int policy_refresh_deviation_factor_percent,
- int64 policy_refresh_deviation_max_ms,
- int64 policy_refresh_error_delay_ms,
- int64 token_fetch_error_delay_ms,
- int64 unmanaged_device_refresh_rate_ms);
-
- // ConfigurationPolicyProvider overrides:
- virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer);
- virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer);
-
- // Sends a request to the device manager backend to fetch policy if one isn't
- // already outstanding.
- void SendPolicyRequest();
-
- // Triggers policy refresh, re-requesting device token and policy information
- // as necessary.
- void RefreshTaskExecute();
-
- // Cancels the refresh task.
- void CancelRefreshTask();
-
- // Notify observers about a policy update.
- void NotifyCloudPolicyUpdate();
-
- // The path of the device token file.
- FilePath GetTokenPath();
-
- // Used only by tests.
- void SetDeviceTokenFetcher(DeviceTokenFetcher* token_fetcher);
-
- // Switches to a new state and triggers any appropriate actions.
- void SetState(ProviderState new_state);
-
- // Check whether the current state is one in which the token is available.
- bool TokenAvailable() const;
-
- // Computes the refresh delay to use.
- int64 GetRefreshDelay();
-
- // Provides the URL at which requests are sent to from the device management
- // backend.
- static std::string GetDeviceManagementURL();
-
- // Returns the path to the sub-directory in the user data directory
- // in which device management persistent state is stored.
- static FilePath GetOrCreateDeviceManagementDir(
- const FilePath& user_data_dir);
-
- scoped_ptr<DeviceManagementBackend> backend_;
- Profile* profile_; // weak
- scoped_ptr<CloudPolicyCache> cache_;
- bool fallback_to_old_protocol_;
- scoped_refptr<DeviceTokenFetcher> token_fetcher_;
- DeviceTokenFetcher::ObserverRegistrar registrar_;
- ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_;
- FilePath storage_dir_;
- ProviderState state_;
- bool initial_fetch_done_;
- RefreshTask* refresh_task_;
- int64 policy_refresh_rate_ms_;
- int policy_refresh_deviation_factor_percent_;
- int64 policy_refresh_deviation_max_ms_;
- int64 policy_refresh_error_delay_ms_;
- int64 effective_policy_refresh_error_delay_ms_;
- int64 token_fetch_error_delay_ms_;
- int64 effective_token_fetch_error_delay_ms_;
- int64 unmanaged_device_refresh_rate_ms_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyProvider);
-};
-
-} // namespace policy
-
-#endif // CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_PROVIDER_H_
diff --git a/chrome/browser/policy/device_management_policy_provider_unittest.cc b/chrome/browser/policy/device_management_policy_provider_unittest.cc
deleted file mode 100644
index 8dc3bf4..0000000
--- a/chrome/browser/policy/device_management_policy_provider_unittest.cc
+++ /dev/null
@@ -1,382 +0,0 @@
-// 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 "base/file_util.h"
-#include "base/message_loop.h"
-#include "base/scoped_temp_dir.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/net/gaia/token_service.h"
-#include "chrome/browser/policy/cloud_policy_cache.h"
-#include "chrome/browser/policy/configuration_policy_pref_store.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
-#include "chrome/browser/policy/device_management_policy_provider.h"
-#include "chrome/browser/policy/mock_configuration_policy_store.h"
-#include "chrome/browser/policy/mock_device_management_backend.h"
-#include "chrome/common/net/gaia/gaia_constants.h"
-#include "chrome/common/notification_observer_mock.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/test/testing_device_token_fetcher.h"
-#include "chrome/test/testing_profile.h"
-#include "policy/policy_constants.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-const char kTestToken[] = "device_policy_provider_test_auth_token";
-
-namespace policy {
-
-using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::InSequence;
-using ::testing::Mock;
-
-class MockConfigurationPolicyObserver
- : public ConfigurationPolicyProvider::Observer {
- public:
- MOCK_METHOD0(OnUpdatePolicy, void());
- void OnProviderGoingAway() {}
-};
-
-class DeviceManagementPolicyProviderTest : public testing::Test {
- public:
- DeviceManagementPolicyProviderTest()
- : ui_thread_(BrowserThread::UI, &loop_),
- file_thread_(BrowserThread::FILE, &loop_) {}
-
- virtual ~DeviceManagementPolicyProviderTest() {}
-
- virtual void SetUp() {
- profile_.reset(new TestingProfile);
- CreateNewProvider();
- EXPECT_TRUE(waiting_for_initial_policies());
- loop_.RunAllPending();
- }
-
- void CreateNewProvider() {
- backend_ = new MockDeviceManagementBackend;
- provider_.reset(new DeviceManagementPolicyProvider(
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
- backend_,
- profile_.get()));
- provider_->SetDeviceTokenFetcher(
- new TestingDeviceTokenFetcher(backend_,
- profile_.get(),
- provider_->GetTokenPath()));
- }
-
- void CreateNewProvider(int64 policy_refresh_rate_ms,
- int policy_refresh_fuzz_factor_percent,
- int64 policy_refresh_fuzz_max,
- int64 policy_refresh_error_delay_ms,
- int64 token_fetch_error_delay_ms,
- int64 unmanaged_device_refresh_rate_ms) {
- backend_ = new MockDeviceManagementBackend;
- provider_.reset(new DeviceManagementPolicyProvider(
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
- backend_,
- profile_.get(),
- policy_refresh_rate_ms,
- policy_refresh_fuzz_factor_percent,
- policy_refresh_fuzz_max,
- policy_refresh_error_delay_ms,
- token_fetch_error_delay_ms,
- unmanaged_device_refresh_rate_ms));
- provider_->SetDeviceTokenFetcher(
- new TestingDeviceTokenFetcher(backend_,
- profile_.get(),
- provider_->GetTokenPath()));
- }
-
- FilePath GetTokenPath() const {
- return provider_->GetTokenPath();
- }
-
- void SimulateSuccessfulLoginAndRunPending() {
- // Make sure the notification for the initial policy fetch is generated.
- MockConfigurationPolicyObserver observer;
- ConfigurationPolicyObserverRegistrar registrar;
- registrar.Init(provider_.get(), &observer);
- EXPECT_CALL(observer, OnUpdatePolicy()).Times(AtLeast(1));
-
- loop_.RunAllPending();
- profile_->GetTokenService()->IssueAuthTokenForTest(
- GaiaConstants::kDeviceManagementService, kTestToken);
- TestingDeviceTokenFetcher* fetcher =
- static_cast<TestingDeviceTokenFetcher*>(
- provider_->token_fetcher_.get());
- fetcher->SimulateLogin(kTestManagedDomainUsername);
- loop_.RunAllPending();
- }
-
- void SimulateSuccessfulInitialPolicyFetch() {
- MockConfigurationPolicyStore store;
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- SimulateSuccessfulLoginAndRunPending();
- EXPECT_FALSE(waiting_for_initial_policies());
- EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(1);
- provider_->Provide(&store);
- ASSERT_EQ(1U, store.policy_map().size());
- Mock::VerifyAndClearExpectations(backend_);
- Mock::VerifyAndClearExpectations(&store);
- }
-
- virtual void TearDown() {
- provider_.reset();
- loop_.RunAllPending();
- }
-
- bool waiting_for_initial_policies() const {
- return !provider_->IsInitializationComplete();
- }
-
- MockDeviceManagementBackend* backend_; // weak
- scoped_ptr<DeviceManagementPolicyProvider> provider_;
-
- protected:
- CloudPolicyCache* cache(DeviceManagementPolicyProvider* provider) {
- return provider->cache_.get();
- }
-
- MessageLoop loop_;
-
- private:
- BrowserThread ui_thread_;
- BrowserThread file_thread_;
- scoped_ptr<Profile> profile_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyProviderTest);
-};
-
-// If there's no login and no previously-fetched policy, the provider should
-// provide an empty policy.
-TEST_F(DeviceManagementPolicyProviderTest, InitialProvideNoLogin) {
- MockConfigurationPolicyStore store;
- EXPECT_CALL(store, Apply(_, _)).Times(0);
- provider_->Provide(&store);
- EXPECT_TRUE(store.policy_map().empty());
- EXPECT_TRUE(waiting_for_initial_policies());
-}
-
-// If the login is successful and there's no previously-fetched policy, the
-// policy should be fetched from the server and should be available the first
-// time the Provide method is called.
-TEST_F(DeviceManagementPolicyProviderTest, InitialProvideWithLogin) {
- EXPECT_TRUE(waiting_for_initial_policies());
- SimulateSuccessfulInitialPolicyFetch();
-}
-
-// If the login succeed but the device management backend is unreachable,
-// there should be no policy provided if there's no previously-fetched policy,
-TEST_F(DeviceManagementPolicyProviderTest, EmptyProvideWithFailedBackend) {
- MockConfigurationPolicyStore store;
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailRegister(
- DeviceManagementBackend::kErrorRequestFailed));
- EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).Times(0);
- SimulateSuccessfulLoginAndRunPending();
- EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(0);
- provider_->Provide(&store);
- EXPECT_TRUE(store.policy_map().empty());
-}
-
-// If a policy has been fetched previously, if should be available even before
-// the login succeeds or the device management backend is available.
-TEST_F(DeviceManagementPolicyProviderTest, SecondProvide) {
- // Pre-fetch and persist a policy
- SimulateSuccessfulInitialPolicyFetch();
-
- // Simulate a app relaunch by constructing a new provider. Policy should be
- // refreshed (since that might be the purpose of the app relaunch).
- CreateNewProvider();
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- loop_.RunAllPending();
- Mock::VerifyAndClearExpectations(backend_);
-
- // Simulate another app relaunch, this time against a failing backend.
- // Cached policy should still be available.
- MockConfigurationPolicyStore store;
- CreateNewProvider();
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorRequestFailed));
- SimulateSuccessfulLoginAndRunPending();
- EXPECT_CALL(store, Apply(kPolicyDisableSpdy, _)).Times(1);
- provider_->Provide(&store);
- ASSERT_EQ(1U, store.policy_map().size());
-}
-
-// When policy is successfully fetched from the device management server, it
-// should force a policy refresh.
-TEST_F(DeviceManagementPolicyProviderTest, FetchTriggersRefresh) {
- MockConfigurationPolicyObserver observer;
- ConfigurationPolicyObserverRegistrar registrar;
- registrar.Init(provider_.get(), &observer);
- EXPECT_CALL(observer, OnUpdatePolicy()).Times(1);
- SimulateSuccessfulInitialPolicyFetch();
-}
-
-TEST_F(DeviceManagementPolicyProviderTest, ErrorCausesNewRequest) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- CreateNewProvider(1000 * 1000, 0, 0, 0, 0, 0);
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailRegister(
- DeviceManagementBackend::kErrorRequestFailed));
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorRequestFailed));
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorRequestFailed));
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- }
- SimulateSuccessfulLoginAndRunPending();
-}
-
-TEST_F(DeviceManagementPolicyProviderTest, RefreshPolicies) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- CreateNewProvider(0, 0, 0, 1000 * 1000, 1000, 0);
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorRequestFailed));
- }
- SimulateSuccessfulLoginAndRunPending();
-}
-
-// The client should try to re-register the device if the device server reports
-// back that it doesn't recognize the device token on a policy request.
-TEST_F(DeviceManagementPolicyProviderTest, DeviceNotFound) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorServiceDeviceNotFound));
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- }
- SimulateSuccessfulLoginAndRunPending();
-}
-
-// The client should try to re-register the device if the device server reports
-// back that the device token is invalid on a policy request.
-TEST_F(DeviceManagementPolicyProviderTest, InvalidTokenOnPolicyRequest) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- }
- SimulateSuccessfulLoginAndRunPending();
-}
-
-// If the client is successfully managed, but the admin stops managing the
-// device, the client should notice and throw away the device token and id.
-TEST_F(DeviceManagementPolicyProviderTest, DeviceNoLongerManaged) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- CreateNewProvider(0, 0, 0, 0, 0, 1000 * 1000);
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorServiceManagementNotSupported));
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailRegister(
- DeviceManagementBackend::kErrorServiceManagementNotSupported));
- }
- SimulateSuccessfulLoginAndRunPending();
- FilePath token_path(GetTokenPath());
- EXPECT_FALSE(file_util::PathExists(token_path));
-}
-
-// This test tests three things (see numbered comments below):
-TEST_F(DeviceManagementPolicyProviderTest, UnmanagedDevice) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailRegister(
- DeviceManagementBackend::kErrorServiceManagementNotSupported));
- }
- SimulateSuccessfulLoginAndRunPending();
- // (1) The provider's DMPolicyCache should know that the device is not
- // managed.
- EXPECT_TRUE(cache(provider_.get())->is_unmanaged());
- // (2) On restart, the provider should detect that this is not the first
- // login.
- CreateNewProvider(1000 * 1000, 0, 0, 0, 0, 0);
- EXPECT_FALSE(waiting_for_initial_policies());
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedSpdyCloudPolicy());
- }
- SimulateSuccessfulLoginAndRunPending();
- // (3) Since the backend call this time returned a device id, the "unmanaged"
- // marker should have been deleted.
- EXPECT_FALSE(cache(provider_.get())->is_unmanaged());
-}
-
-TEST_F(DeviceManagementPolicyProviderTest, FallbackToOldProtocol) {
- { // Scoping so SimulateSuccessfulLoginAndRunPending doesn't see the sequence.
- InSequence s;
- CreateNewProvider(0, 0, 0, 0, 0, 1000 * 1000);
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- // If the CloudPolicyRequest fails with kErrorRequestInvalid...
- EXPECT_CALL(*backend_, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorRequestInvalid));
- // ...the client should fall back to a classic PolicyRequest...
- EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedBooleanPolicy(
- key::kDisableSpdy, true));
- // ...and remember this fallback for any future request, ...
- EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorHttpStatus));
- // ...both after successful fetches and after errors.
- EXPECT_CALL(*backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorServiceManagementNotSupported));
- // Finally, we set the client to 'unmanaged' to stop its request stream.
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailRegister(
- DeviceManagementBackend::kErrorServiceManagementNotSupported));
- }
- SimulateSuccessfulLoginAndRunPending();
-}
-
-} // namespace policy
diff --git a/chrome/browser/policy/device_management_service.h b/chrome/browser/policy/device_management_service.h
index 76a3520..c5f5869 100644
--- a/chrome/browser/policy/device_management_service.h
+++ b/chrome/browser/policy/device_management_service.h
@@ -51,7 +51,8 @@ class DeviceManagementService : public URLFetcher::Delegate {
// Constructs a device management backend for use by client code. Ownership of
// the returned backend object is transferred to the caller.
- DeviceManagementBackend* CreateBackend();
+ // Marked virtual for the benefit of tests.
+ virtual DeviceManagementBackend* CreateBackend();
// Provides the backend with a request context so it can make actual network
// requests. This will also fire any requests queued earlier.
diff --git a/chrome/browser/policy/device_policy_identity_strategy.cc b/chrome/browser/policy/device_policy_identity_strategy.cc
new file mode 100644
index 0000000..0f19945
--- /dev/null
+++ b/chrome/browser/policy/device_policy_identity_strategy.cc
@@ -0,0 +1,114 @@
+// 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/device_policy_identity_strategy.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/login/ownership_service.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+
+namespace policy {
+
+DevicePolicyIdentityStrategy::DevicePolicyIdentityStrategy()
+ : should_register_(false) {
+ registrar_.Add(this,
+ NotificationType::TOKEN_AVAILABLE,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::LOGIN_USER_CHANGED,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::OWNERSHIP_TAKEN,
+ 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";
+}
+
+std::string DevicePolicyIdentityStrategy::GetDeviceToken() {
+ return device_token_;
+}
+
+std::string DevicePolicyIdentityStrategy::GetDeviceID() {
+ return machine_id_;
+}
+
+bool DevicePolicyIdentityStrategy::GetCredentials(std::string* username,
+ std::string* auth_token) {
+ // Only register if requested.
+ if (!should_register_)
+ return false;
+
+ // 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 (!chromeos::OwnershipService::GetSharedInstance()->CurrentUserIsOwner())
+ 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);
+
+ return !username->empty() && !auth_token->empty();
+}
+
+void DevicePolicyIdentityStrategy::OnDeviceTokenAvailable(
+ const std::string& token) {
+ DCHECK(!machine_id_.empty());
+
+ // Reset registration flag, so we only attempt registration once.
+ should_register_ = false;
+
+ device_token_ = token;
+ NotifyDeviceTokenChanged();
+}
+
+void DevicePolicyIdentityStrategy::CheckAndTriggerFetch() {
+ std::string username;
+ std::string auth_token;
+ if (GetCredentials(&username, &auth_token))
+ 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)
+ CheckAndTriggerFetch();
+ } else if (type == NotificationType::LOGIN_USER_CHANGED) {
+ should_register_ = false;
+ CheckAndTriggerFetch();
+ } else if (type == NotificationType::OWNERSHIP_TAKEN) {
+ should_register_ = true;
+ CheckAndTriggerFetch();
+ } else if (type == NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
+ CheckAndTriggerFetch();
+ } else {
+ NOTREACHED();
+ }
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/device_policy_identity_strategy.h b/chrome/browser/policy/device_policy_identity_strategy.h
new file mode 100644
index 0000000..838124d
--- /dev/null
+++ b/chrome/browser/policy/device_policy_identity_strategy.h
@@ -0,0 +1,62 @@
+// 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_DEVICE_POLICY_IDENTITY_STRATEGY_H_
+#define CHROME_BROWSER_POLICY_DEVICE_POLICY_IDENTITY_STRATEGY_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/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 {
+ public:
+ DevicePolicyIdentityStrategy();
+ virtual ~DevicePolicyIdentityStrategy() {}
+
+ // CloudPolicyIdentityStrategy implementation:
+ virtual std::string GetDeviceToken();
+ virtual std::string GetDeviceID();
+ virtual bool GetCredentials(std::string* username,
+ std::string* auth_token);
+ virtual void OnDeviceTokenAvailable(const std::string& token);
+
+ private:
+ // Recheck whether all parameters are available and if so, trigger a
+ // credentials changed notification.
+ void CheckAndTriggerFetch();
+
+ // NotificationObserver method overrides:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // The machine identifier.
+ std::string machine_id_;
+
+ // Current token. Empty if not available.
+ std::string device_token_;
+
+ // Whether to try and register. Device policy enrollment does not happen
+ // automatically except for the case that the device gets claimed. This
+ // situation is detected by listening for the OWNERSHIP_TAKEN notification.
+ bool should_register_;
+
+ // Registers the provider for notification of successful Gaia logins.
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevicePolicyIdentityStrategy);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_DEVICE_POLICY_IDENTITY_STRATEGY_H_
diff --git a/chrome/browser/policy/device_token_fetcher.cc b/chrome/browser/policy/device_token_fetcher.cc
index 3f977c1..6661d3c 100644
--- a/chrome/browser/policy/device_token_fetcher.cc
+++ b/chrome/browser/policy/device_token_fetcher.cc
@@ -4,52 +4,19 @@
#include "chrome/browser/policy/device_token_fetcher.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/singleton.h"
-#include "base/string_util.h"
-#include "chrome/browser/net/gaia/token_service.h"
-#include "chrome/browser/policy/proto/device_management_local.pb.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/guid.h"
-#include "chrome/common/net/gaia/gaia_constants.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
+#include <algorithm>
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/user_manager.h"
-#else
-#include "chrome/browser/browser_signin.h"
-#endif
+#include "base/message_loop.h"
+#include "chrome/browser/policy/cloud_policy_cache.h"
+#include "chrome/browser/policy/device_management_service.h"
+#include "chrome/browser/policy/proto/device_management_local.pb.h"
namespace {
-// Domain names that are known not to be managed.
-// We don't register the device when such a user logs in.
-const char* kNonManagedDomains[] = {
- "@googlemail.com",
- "@gmail.com"
-};
-
-// Checks the domain part of the given username against the list of known
-// non-managed domain names. Returns false if |username| is empty or its
-// in a domain known not to be managed.
-bool CanBeInManagedDomain(const std::string& username) {
- if (username.empty()) {
- // This means incognito user in case of ChromiumOS and
- // no logged-in user in case of Chromium (SigninService).
- return false;
- }
- for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) {
- if (EndsWith(username, kNonManagedDomains[i], true)) {
- return false;
- }
- }
- return true;
-}
+// Retry after 3 seconds (with exponential backoff) after token fetch errors.
+const int64 kTokenFetchErrorDelayMilliseconds = 3 * 1000;
+// For unmanaged devices, check once per day whether they're still unmanaged.
+const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000;
} // namespace
@@ -57,284 +24,155 @@ namespace policy {
namespace em = enterprise_management;
-DeviceTokenFetcher::ObserverRegistrar::ObserverRegistrar() {}
-
-DeviceTokenFetcher::ObserverRegistrar::~ObserverRegistrar() {
- RemoveAll();
+DeviceTokenFetcher::DeviceTokenFetcher(
+ DeviceManagementService* service,
+ CloudPolicyCache* cache)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ Initialize(service,
+ cache,
+ kTokenFetchErrorDelayMilliseconds,
+ kUnmanagedDeviceRefreshRateMilliseconds);
}
-void DeviceTokenFetcher::ObserverRegistrar::Init(
- DeviceTokenFetcher* token_fetcher) {
- RemoveAll();
- token_fetcher_ = token_fetcher;
+DeviceTokenFetcher::DeviceTokenFetcher(
+ DeviceManagementService* service,
+ CloudPolicyCache* cache,
+ int64 token_fetch_error_delay_ms,
+ int64 unmanaged_device_refresh_rate_ms)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ Initialize(service,
+ cache,
+ token_fetch_error_delay_ms,
+ unmanaged_device_refresh_rate_ms);
}
-void DeviceTokenFetcher::ObserverRegistrar::AddObserver(
- DeviceTokenFetcher::Observer* observer) {
- observers_.push_back(observer);
- token_fetcher_->AddObserver(observer);
+DeviceTokenFetcher::~DeviceTokenFetcher() {
+ CancelRetryTask();
}
-void DeviceTokenFetcher::ObserverRegistrar::RemoveAll() {
- for (std::vector<DeviceTokenFetcher::Observer*>::iterator it =
- observers_.begin(); it != observers_.end(); ++it) {
- token_fetcher_->RemoveObserver(*it);
- }
- observers_.clear();
+void DeviceTokenFetcher::FetchToken(const std::string& auth_token,
+ const std::string& device_id) {
+ SetState(STATE_INACTIVE);
+ auth_token_ = auth_token;
+ device_id_ = device_id;
+ FetchTokenInternal();
}
-DeviceTokenFetcher::DeviceTokenFetcher(
- DeviceManagementBackend* backend,
- Profile* profile,
- const FilePath& token_path)
- : profile_(profile),
- token_path_(token_path),
- backend_(backend),
- state_(kStateNotStarted),
- device_token_load_complete_event_(true, false) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- TokenService* token_service = profile_->GetTokenService();
- auth_token_ = token_service->GetTokenForService(
- GaiaConstants::kDeviceManagementService);
-
- registrar_.Add(this,
- NotificationType::TOKEN_AVAILABLE,
- Source<TokenService>(token_service));
- // Register for the event of user login. The device management token won't
- // be fetched until we know the domain of the currently logged in user.
-#if defined(OS_CHROMEOS)
- registrar_.Add(this,
- NotificationType::LOGIN_USER_CHANGED,
- NotificationService::AllSources());
-#else
- registrar_.Add(this,
- NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
- Source<Profile>(profile_));
-#endif
+void DeviceTokenFetcher::FetchTokenInternal() {
+ DCHECK(state_ != STATE_TOKEN_AVAILABLE);
+ DCHECK(!auth_token_.empty() && !device_id_.empty());
+ // Construct a new backend, which will discard any previous requests.
+ backend_.reset(service_->CreateBackend());
+ em::DeviceRegisterRequest request;
+ backend_->ProcessRegisterRequest(auth_token_, device_id_, request, this);
}
-DeviceTokenFetcher::~DeviceTokenFetcher() {}
+const std::string& DeviceTokenFetcher::GetDeviceToken() {
+ return device_token_;
+}
-void DeviceTokenFetcher::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (type == NotificationType::TOKEN_AVAILABLE) {
- if (Source<TokenService>(source).ptr() == profile_->GetTokenService()) {
- const TokenService::TokenAvailableDetails* token_details =
- Details<const TokenService::TokenAvailableDetails>(details).ptr();
- if (token_details->service() == GaiaConstants::kDeviceManagementService) {
- if (!HasAuthToken()) {
- auth_token_ = token_details->token();
- SendServerRequestIfPossible();
- }
- }
- }
-#if defined(OS_CHROMEOS)
- } else if (type == NotificationType::LOGIN_USER_CHANGED) {
- SendServerRequestIfPossible();
-#else
- } else if (type == NotificationType::GOOGLE_SIGNIN_SUCCESSFUL) {
- if (profile_ == Source<Profile>(source).ptr()) {
- SendServerRequestIfPossible();
- }
-#endif
- } else {
- NOTREACHED();
- }
+void DeviceTokenFetcher::AddObserver(DeviceTokenFetcher::Observer* observer) {
+ observer_list_.AddObserver(observer);
}
-std::string DeviceTokenFetcher::GetCurrentUser() {
-#if defined(OS_CHROMEOS)
- return chromeos::UserManager::Get()->logged_in_user().email();
-#else
- return profile_->GetBrowserSignin()->GetSignedInUsername();
-#endif
+void DeviceTokenFetcher::RemoveObserver(
+ DeviceTokenFetcher::Observer* observer) {
+ observer_list_.RemoveObserver(observer);
}
void DeviceTokenFetcher::HandleRegisterResponse(
const em::DeviceRegisterResponse& response) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(kStateRequestingDeviceTokenFromServer, state_);
if (response.has_device_management_token()) {
device_token_ = response.device_management_token();
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- NewRunnableFunction(&WriteDeviceTokenToDisk,
- token_path_,
- device_token_,
- device_id_));
- SetState(kStateHasDeviceToken);
+ SetState(STATE_TOKEN_AVAILABLE);
} else {
NOTREACHED();
- SetState(kStateFailure);
+ SetState(STATE_ERROR);
}
}
void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // For privacy reasons, delete all identifying data when this device is not
- // managed.
if (code == DeviceManagementBackend::kErrorServiceManagementNotSupported) {
- device_token_ = std::string();
- device_id_ = std::string();
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- // The Windows compiler needs explicit template instantiation.
- NewRunnableFunction<bool(*)(const FilePath&, bool), FilePath, bool>(
- &file_util::Delete, token_path_, false));
- SetState(kStateNotManaged);
- return;
+ cache_->SetUnmanaged();
+ SetState(STATE_UNMANAGED);
}
- SetState(kStateFailure);
+ SetState(STATE_ERROR);
}
-void DeviceTokenFetcher::Restart() {
- // Complain if there's currently an asynchronous operation going on.
- DCHECK(state_ == kStateNotStarted ||
- state_ == kStateHasDeviceToken ||
- state_ == kStateFailure ||
- state_ == kStateNotManaged);
- device_token_.clear();
- device_token_load_complete_event_.Reset();
- MakeReadyToRequestDeviceToken();
-}
+void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
+ CloudPolicyCache* cache,
+ int64 token_fetch_error_delay_ms,
+ int64 unmanaged_device_refresh_rate_ms) {
+ service_ = service;
+ cache_ = cache;
+ token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
+ effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms;
+ unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms;
+ state_ = STATE_INACTIVE;
+ retry_task_ = NULL;
-void DeviceTokenFetcher::StartFetching() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (state_ == kStateNotStarted) {
- SetState(kStateLoadDeviceTokenFromDisk);
- // The file calls for loading the persisted token must be deferred to the
- // FILE thread.
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- NewRunnableMethod(this,
- &DeviceTokenFetcher::AttemptTokenLoadFromDisk));
- }
-}
-
-void DeviceTokenFetcher::AttemptTokenLoadFromDisk() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- if (file_util::PathExists(token_path_)) {
- std::string data;
- em::DeviceCredentials device_credentials;
- if (file_util::ReadFileToString(token_path_, &data) &&
- device_credentials.ParseFromArray(data.c_str(), data.size())) {
- device_token_ = device_credentials.device_token();
- device_id_ = device_credentials.device_id();
- if (!device_token_.empty() && !device_id_.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- NewRunnableMethod(this,
- &DeviceTokenFetcher::SetState,
- kStateHasDeviceToken));
- return;
- }
- }
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- NewRunnableMethod(this,
- &DeviceTokenFetcher::MakeReadyToRequestDeviceToken));
-}
-
-void DeviceTokenFetcher::MakeReadyToRequestDeviceToken() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SetState(kStateReadyToRequestDeviceTokenFromServer);
- SendServerRequestIfPossible();
-}
-
-void DeviceTokenFetcher::SendServerRequestIfPossible() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::string username = GetCurrentUser();
- if (state_ == kStateReadyToRequestDeviceTokenFromServer
- && HasAuthToken()
- && backend_
- && !username.empty()) {
- if (CanBeInManagedDomain(username)) {
- em::DeviceRegisterRequest register_request;
- SetState(kStateRequestingDeviceTokenFromServer);
- backend_->ProcessRegisterRequest(auth_token_,
- GetDeviceID(),
- register_request,
- this);
- } else {
- SetState(kStateNotManaged);
- }
- }
-}
-
-bool DeviceTokenFetcher::IsTokenPending() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return !device_token_load_complete_event_.IsSignaled();
-}
-
-std::string DeviceTokenFetcher::GetDeviceToken() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- device_token_load_complete_event_.Wait();
- return device_token_;
-}
-
-std::string DeviceTokenFetcher::GetDeviceID() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // As long as access to this is only allowed from the UI thread, no explicit
- // locking is necessary to prevent the ID from being generated twice.
- if (device_id_.empty())
- device_id_ = GenerateNewDeviceID();
- return device_id_;
+ if (cache_->is_unmanaged())
+ SetState(STATE_UNMANAGED);
}
void DeviceTokenFetcher::SetState(FetcherState state) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (state_ == state)
- return;
state_ = state;
- if (state == kStateFailure) {
- device_token_load_complete_event_.Signal();
- NotifyTokenError();
- } else if (state == kStateNotManaged) {
- device_token_load_complete_event_.Signal();
- NotifyNotManaged();
- } else if (state == kStateHasDeviceToken) {
- device_token_load_complete_event_.Signal();
- NotifyTokenSuccess();
+ if (state_ != STATE_ERROR)
+ effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_;
+
+ base::Time delayed_work_at;
+ switch (state_) {
+ case STATE_INACTIVE:
+ device_token_.clear();
+ auth_token_.clear();
+ device_id_.clear();
+ break;
+ case STATE_TOKEN_AVAILABLE:
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceTokenAvailable());
+ break;
+ case STATE_UNMANAGED:
+ delayed_work_at = cache_->last_policy_refresh_time() +
+ base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_);
+ break;
+ case STATE_ERROR:
+ delayed_work_at = base::Time::Now() +
+ base::TimeDelta::FromMilliseconds(
+ effective_token_fetch_error_delay_ms_);
+ effective_token_fetch_error_delay_ms_ *= 2;
+ break;
}
-}
-void DeviceTokenFetcher::GetDeviceTokenPath(FilePath* token_path) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- *token_path = token_path_;
+ CancelRetryTask();
+ if (!delayed_work_at.is_null()) {
+ base::Time now(base::Time::Now());
+ int64 delay = std::max<int64>((delayed_work_at - now).InMilliseconds(), 0);
+ retry_task_ = method_factory_.NewRunnableMethod(
+ &DeviceTokenFetcher::ExecuteRetryTask);
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, retry_task_,
+ delay);
+ }
}
-bool DeviceTokenFetcher::IsTokenValid() const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return state_ == kStateHasDeviceToken;
-}
+void DeviceTokenFetcher::ExecuteRetryTask() {
+ DCHECK(retry_task_);
+ retry_task_ = NULL;
-// static
-void DeviceTokenFetcher::WriteDeviceTokenToDisk(
- const FilePath& path,
- const std::string& device_token,
- const std::string& device_id) {
- em::DeviceCredentials device_credentials;
- device_credentials.set_device_token(device_token);
- device_credentials.set_device_id(device_id);
- std::string data;
- bool no_error = device_credentials.SerializeToString(&data);
- DCHECK(no_error);
- file_util::WriteFile(path, data.c_str(), data.length());
+ switch (state_) {
+ case STATE_INACTIVE:
+ case STATE_TOKEN_AVAILABLE:
+ break;
+ case STATE_UNMANAGED:
+ case STATE_ERROR:
+ FetchTokenInternal();
+ break;
+ }
}
-// static
-std::string DeviceTokenFetcher::GenerateNewDeviceID() {
- return guid::GenerateGUID();
+void DeviceTokenFetcher::CancelRetryTask() {
+ if (retry_task_) {
+ retry_task_->Cancel();
+ retry_task_ = NULL;
+ }
}
} // namespace policy
diff --git a/chrome/browser/policy/device_token_fetcher.h b/chrome/browser/policy/device_token_fetcher.h
index ae22f3d..0501433 100644
--- a/chrome/browser/policy/device_token_fetcher.h
+++ b/chrome/browser/policy/device_token_fetcher.h
@@ -7,20 +7,17 @@
#pragma once
#include <string>
-#include <vector>
-#include "base/file_path.h"
#include "base/observer_list.h"
-#include "base/ref_counted.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
#include "chrome/browser/policy/device_management_backend.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-
-class Profile;
namespace policy {
+class CloudPolicyCache;
+class DeviceManagementService;
+
namespace em = enterprise_management;
// Fetches the device token that can be used for policy requests with the device
@@ -29,170 +26,112 @@ namespace em = enterprise_management;
// fetcher is shared as a singleton by all users of the device management token
// to ensure they all get the same token.
class DeviceTokenFetcher
- : public NotificationObserver,
- public DeviceManagementBackend::DeviceRegisterResponseDelegate,
- public base::RefCountedThreadSafe<DeviceTokenFetcher> {
+ : public DeviceManagementBackend::DeviceRegisterResponseDelegate {
public:
class Observer {
public:
- virtual void OnTokenSuccess() = 0;
- virtual void OnTokenError() = 0;
- virtual void OnNotManaged() = 0;
virtual ~Observer() {}
+ virtual void OnDeviceTokenAvailable() = 0;
};
- class ObserverRegistrar {
- public:
- ObserverRegistrar();
- ~ObserverRegistrar();
-
- void Init(DeviceTokenFetcher* token_fetcher);
- void AddObserver(DeviceTokenFetcher::Observer* observer);
- void RemoveAll();
- private:
- DeviceTokenFetcher* token_fetcher_;
- std::vector<DeviceTokenFetcher::Observer*> observers_;
- };
-
- // Requests to the device management server are sent through |backend|. It
- // obtains the authentication token from |token_service|. The fetcher stores
- // the device token to |token_path| once it's retrieved from the server.
- DeviceTokenFetcher(DeviceManagementBackend* backend,
- Profile* profile,
- const FilePath& token_path);
+ // |service| is used to talk to the device management service and |cache| is
+ // used to persist whether the device is unmanaged.
+ DeviceTokenFetcher(DeviceManagementService* service,
+ CloudPolicyCache* cache);
+ // Version for tests that allows to set timing paramters.
+ DeviceTokenFetcher(DeviceManagementService* service,
+ CloudPolicyCache* cache,
+ int64 token_fetch_error_delay_ms,
+ int64 unmanaged_device_refresh_rate_ms);
virtual ~DeviceTokenFetcher();
- // NotificationObserver method overrides:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
+ // Starts fetching a token.
+ // Declared virtual so it can be overridden by mocks.
+ virtual void FetchToken(const std::string& auth_token,
+ const std::string& device_id);
+
+ // Returns the device management token or the empty string if not available.
+ // Declared virtual so it can be overridden by mocks.
+ virtual const std::string& GetDeviceToken();
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
// DeviceManagementBackend::DeviceRegisterResponseDelegate method overrides:
virtual void HandleRegisterResponse(
const em::DeviceRegisterResponse& response);
virtual void OnError(DeviceManagementBackend::ErrorCode code);
- // Re-initializes this DeviceTokenFetcher
- void Restart();
-
- // Called by subscribers of the device management token to indicate that they
- // will need the token in the future. Must be called on the UI thread.
- void StartFetching();
-
- // Returns true if there is a pending token request to the device management
- // server.
- bool IsTokenPending();
-
- // Returns the device management token for this device, blocking until
- // outstanding requests to the device management server are satisfied. In the
- // case that the token could not be fetched, an empty string is returned.
- std::string GetDeviceToken();
-
- // Returns the device ID for this device. If no such ID has been set yet, a
- // new ID is generated and returned.
- std::string GetDeviceID();
-
- // True if the fetcher has a valid AuthToken for the device management server.
- bool HasAuthToken() const { return !auth_token_.empty(); }
-
- // True if the device token has been fetched and is valid.
- bool IsTokenValid() const;
-
- protected:
- // Returns the email address of the currently logged-in user.
- virtual std::string GetCurrentUser();
-
- // Used to identify GOOGLE_SIGNIN_SUCCESSFUL notifications from the owning
- // profile, and to query for the current username.
- Profile* profile_; // weak
-
private:
friend class DeviceTokenFetcherTest;
// The different states that the fetcher can be in during the process of
- // getting the device token.
+ // getting the device token. |state_| is initialized to INACTIVE, depending
+ // on the result of a token fetching attempt can transition to either of
+ // TOKEN_AVAILABLE, UNMANAGED, or ERROR. The first attempt must be triggered
+ // externally. When |state_| is UNMANAGED, a new fetching attempt is
+ // performed every |unmanaged_device_refresh_rate_ms_|; when it's ERROR,
+ // a new attempt is done after |effective_token_fetch_error_delay_ms_|.
enum FetcherState {
- kStateNotStarted,
- kStateLoadDeviceTokenFromDisk,
- kStateReadyToRequestDeviceTokenFromServer,
- kStateRequestingDeviceTokenFromServer,
- kStateHasDeviceToken,
- kStateFailure,
- kStateNotManaged,
+ // Fetcher inactive.
+ STATE_INACTIVE,
+ // Token available.
+ STATE_TOKEN_AVAILABLE,
+ // Device unmanaged.
+ STATE_UNMANAGED,
+ // Error, retry later.
+ STATE_ERROR,
};
- // Moves the fetcher into a new state. If the fetcher has the device token
- // or is moving into the failure state, callers waiting on WaitForToken
- // are unblocked.
- void SetState(FetcherState state);
-
- // Returns the full path to the file that persists the device manager token.
- void GetDeviceTokenPath(FilePath* token_path) const;
-
- // Tries to load the device token from disk. Must be called on the FILE
- // thread.
- void AttemptTokenLoadFromDisk();
-
- // Called if it's not possible to load the device token from disk. Sets the
- // fetcher in a state that's ready to register the device with the device
- // management server and receive the device token in return. If the AuthToken
- // for the device management server is available, initiate the server
- // request.
- void MakeReadyToRequestDeviceToken();
-
- // Issues a registration request to the server if both the fetcher is in the
- // ready-to-request state and the device management server AuthToken is
- // available.
- void SendServerRequestIfPossible();
+ // Common initialization helper.
+ void Initialize(DeviceManagementService* service,
+ CloudPolicyCache* cache,
+ int64 token_fetch_error_delay_ms,
+ int64 unmanaged_device_refresh_rate_ms);
- void AddObserver(Observer* obs) {
- observer_list_.AddObserver(obs);
- }
+ // Moves the fetcher into a new state.
+ void SetState(FetcherState state);
- void RemoveObserver(Observer* obs) {
- observer_list_.RemoveObserver(obs);
- }
+ // Resets |backend_|, then uses |auth_token_| and |device_id_| to perform
+ // an actual token fetch.
+ void FetchTokenInternal();
- void NotifyTokenSuccess() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnTokenSuccess());
- }
+ // Called back from the |retry_task_|.
+ void ExecuteRetryTask();
- void NotifyTokenError() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnTokenError());
- }
+ // Cancels the |retry_task_|.
+ void CancelRetryTask();
- void NotifyNotManaged() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnNotManaged());
- }
+ // Service and backend. A new backend is created whenever the fetcher gets
+ // reset.
+ DeviceManagementService* service_; // weak
+ scoped_ptr<DeviceManagementBackend> backend_;
- // Saves the device management token to disk once it has been retrieved from
- // the server. Must be called on the FILE thread.
- static void WriteDeviceTokenToDisk(const FilePath& path,
- const std::string& token,
- const std::string& device_id);
+ // Reference to the cache. Used to persist and read unmanaged state.
+ CloudPolicyCache* cache_;
- // Generates a new device ID used to register the device with the device
- // management server and generate the device token.
- static std::string GenerateNewDeviceID();
+ // Refresh parameters.
+ int64 token_fetch_error_delay_ms_;
+ int64 effective_token_fetch_error_delay_ms_;
+ int64 unmanaged_device_refresh_rate_ms_;
- ObserverList<Observer, true> observer_list_;
- FilePath token_path_;
- DeviceManagementBackend* backend_; // weak
+ // State the fetcher is currently in.
FetcherState state_;
+
+ // Current device token.
std::string device_token_;
- std::string device_id_;
- // Contains the AuthToken for the device management server. Empty if the
- // AuthToken hasn't been issued yet or that was an error getting the
- // AuthToken.
+ // Contains the AuthToken for the device management server.
std::string auth_token_;
+ // Device identifier to send to the server.
+ std::string device_id_;
+
+ // Task that has been scheduled to retry fetching a token.
+ CancelableTask* retry_task_;
- // An event that is signaled only once the device token has been fetched
- // or it has been determined that there was an error during fetching.
- base::WaitableEvent device_token_load_complete_event_;
+ ScopedRunnableMethodFactory<DeviceTokenFetcher> method_factory_;
- // Registers the fetcher for notification of successful Gaia logins.
- NotificationRegistrar registrar_;
+ ObserverList<Observer, true> observer_list_;
};
} // namespace policy
diff --git a/chrome/browser/policy/device_token_fetcher_unittest.cc b/chrome/browser/policy/device_token_fetcher_unittest.cc
index 28d11b0..f87265d 100644
--- a/chrome/browser/policy/device_token_fetcher_unittest.cc
+++ b/chrome/browser/policy/device_token_fetcher_unittest.cc
@@ -1,18 +1,18 @@
-// 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 <string>
+#include "chrome/browser/policy/device_token_fetcher.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/scoped_temp_dir.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/net/gaia/token_service.h"
-#include "chrome/browser/policy/device_token_fetcher.h"
+#include "chrome/browser/policy/cloud_policy_cache.h"
+#include "chrome/browser/policy/device_management_service.h"
#include "chrome/browser/policy/mock_device_management_backend.h"
#include "chrome/common/net/gaia/gaia_constants.h"
-#include "chrome/test/testing_device_token_fetcher.h"
#include "chrome/test/testing_profile.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,223 +29,170 @@ class MockTokenAvailableObserver : public DeviceTokenFetcher::Observer {
MockTokenAvailableObserver() {}
virtual ~MockTokenAvailableObserver() {}
- MOCK_METHOD0(OnTokenSuccess, void());
- MOCK_METHOD0(OnTokenError, void());
- MOCK_METHOD0(OnNotManaged, void());
+ MOCK_METHOD0(OnDeviceTokenAvailable, void());
private:
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);
+ }
+ virtual void ProcessCloudPolicyRequest(
+ const std::string& device_management_token,
+ const std::string& device_id,
+ const em::CloudPolicyRequest& request,
+ DevicePolicyResponseDelegate* delegate) {
+ backend_->ProcessCloudPolicyRequest(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()
: ui_thread_(BrowserThread::UI, &loop_),
file_thread_(BrowserThread::FILE, &loop_) {
EXPECT_TRUE(temp_user_data_dir_.CreateUniqueTempDir());
- fetcher_ = NewTestFetcher(temp_user_data_dir_.path());
- fetcher_->StartFetching();
}
- virtual void TearDown() {
- backend_.reset();
- profile_.reset();
- loop_.RunAllPending();
+ virtual void SetUp() {
+ cache_.reset(new CloudPolicyCache(
+ temp_user_data_dir_.path().AppendASCII("DeviceTokenFetcherTest")));
+ service_.set_backend(&backend_);
}
- void SimulateSuccessfulLoginAndRunPending(const std::string& username) {
- loop_.RunAllPending();
- profile_->GetTokenService()->IssueAuthTokenForTest(
- GaiaConstants::kDeviceManagementService, kTestToken);
- fetcher_->SimulateLogin(username);
+ virtual void TearDown() {
loop_.RunAllPending();
}
- TestingDeviceTokenFetcher* NewTestFetcher(const FilePath& token_dir) {
- profile_.reset(new TestingProfile());
- backend_.reset(new MockDeviceManagementBackend());
- return new TestingDeviceTokenFetcher(
- backend_.get(),
- profile_.get(),
- token_dir.Append(FILE_PATH_LITERAL("test-token-file.txt")));
- }
-
- static void GetDeviceTokenPath(const DeviceTokenFetcher* fetcher,
- FilePath* path) {
- fetcher->GetDeviceTokenPath(path);
- }
-
- const std::string& device_id(const DeviceTokenFetcher* fetcher) {
- return fetcher->device_id_;
- }
-
MessageLoop loop_;
- scoped_ptr<MockDeviceManagementBackend> backend_;
+ MockDeviceManagementBackend backend_;
+ MockDeviceManagementService service_;
+ scoped_ptr<CloudPolicyCache> cache_;
ScopedTempDir temp_user_data_dir_;
- scoped_refptr<TestingDeviceTokenFetcher> fetcher_;
- scoped_ptr<Profile> profile_;
private:
BrowserThread ui_thread_;
BrowserThread file_thread_;
};
-TEST_F(DeviceTokenFetcherTest, IsPending) {
- ASSERT_TRUE(fetcher_->IsTokenPending());
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+TEST_F(DeviceTokenFetcherTest, FetchToken) {
+ testing::InSequence s;
+ EXPECT_CALL(backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedRegister());
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
-}
-
-TEST_F(DeviceTokenFetcherTest, StoreAndLoad) {
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- std::string device_token = fetcher_->GetDeviceToken();
- std::string device_id = fetcher_->GetDeviceID();
- ASSERT_NE("", device_id);
-
- FilePath token_path;
- GetDeviceTokenPath(fetcher_, &token_path);
- scoped_refptr<DeviceTokenFetcher> fetcher2(
- new TestingDeviceTokenFetcher(
- backend_.get(), profile_.get(), token_path));
- fetcher2->StartFetching();
+ DeviceTokenFetcher fetcher(&service_, cache_.get());
+ MockTokenAvailableObserver observer;
+ EXPECT_CALL(observer, OnDeviceTokenAvailable());
+ fetcher.AddObserver(&observer);
+ EXPECT_EQ("", fetcher.GetDeviceToken());
+ fetcher.FetchToken("fake_auth_token", "fake_device_id");
loop_.RunAllPending();
- ASSERT_EQ(device_id, fetcher2->GetDeviceID());
- ASSERT_EQ(device_token, fetcher2->GetDeviceToken());
-}
-
-TEST_F(DeviceTokenFetcherTest, SimpleFetchSingleLogin) {
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- ASSERT_TRUE(fetcher_->IsTokenValid());
- const std::string token(fetcher_->GetDeviceToken());
- EXPECT_NE("", token);
-}
-
-TEST_F(DeviceTokenFetcherTest, SimpleFetchDoubleLogin) {
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- const std::string token(fetcher_->GetDeviceToken());
+ Mock::VerifyAndClearExpectations(&observer);
+ std::string token = fetcher.GetDeviceToken();
EXPECT_NE("", token);
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- const std::string token2(fetcher_->GetDeviceToken());
- EXPECT_NE("", token2);
- EXPECT_EQ(token, token2);
-}
-
-TEST_F(DeviceTokenFetcherTest, FetchBetweenBrowserLaunchAndNotify) {
- MockTokenAvailableObserver observer;
- DeviceTokenFetcher::ObserverRegistrar registrar;
- registrar.Init(fetcher_);
- registrar.AddObserver(&observer);
- EXPECT_CALL(observer, OnTokenSuccess()).Times(1);
- EXPECT_CALL(observer, OnTokenError()).Times(0);
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+ // Calling FetchToken() again should result in a new token being fetched.
+ EXPECT_CALL(backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedRegister());
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- const std::string token(fetcher_->GetDeviceToken());
- EXPECT_NE("", token);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Swap out the fetchers, including copying the device management token on
- // disk to where the new fetcher expects it.
- registrar.RemoveAll();
- fetcher_ = NewTestFetcher(temp_user_data_dir_.path());
- registrar.Init(fetcher_);
- fetcher_->StartFetching();
- ASSERT_TRUE(fetcher_->IsTokenPending());
+ EXPECT_CALL(observer, OnDeviceTokenAvailable());
+ fetcher.FetchToken("fake_auth_token", "fake_device_id");
loop_.RunAllPending();
- ASSERT_FALSE(fetcher_->IsTokenPending());
- const std::string token2(fetcher_->GetDeviceToken());
+ Mock::VerifyAndClearExpectations(&observer);
+ std::string token2 = fetcher.GetDeviceToken();
EXPECT_NE("", token2);
- EXPECT_EQ(token, token2);
+ EXPECT_NE(token, token2);
+ fetcher.RemoveObserver(&observer);
}
-TEST_F(DeviceTokenFetcherTest, FailedServerRequest) {
- MockTokenAvailableObserver observer;
- DeviceTokenFetcher::ObserverRegistrar registrar;
- registrar.Init(fetcher_);
- registrar.AddObserver(&observer);
- EXPECT_CALL(observer, OnTokenSuccess()).Times(0);
- EXPECT_CALL(observer, OnTokenError()).Times(1);
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+TEST_F(DeviceTokenFetcherTest, RetryOnError) {
+ testing::InSequence s;
+ EXPECT_CALL(backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailRegister(
- DeviceManagementBackend::kErrorRequestFailed));
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- const std::string token(fetcher_->GetDeviceToken());
- EXPECT_EQ("", token);
+ DeviceManagementBackend::kErrorRequestFailed)).WillOnce(
+ MockDeviceManagementBackendSucceedRegister());
+ DeviceTokenFetcher fetcher(&service_, cache_.get(), 0, 0);
+ MockTokenAvailableObserver observer;
+ EXPECT_CALL(observer, OnDeviceTokenAvailable());
+ fetcher.AddObserver(&observer);
+ fetcher.FetchToken("fake_auth_token", "fake_device_id");
+ loop_.RunAllPending();
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_NE("", fetcher.GetDeviceToken());
+ fetcher.RemoveObserver(&observer);
}
TEST_F(DeviceTokenFetcherTest, UnmanagedDevice) {
- FilePath token_path;
- GetDeviceTokenPath(fetcher_, &token_path);
- file_util::WriteFile(token_path, "foo", 3);
- ASSERT_TRUE(file_util::PathExists(token_path));
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailRegister(
DeviceManagementBackend::kErrorServiceManagementNotSupported));
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- ASSERT_EQ("", fetcher_->GetDeviceToken());
- ASSERT_EQ("", device_id(fetcher_));
- ASSERT_FALSE(file_util::PathExists(token_path));
-}
-
-
-TEST_F(DeviceTokenFetcherTest, FetchBetweenTokenNotifyAndLoginNotify) {
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(0);
-
- // Simulate an available token, but without available user name.
- loop_.RunAllPending();
- profile_->GetTokenService()->IssueAuthTokenForTest(
- GaiaConstants::kDeviceManagementService, kTestToken);
- loop_.RunAllPending();
-
- ASSERT_TRUE(fetcher_->IsTokenPending());
- ASSERT_FALSE(fetcher_->IsTokenValid());
-}
-
-TEST_F(DeviceTokenFetcherTest, FetchWithNonManagedUsername) {
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).Times(0);
- SimulateSuccessfulLoginAndRunPending("___@gmail.com");
- ASSERT_FALSE(fetcher_->IsTokenPending());
- ASSERT_FALSE(fetcher_->IsTokenValid());
-}
-
-TEST_F(DeviceTokenFetcherTest, RestartImmediately) {
- // Create a token.
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- SimulateSuccessfulLoginAndRunPending(kTestManagedDomainUsername);
- ASSERT_FALSE(fetcher_->IsTokenPending());
- std::string device_token = fetcher_->GetDeviceToken();
-
- // Restart a new fetcher immediately without calling StartFetching(). The
- // existing token should not be loaded, but rather a new token generated.
- FilePath token_path;
- GetDeviceTokenPath(fetcher_, &token_path);
- scoped_refptr<TestingDeviceTokenFetcher> fetcher2(
- new TestingDeviceTokenFetcher(
- backend_.get(), profile_.get(), token_path));
- fetcher2->Restart();
- EXPECT_CALL(*backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedRegister());
- fetcher2->SimulateLogin(kTestManagedDomainUsername);
+ EXPECT_FALSE(cache_->is_unmanaged());
+ DeviceTokenFetcher fetcher(&service_, cache_.get());
+ MockTokenAvailableObserver observer;
+ EXPECT_CALL(observer, OnDeviceTokenAvailable()).Times(0);
+ fetcher.AddObserver(&observer);
+ fetcher.FetchToken("fake_auth_token", "fake_device_id");
loop_.RunAllPending();
- ASSERT_FALSE(fetcher2->IsTokenPending());
- ASSERT_NE(device_token, fetcher2->GetDeviceToken());
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_EQ("", fetcher.GetDeviceToken());
+ EXPECT_TRUE(cache_->is_unmanaged());
+ fetcher.RemoveObserver(&observer);
}
} // namespace policy
diff --git a/chrome/browser/policy/profile_policy_connector.cc b/chrome/browser/policy/profile_policy_connector.cc
new file mode 100644
index 0000000..ac22603
--- /dev/null
+++ b/chrome/browser/policy/profile_policy_connector.cc
@@ -0,0 +1,100 @@
+// 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 <algorithm>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "chrome/browser/policy/cloud_policy_subsystem.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
+#include "chrome/browser/policy/user_policy_identity_strategy.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/url_request_context_getter.h"
+#include "chrome/common/pref_names.h"
+
+namespace {
+
+const FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("Device Management");
+const FilePath::CharType kTokenCacheFile[] = FILE_PATH_LITERAL("Token");
+const FilePath::CharType kPolicyCacheFile[] = FILE_PATH_LITERAL("Policy");
+
+} // namespace
+
+namespace policy {
+
+ProfilePolicyConnector::ProfilePolicyConnector(Profile* profile)
+ : profile_(profile) {
+ // TODO(mnissler): We access the file system here. The cloud policy context
+ // below needs to do so anyway, since it needs to read the policy cache from
+ // disk. If this proves to be a problem, we need to do this initialization
+ // asynchronously on the file thread and put in synchronization that allows us
+ // to wait for the cache to be read during the browser startup code paths.
+ // Another option would be to provide a generic IO-safe initializer called
+ // from the PrefService that we could hook up with through the policy
+ // provider.
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
+ FilePath policy_cache_dir(profile_->GetPath());
+ policy_cache_dir = policy_cache_dir.Append(kPolicyDir);
+ if (!file_util::CreateDirectory(policy_cache_dir)) {
+ LOG(WARNING) << "Failed to create policy state dir "
+ << policy_cache_dir.value()
+ << ", skipping cloud policy initialization.";
+ return;
+ }
+
+ identity_strategy_.reset(new UserPolicyIdentityStrategy(
+ profile_,
+ policy_cache_dir.Append(kTokenCacheFile)));
+ cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
+ policy_cache_dir.Append(kPolicyCacheFile),
+ identity_strategy_.get()));
+ }
+}
+
+ProfilePolicyConnector::~ProfilePolicyConnector() {
+ cloud_policy_subsystem_.reset();
+ identity_strategy_.reset();
+}
+
+void ProfilePolicyConnector::Initialize() {
+ // TODO(jkummerow, mnissler): Move this out of the browser startup path.
+ if (cloud_policy_subsystem_.get()) {
+ cloud_policy_subsystem_->Initialize(profile_->GetPrefs(),
+ prefs::kPolicyUserPolicyRefreshRate,
+ profile_->GetRequestContext());
+ }
+}
+
+void ProfilePolicyConnector::Shutdown() {
+ if (cloud_policy_subsystem_.get())
+ cloud_policy_subsystem_->Shutdown();
+}
+
+ConfigurationPolicyProvider*
+ ProfilePolicyConnector::GetManagedCloudProvider() {
+ if (cloud_policy_subsystem_.get())
+ return cloud_policy_subsystem_->GetManagedPolicyProvider();
+
+ return NULL;
+}
+
+ConfigurationPolicyProvider*
+ ProfilePolicyConnector::GetRecommendedCloudProvider() {
+ if (cloud_policy_subsystem_.get())
+ return cloud_policy_subsystem_->GetRecommendedPolicyProvider();
+
+ return NULL;
+}
+
+// static
+void ProfilePolicyConnector::RegisterPrefs(PrefService* user_prefs) {
+ user_prefs->RegisterIntegerPref(prefs::kPolicyUserPolicyRefreshRate,
+ kDefaultPolicyRefreshRateInMilliseconds);
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/profile_policy_connector.h b/chrome/browser/policy/profile_policy_connector.h
new file mode 100644
index 0000000..f65d077
--- /dev/null
+++ b/chrome/browser/policy/profile_policy_connector.h
@@ -0,0 +1,56 @@
+// 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_PROFILE_POLICY_CONNECTOR_H_
+#define CHROME_BROWSER_POLICY_PROFILE_POLICY_CONNECTOR_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+
+class Profile;
+
+namespace policy {
+
+class CloudPolicySubsystem;
+class ConfigurationPolicyProvider;
+class UserPolicyIdentityStrategy;
+
+// This class is a container for the profile-specific policy bits located in the
+// profile. Since the subsystem owns the policy provider, it's vital that it
+// gets initialized before the profile's prefs and destroyed after the prefs
+// are gone.
+class ProfilePolicyConnector {
+ public:
+ explicit ProfilePolicyConnector(Profile* profile);
+ ~ProfilePolicyConnector();
+
+ // Initializes the context. Should be called only after the profile's request
+ // context is up.
+ void Initialize();
+
+ // Shuts the context down. This must be called before the networking
+ // infrastructure in the profile goes away.
+ void Shutdown();
+
+ ConfigurationPolicyProvider* GetManagedCloudProvider();
+ ConfigurationPolicyProvider* GetRecommendedCloudProvider();
+
+ static void RegisterPrefs(PrefService* user_prefs);
+
+ static const int kDefaultPolicyRefreshRateInMilliseconds =
+ 3 * 60 * 60 * 1000; // 3 hours.
+
+ private:
+ Profile* profile_;
+
+ scoped_ptr<UserPolicyIdentityStrategy> identity_strategy_;
+ scoped_ptr<CloudPolicySubsystem> cloud_policy_subsystem_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfilePolicyConnector);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_PROFILE_POLICY_CONNECTOR_H_
diff --git a/chrome/browser/policy/profile_policy_context.cc b/chrome/browser/policy/profile_policy_context.cc
deleted file mode 100644
index b8e3151a..0000000
--- a/chrome/browser/policy/profile_policy_context.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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 <algorithm>
-#include <string>
-
-#include "base/command_line.h"
-#include "chrome/browser/policy/configuration_policy_pref_store.h"
-#include "chrome/browser/policy/device_management_policy_provider.h"
-#include "chrome/browser/policy/device_management_service.h"
-#include "chrome/browser/policy/profile_policy_context.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/pref_names.h"
-
-namespace {
-
-// Refresh rate sanity interval bounds.
-const int64 kPolicyRefreshRateMinMs = 30 * 60 * 1000; // 30 minutes
-const int64 kPolicyRefreshRateMaxMs = 24 * 60 * 60 * 1000; // 1 day
-
-} // namespace
-
-namespace policy {
-
-ProfilePolicyContext::ProfilePolicyContext(Profile* profile)
- : profile_(profile) {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
- device_management_service_.reset(new DeviceManagementService(
- command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl)));
- device_management_policy_provider_.reset(
- new policy::DeviceManagementPolicyProvider(
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
- device_management_service_->CreateBackend(),
- profile_));
- }
-}
-
-ProfilePolicyContext::~ProfilePolicyContext() {
- device_management_policy_provider_.reset();
- device_management_service_.reset();
-}
-
-void ProfilePolicyContext::Initialize() {
- if (device_management_service_.get())
- device_management_service_->Initialize(profile_->GetRequestContext());
-
- policy_refresh_rate_.Init(prefs::kPolicyRefreshRate, profile_->GetPrefs(),
- this);
- UpdatePolicyRefreshRate();
-}
-
-void ProfilePolicyContext::Shutdown() {
- if (device_management_service_.get())
- device_management_service_->Shutdown();
-}
-
-DeviceManagementPolicyProvider*
-ProfilePolicyContext::GetDeviceManagementPolicyProvider() {
- return device_management_policy_provider_.get();
-}
-
-// static
-void ProfilePolicyContext::RegisterUserPrefs(PrefService* user_prefs) {
- user_prefs->RegisterIntegerPref(prefs::kPolicyRefreshRate,
- kDefaultPolicyRefreshRateInMilliseconds);
-}
-
-void ProfilePolicyContext::UpdatePolicyRefreshRate() {
- if (device_management_policy_provider_.get()) {
- // Clamp to sane values.
- int64 refresh_rate = policy_refresh_rate_.GetValue();
- refresh_rate = std::max(kPolicyRefreshRateMinMs, refresh_rate);
- refresh_rate = std::min(kPolicyRefreshRateMaxMs, refresh_rate);
- device_management_policy_provider_->SetRefreshRate(refresh_rate);
- }
-}
-
-void ProfilePolicyContext::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (type == NotificationType::PREF_CHANGED &&
- prefs::kPolicyRefreshRate == *(Details<std::string>(details).ptr()) &&
- profile_->GetPrefs() == Source<PrefService>(source).ptr()) {
- UpdatePolicyRefreshRate();
- } else {
- NOTREACHED();
- }
-}
-
-} // namespace policy
diff --git a/chrome/browser/policy/profile_policy_context.h b/chrome/browser/policy/profile_policy_context.h
deleted file mode 100644
index 8650ec5..0000000
--- a/chrome/browser/policy/profile_policy_context.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2010 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_PROFILE_POLICY_CONTEXT_H_
-#define CHROME_BROWSER_POLICY_PROFILE_POLICY_CONTEXT_H_
-#pragma once
-
-#include "base/scoped_ptr.h"
-#include "chrome/browser/prefs/pref_member.h"
-#include "chrome/common/notification_observer.h"
-
-class Profile;
-
-namespace policy {
-
-class DeviceManagementPolicyProvider;
-class DeviceManagementService;
-
-// This class is a container for the profile-specific policy bits located in the
-// profile. Since the context owns the policy provider, it's vital that it gets
-// initialized before the profile's prefs and destroyed after the prefs are
-// gone.
-class ProfilePolicyContext : public NotificationObserver {
- public:
- explicit ProfilePolicyContext(Profile* profile);
- ~ProfilePolicyContext();
-
- // Initializes the context. Should be called only after the profile's request
- // context is up.
- void Initialize();
-
- // Shuts the context down. This must be called before the networking
- // infrastructure in the profile goes away.
- void Shutdown();
-
- // Get the policy provider.
- DeviceManagementPolicyProvider* GetDeviceManagementPolicyProvider();
-
- // Register preferences.
- static void RegisterUserPrefs(PrefService* user_prefs);
-
- static const int kDefaultPolicyRefreshRateInMilliseconds =
- 3 * 60 * 60 * 1000; // 3 hours.
-
- private:
- // Updates the policy provider with a new refresh rate value.
- void UpdatePolicyRefreshRate();
-
- // NotificationObserver overrides.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
- // The profile this context is associated with.
- Profile* profile_;
-
- // Tracks the pref value for the policy refresh rate.
- IntegerPrefMember policy_refresh_rate_;
-
- // The device management service.
- scoped_ptr<DeviceManagementService> device_management_service_;
-
- // Our provider.
- scoped_ptr<DeviceManagementPolicyProvider> device_management_policy_provider_;
-};
-
-} // namespace policy
-
-#endif // CHROME_BROWSER_POLICY_PROFILE_POLICY_CONTEXT_H_
diff --git a/chrome/browser/policy/user_policy_identity_strategy.cc b/chrome/browser/policy/user_policy_identity_strategy.cc
new file mode 100644
index 0000000..5270ca3
--- /dev/null
+++ b/chrome/browser/policy/user_policy_identity_strategy.cc
@@ -0,0 +1,236 @@
+// 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/user_policy_identity_strategy.h"
+
+#include "base/file_util.h"
+#include "chrome/browser/browser_signin.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/policy/proto/device_management_local.pb.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/guid.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_source.h"
+
+namespace policy {
+
+namespace em = enterprise_management;
+
+// Responsible for managing the on-disk token cache.
+class UserPolicyIdentityStrategy::TokenCache
+ : public base::RefCountedThreadSafe<
+ UserPolicyIdentityStrategy::TokenCache> {
+ public:
+ TokenCache(const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy,
+ const FilePath& cache_file);
+
+ void Load();
+ void Store(const std::string& token, const std::string& device_id);
+
+ private:
+ friend class base::RefCountedThreadSafe<
+ UserPolicyIdentityStrategy::TokenCache>;
+ ~TokenCache() {}
+ void LoadOnFileThread();
+ void NotifyOnUIThread(const std::string& token,
+ const std::string& device_id);
+ void StoreOnFileThread(const std::string& token,
+ const std::string& device_id);
+
+ const base::WeakPtr<UserPolicyIdentityStrategy> identity_strategy_;
+ const FilePath cache_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(TokenCache);
+};
+
+UserPolicyIdentityStrategy::TokenCache::TokenCache(
+ const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy,
+ const FilePath& cache_file)
+ : identity_strategy_(identity_strategy),
+ cache_file_(cache_file) {}
+
+void UserPolicyIdentityStrategy::TokenCache::Load() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this, &UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread));
+}
+
+void UserPolicyIdentityStrategy::TokenCache::Store(
+ const std::string& token,
+ const std::string& device_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread,
+ token,
+ device_id));
+}
+
+void UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ std::string device_token;
+ std::string device_id;
+
+ if (file_util::PathExists(cache_file_)) {
+ std::string data;
+ em::DeviceCredentials device_credentials;
+ if (file_util::ReadFileToString(cache_file_, &data) &&
+ device_credentials.ParseFromArray(data.c_str(), data.size())) {
+ device_token = device_credentials.device_token();
+ device_id = device_credentials.device_id();
+ }
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread,
+ device_token,
+ device_id));
+}
+
+void UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread(
+ const std::string& token,
+ const std::string& device_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (identity_strategy_.get())
+ identity_strategy_->OnCacheLoaded(token, device_id);
+}
+
+void UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread(
+ const std::string& token,
+ const std::string& device_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ em::DeviceCredentials device_credentials;
+ device_credentials.set_device_token(token);
+ device_credentials.set_device_id(device_id);
+ std::string data;
+ bool success = device_credentials.SerializeToString(&data);
+ if (!success) {
+ LOG(WARNING) << "Failed serialize device token data, will not write "
+ << cache_file_.value();
+ return;
+ }
+
+ file_util::WriteFile(cache_file_, data.c_str(), data.length());
+}
+
+UserPolicyIdentityStrategy::UserPolicyIdentityStrategy(
+ Profile* profile,
+ const FilePath& cache_file)
+ : profile_(profile),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+ cache_ = new TokenCache(weak_ptr_factory_.GetWeakPtr(), cache_file);
+ registrar_.Add(this,
+ NotificationType::TOKEN_AVAILABLE,
+ Source<TokenService>(profile->GetTokenService()));
+
+ // Register for the event of user login. The device management token won't
+ // be fetched until we know the domain of the currently logged in user.
+#if defined(OS_CHROMEOS)
+ registrar_.Add(this,
+ NotificationType::LOGIN_USER_CHANGED,
+ NotificationService::AllSources());
+#else
+ registrar_.Add(this,
+ NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
+ Source<Profile>(profile_));
+#endif
+
+ cache_->Load();
+}
+
+UserPolicyIdentityStrategy::~UserPolicyIdentityStrategy() {}
+
+std::string UserPolicyIdentityStrategy::GetDeviceToken() {
+ return device_token_;
+}
+
+std::string UserPolicyIdentityStrategy::GetDeviceID() {
+ return device_id_;
+}
+
+bool UserPolicyIdentityStrategy::GetCredentials(std::string* username,
+ std::string* auth_token) {
+ *username = GetCurrentUser();
+ *auth_token = profile_->GetTokenService()->GetTokenForService(
+ GaiaConstants::kDeviceManagementService);
+
+ return !username->empty() && !auth_token->empty() && !device_id_.empty();
+}
+
+void UserPolicyIdentityStrategy::OnDeviceTokenAvailable(
+ const std::string& token) {
+ DCHECK(!device_id_.empty());
+ device_token_ = token;
+ cache_->Store(device_token_, device_id_);
+ NotifyDeviceTokenChanged();
+}
+
+std::string UserPolicyIdentityStrategy::GetCurrentUser() {
+#if defined(OS_CHROMEOS)
+ // TODO(mnissler) On CrOS it seems impossible to figure out what user belongs
+ // to a profile. Revisit after multi-profile support landed.
+ return chromeos::UserManager::Get()->logged_in_user().email();
+#else
+ return profile_->GetBrowserSignin()->GetSignedInUsername();
+#endif
+}
+
+void UserPolicyIdentityStrategy::CheckAndTriggerFetch() {
+ if (!GetCurrentUser().empty() &&
+ profile_->GetTokenService()->HasTokenForService(
+ GaiaConstants::kDeviceManagementService)) {
+ // For user tokens, there is no actual identifier. We generate a random
+ // identifier instead each time we ask for the token.
+ device_id_ = guid::GenerateGUID();
+ NotifyAuthChanged();
+ }
+}
+
+void UserPolicyIdentityStrategy::OnCacheLoaded(const std::string& token,
+ const std::string& device_id) {
+ if (!token.empty() && !device_id.empty()) {
+ device_token_ = token;
+ device_id_ = device_id;
+ NotifyDeviceTokenChanged();
+ } else {
+ CheckAndTriggerFetch();
+ }
+}
+
+void UserPolicyIdentityStrategy::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (type == NotificationType::TOKEN_AVAILABLE) {
+ if (Source<TokenService>(source).ptr() == profile_->GetTokenService()) {
+ const TokenService::TokenAvailableDetails* token_details =
+ Details<const TokenService::TokenAvailableDetails>(details).ptr();
+ if (token_details->service() == GaiaConstants::kDeviceManagementService)
+ CheckAndTriggerFetch();
+ }
+#if defined(OS_CHROMEOS)
+ } else if (type == NotificationType::LOGIN_USER_CHANGED) {
+ CheckAndTriggerFetch();
+#else
+ } else if (type == NotificationType::GOOGLE_SIGNIN_SUCCESSFUL) {
+ if (profile_ == Source<Profile>(source).ptr())
+ CheckAndTriggerFetch();
+#endif
+ } else {
+ NOTREACHED();
+ }
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/user_policy_identity_strategy.h b/chrome/browser/policy/user_policy_identity_strategy.h
new file mode 100644
index 0000000..bf6ca55
--- /dev/null
+++ b/chrome/browser/policy/user_policy_identity_strategy.h
@@ -0,0 +1,81 @@
+// 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_USER_POLICY_IDENTITY_STRATEGY_H_
+#define CHROME_BROWSER_POLICY_USER_POLICY_IDENTITY_STRATEGY_H_
+#pragma once
+
+#include <string>
+
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "base/weak_ptr.h"
+#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class Profile;
+
+namespace policy {
+
+class DeviceManagementBackend;
+
+// A token provider implementation that provides a user device token for the
+// user corresponding to a given profile.
+class UserPolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
+ public NotificationObserver {
+ public:
+ UserPolicyIdentityStrategy(Profile* profile,
+ const FilePath& token_cache_file);
+ virtual ~UserPolicyIdentityStrategy();
+
+ // CloudPolicyIdentityStrategy implementation:
+ virtual std::string GetDeviceToken();
+ virtual std::string GetDeviceID();
+ virtual bool GetCredentials(std::string* username,
+ std::string* auth_token);
+ virtual void OnDeviceTokenAvailable(const std::string& token);
+
+ private:
+ class TokenCache;
+
+ // Checks whether a new token should be fetched and if so, sends out a
+ // notification.
+ void CheckAndTriggerFetch();
+
+ // Gets the current user.
+ std::string GetCurrentUser();
+
+ // Called from the token cache when the token has been loaded.
+ void OnCacheLoaded(const std::string& token, const std::string& device_id);
+
+ // NotificationObserver method overrides:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // The profile this provider is associated with.
+ Profile* profile_;
+
+ // Keeps the on-disk copy of the token.
+ scoped_refptr<TokenCache> cache_;
+
+ // The device ID we use.
+ std::string device_id_;
+
+ // Current device token. Empty if not available.
+ std::string device_token_;
+
+ // Registers the provider for notification of successful Gaia logins.
+ NotificationRegistrar registrar_;
+
+ // Allows to construct weak ptrs.
+ base::WeakPtrFactory<UserPolicyIdentityStrategy> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserPolicyIdentityStrategy);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_USER_POLICY_IDENTITY_STRATEGY_H_
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 0c76b2f..a03452f 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -34,7 +34,8 @@
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/page_info_model.h"
#include "chrome/browser/password_manager/password_manager.h"
-#include "chrome/browser/policy/profile_policy_context.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile_impl.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
@@ -101,6 +102,7 @@ void RegisterLocalState(PrefService* local_state) {
BackgroundPageTracker::RegisterPrefs(local_state);
NotificationUIManager::RegisterPrefs(local_state);
PrefProxyConfigService::RegisterPrefs(local_state);
+ policy::BrowserPolicyConnector::RegisterPrefs(local_state);
#if defined(OS_CHROMEOS)
chromeos::AudioMixerAlsa::RegisterPrefs(local_state);
chromeos::UserManager::RegisterPrefs(local_state);
@@ -150,7 +152,7 @@ void RegisterUserPrefs(PrefService* user_prefs) {
TemplateURLModel::RegisterUserPrefs(user_prefs);
InstantController::RegisterUserPrefs(user_prefs);
NetPrefObserver::RegisterPrefs(user_prefs);
- policy::ProfilePolicyContext::RegisterUserPrefs(user_prefs);
+ policy::ProfilePolicyConnector::RegisterPrefs(user_prefs);
ProtocolHandlerRegistry::RegisterPrefs(user_prefs);
}
diff --git a/chrome/browser/prefs/pref_member.h b/chrome/browser/prefs/pref_member.h
index 977e1f1..1884edc 100644
--- a/chrome/browser/prefs/pref_member.h
+++ b/chrome/browser/prefs/pref_member.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.
//
@@ -192,6 +192,11 @@ class PrefMember : public subtle::PrefMemberBase {
}
}
+ // Returns the pref name.
+ const std::string& GetPrefName() const {
+ return pref_name();
+ }
+
private:
class Internal : public subtle::PrefMemberBase::Internal {
public:
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index 0443d9c..f183856 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -640,7 +640,7 @@ class OffTheRecordProfileImpl : public Profile,
return profile_->GetExtensionInfoMap();
}
- virtual policy::ProfilePolicyContext* GetPolicyContext() {
+ virtual policy::ProfilePolicyConnector* GetPolicyConnector() {
return NULL;
}
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 71eaf25..42252da 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -37,7 +37,7 @@ class SSLConfigService;
}
namespace policy {
-class ProfilePolicyContext;
+class ProfilePolicyConnector;
}
namespace prerender {
@@ -505,8 +505,8 @@ class Profile {
// Returns the PromoCounter for Instant, or NULL if not applicable.
virtual PromoCounter* GetInstantPromoCounter() = 0;
- // Gets the policy context associated with this profile.
- virtual policy::ProfilePolicyContext* GetPolicyContext() = 0;
+ // Gets the policy connector associated with this profile.
+ virtual policy::ProfilePolicyConnector* GetPolicyConnector() = 0;
// Returns the ChromeURLDataManager for this profile.
virtual ChromeURLDataManager* GetChromeURLDataManager() = 0;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 54f58db..91db2cd 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -58,7 +58,7 @@
#include "chrome/browser/password_manager/password_store_default.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
-#include "chrome/browser/policy/profile_policy_context.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/browser/prerender/prerender_manager.h"
@@ -345,9 +345,9 @@ ProfileImpl::ProfileImpl(const FilePath& path)
io_data_.Init(cookie_path, cache_path, cache_max_size,
media_cache_path, media_cache_max_size, extensions_cookie_path);
- // Initialize the ProfilePolicyContext after |io_data_| since it requires
+ // Initialize the ProfilePolicyConnector after |io_data_| since it requires
// the URLRequestContextGetter to be initialized.
- GetPolicyContext()->Initialize();
+ GetPolicyConnector()->Initialize();
}
void ProfileImpl::InitExtensions() {
@@ -519,7 +519,7 @@ ProfileImpl::~ProfileImpl() {
Source<Profile>(this),
NotificationService::NoDetails());
- GetPolicyContext()->Shutdown();
+ GetPolicyConnector()->Shutdown();
tab_restore_service_ = NULL;
@@ -1380,11 +1380,11 @@ ExtensionInfoMap* ProfileImpl::GetExtensionInfoMap() {
return extension_info_map_.get();
}
-policy::ProfilePolicyContext* ProfileImpl::GetPolicyContext() {
- if (!profile_policy_context_.get())
- profile_policy_context_.reset(new policy::ProfilePolicyContext(this));
+policy::ProfilePolicyConnector* ProfileImpl::GetPolicyConnector() {
+ if (!profile_policy_connector_.get())
+ profile_policy_connector_.reset(new policy::ProfilePolicyConnector(this));
- return profile_policy_context_.get();
+ return profile_policy_connector_.get();
}
ChromeURLDataManager* ProfileImpl::GetChromeURLDataManager() {
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 7cc5e4a..5eea88cb 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -132,7 +132,7 @@ class ProfileImpl : public Profile,
virtual ExtensionInfoMap* GetExtensionInfoMap();
virtual PromoCounter* GetInstantPromoCounter();
virtual BrowserSignin* GetBrowserSignin();
- virtual policy::ProfilePolicyContext* GetPolicyContext();
+ virtual policy::ProfilePolicyConnector* GetPolicyConnector();
virtual ChromeURLDataManager* GetChromeURLDataManager();
#if defined(OS_CHROMEOS)
@@ -206,7 +206,7 @@ class ProfileImpl : public Profile,
transport_security_state_;
scoped_refptr<TransportSecurityPersister>
transport_security_persister_;
- scoped_ptr<policy::ProfilePolicyContext> profile_policy_context_;
+ scoped_ptr<policy::ProfilePolicyConnector> profile_policy_connector_;
scoped_ptr<NetPrefObserver> net_pref_observer_;
scoped_ptr<TemplateURLFetcher> template_url_fetcher_;
scoped_ptr<TemplateURLModel> template_url_model_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d17c616..ac188c6 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1594,8 +1594,15 @@
'browser/policy/asynchronous_policy_loader.h',
'browser/policy/asynchronous_policy_provider.cc',
'browser/policy/asynchronous_policy_provider.h',
+ 'browser/policy/browser_policy_connector.cc',
+ 'browser/policy/browser_policy_connector.h',
'browser/policy/cloud_policy_cache.cc',
'browser/policy/cloud_policy_cache.h',
+ 'browser/policy/cloud_policy_controller.cc',
+ 'browser/policy/cloud_policy_controller.h',
+ 'browser/policy/cloud_policy_identity_strategy.h',
+ 'browser/policy/cloud_policy_subsystem.cc',
+ 'browser/policy/cloud_policy_subsystem.h',
'browser/policy/config_dir_policy_provider.cc',
'browser/policy/config_dir_policy_provider.h',
'browser/policy/configuration_policy_loader_win.cc',
@@ -1606,8 +1613,6 @@
'browser/policy/configuration_policy_provider.h',
'browser/policy/configuration_policy_provider_delegate_win.cc',
'browser/policy/configuration_policy_provider_delegate_win.h',
- 'browser/policy/configuration_policy_provider_keeper.cc',
- 'browser/policy/configuration_policy_provider_keeper.h',
'browser/policy/configuration_policy_provider_mac.cc',
'browser/policy/configuration_policy_provider_mac.h',
'browser/policy/configuration_policy_provider_win.cc',
@@ -1616,10 +1621,10 @@
'browser/policy/device_management_backend.h',
'browser/policy/device_management_backend_impl.cc',
'browser/policy/device_management_backend_impl.h',
- 'browser/policy/device_management_policy_provider.cc',
- 'browser/policy/device_management_policy_provider.h',
'browser/policy/device_management_service.cc',
'browser/policy/device_management_service.h',
+ 'browser/policy/device_policy_identity_strategy.cc',
+ 'browser/policy/device_policy_identity_strategy.h',
'browser/policy/device_token_fetcher.cc',
'browser/policy/device_token_fetcher.h',
'browser/policy/dummy_configuration_policy_provider.cc',
@@ -1630,8 +1635,10 @@
'browser/policy/file_based_policy_provider.h',
'browser/policy/managed_prefs_banner_base.cc',
'browser/policy/managed_prefs_banner_base.h',
- 'browser/policy/profile_policy_context.cc',
- 'browser/policy/profile_policy_context.h',
+ 'browser/policy/profile_policy_connector.cc',
+ 'browser/policy/profile_policy_connector.h',
+ 'browser/policy/user_policy_identity_strategy.cc',
+ 'browser/policy/user_policy_identity_strategy.h',
# TODO(danno): Find a better way to include these files
'<(protoc_out_dir)/chrome/browser/policy/proto/device_management_backend.pb.cc',
'<(protoc_out_dir)/chrome/browser/policy/proto/device_management_backend.pb.h',
@@ -3492,6 +3499,8 @@
['exclude', 'browser/extensions/extension_tts_api_chromeos.cc'],
['exclude', 'browser/oom_priority_manager.cc'],
['exclude', 'browser/oom_priority_manager.h'],
+ ['exclude', 'browser/policy/device_policy_identity_strategy.cc'],
+ ['exclude', 'browser/policy/device_policy_identity_strategy.h'],
['exclude', 'browser/renderer_host/offline_resource_handler.cc'],
['exclude', 'browser/renderer_host/offline_resource_handler.h'],
['exclude', 'browser/webui/filebrowse_ui.cc'],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 837ab0f..fbdbf3a 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -160,8 +160,6 @@
'test/testing_browser_process.cc',
'test/testing_browser_process.h',
'test/testing_browser_process_test.h',
- 'test/testing_device_token_fetcher.cc',
- 'test/testing_device_token_fetcher.h',
'test/testing_pref_service.cc',
'test/testing_pref_service.h',
'test/testing_profile.cc',
@@ -1405,6 +1403,7 @@
'browser/policy/asynchronous_policy_test_base.cc',
'browser/policy/asynchronous_policy_test_base.h',
'browser/policy/cloud_policy_cache_unittest.cc',
+ 'browser/policy/cloud_policy_controller_unittest.cc',
'browser/policy/config_dir_policy_provider_unittest.cc',
'browser/policy/configuration_policy_pref_store_unittest.cc',
'browser/policy/configuration_policy_provider_mac_unittest.cc',
@@ -1414,7 +1413,6 @@
'browser/policy/device_management_backend_mock.cc',
'browser/policy/device_management_backend_mock.h',
'browser/policy/device_management_service_unittest.cc',
- 'browser/policy/device_management_policy_provider_unittest.cc',
'browser/policy/managed_prefs_banner_base_unittest.cc',
'browser/policy/mock_configuration_policy_provider.cc',
'browser/policy/mock_configuration_policy_provider.h',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 62978fc..b3e69ef 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -150,6 +150,10 @@ const char kDebugPrint[] = "debug-print";
// device management backend.
const char kDeviceManagementUrl[] = "device-management-url";
+// Specifies the directory in which to store the shared device policy cache
+// file. If not specified, device policy will be disabled.
+const char kDevicePolicyCacheDir[] = "device-policy-cache-dir";
+
// Triggers a pletora of diagnostic modes.
const char kDiagnostics[] = "diagnostics";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index a55991b5..faad820 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -9,6 +9,7 @@
#pragma once
#include "build/build_config.h"
+
#include "base/base_switches.h"
namespace switches {
@@ -54,6 +55,7 @@ extern const char kConflictingModulesCheck[];
extern const char kCountry[];
extern const char kDebugPrint[];
extern const char kDeviceManagementUrl[];
+extern const char kDevicePolicyCacheDir[];
extern const char kDiagnostics[];
extern const char kDisable3DAPIs[];
extern const char kDisableAcceleratedCompositing[];
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 27b364d..19b74330 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -674,10 +674,14 @@ const char kEnableTranslate[] = "translate.enabled";
const char kPinnedTabs[] = "pinned_tabs";
-// Integer that specifies the policy refresh rate in milliseconds. Not all
-// values are meaningful, so it is clamped to a sane range by the policy
-// provider.
-const char kPolicyRefreshRate[] = "policy.refresh_rate";
+// Integer that specifies the policy refresh rate for user policy in
+// milliseconds. Not all values are meaningful, so it is clamped to a sane
+// range by the cloud policy subsystem.
+const char kPolicyUserPolicyRefreshRate[] = "policy.user_policy_refresh_rate";
+
+// Same as |kPolicyUserPolicyRefreshRate|, but for device policy.
+const char kPolicyDevicePolicyRefreshRate[] =
+ "policy.device_policy_refresh_rate";
// Integer containing the default Geolocation content setting.
const char kGeolocationDefaultContentSetting[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index f41e3ff..14364d9 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -238,7 +238,9 @@ extern const char kAutoFillPersonalDataManagerFirstRun[];
extern const char kUseVerticalTabs[];
extern const char kEnableTranslate[];
extern const char kPinnedTabs[];
-extern const char kPolicyRefreshRate[];
+
+extern const char kPolicyUserPolicyRefreshRate[];
+extern const char kPolicyDevicePolicyRefreshRate[];
// Local state
extern const char kMetricsClientID[];
diff --git a/chrome/test/testing_browser_process.cc b/chrome/test/testing_browser_process.cc
index 01090d2..e6f5696 100644
--- a/chrome/test/testing_browser_process.cc
+++ b/chrome/test/testing_browser_process.cc
@@ -8,9 +8,9 @@
#include "base/synchronization/waitable_event.h"
#include "chrome/browser/google/google_url_tracker.h"
#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
-#include "chrome/browser/policy/configuration_policy_provider_keeper.h"
#include "chrome/browser/policy/dummy_configuration_policy_provider.h"
#include "ui/base/clipboard/clipboard.h"
@@ -18,8 +18,7 @@ TestingBrowserProcess::TestingBrowserProcess()
: shutdown_event_(new base::WaitableEvent(true, false)),
module_ref_count_(0),
app_locale_("en"),
- pref_service_(NULL),
- created_configuration_policy_provider_keeper_(false) {
+ pref_service_(NULL) {
}
TestingBrowserProcess::~TestingBrowserProcess() {
@@ -70,21 +69,18 @@ PrefService* TestingBrowserProcess::local_state() {
return pref_service_;
}
-policy::ConfigurationPolicyProviderKeeper*
-TestingBrowserProcess::configuration_policy_provider_keeper() {
- if (!created_configuration_policy_provider_keeper_) {
- DCHECK(configuration_policy_provider_keeper_.get() == NULL);
- created_configuration_policy_provider_keeper_ = true;
+policy::BrowserPolicyConnector*
+ TestingBrowserProcess::browser_policy_connector() {
+ if (!browser_policy_connector_.get()) {
const policy::ConfigurationPolicyProvider::PolicyDefinitionList*
policy_list = policy::ConfigurationPolicyPrefStore::
GetChromePolicyDefinitionList();
- configuration_policy_provider_keeper_.reset(
- new policy::ConfigurationPolicyProviderKeeper(
- new policy::DummyConfigurationPolicyProvider(policy_list),
+ browser_policy_connector_.reset(
+ new policy::BrowserPolicyConnector(
new policy::DummyConfigurationPolicyProvider(policy_list),
new policy::DummyConfigurationPolicyProvider(policy_list)));
}
- return configuration_policy_provider_keeper_.get();
+ return browser_policy_connector_.get();
}
IconManager* TestingBrowserProcess::icon_manager() {
diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h
index 04e50939..7ccef97 100644
--- a/chrome/test/testing_browser_process.h
+++ b/chrome/test/testing_browser_process.h
@@ -29,7 +29,7 @@ class WaitableEvent;
}
namespace policy {
-class ConfigurationPolicyProviderKeeper;
+class BrowserPolicyConnector;
}
namespace ui {
@@ -65,8 +65,7 @@ class TestingBrowserProcess : public BrowserProcess {
virtual PrefService* local_state();
- virtual policy::ConfigurationPolicyProviderKeeper*
- configuration_policy_provider_keeper();
+ virtual policy::BrowserPolicyConnector* browser_policy_connector();
virtual IconManager* icon_manager();
@@ -140,9 +139,7 @@ class TestingBrowserProcess : public BrowserProcess {
std::string app_locale_;
PrefService* pref_service_;
- bool created_configuration_policy_provider_keeper_;
- scoped_ptr<policy::ConfigurationPolicyProviderKeeper>
- configuration_policy_provider_keeper_;
+ scoped_ptr<policy::BrowserPolicyConnector> browser_policy_connector_;
scoped_ptr<GoogleURLTracker> google_url_tracker_;
DISALLOW_COPY_AND_ASSIGN(TestingBrowserProcess);
diff --git a/chrome/test/testing_device_token_fetcher.cc b/chrome/test/testing_device_token_fetcher.cc
deleted file mode 100644
index 263f47a..0000000
--- a/chrome/test/testing_device_token_fetcher.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2010 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/test/testing_device_token_fetcher.h"
-
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/browser/policy/device_token_fetcher.h"
-#include "chrome/browser/profiles/profile.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/user_manager.h"
-#else
-#include "chrome/browser/sync/signin_manager.h"
-#endif
-
-namespace policy {
-
-const char* kTestManagedDomainUsername = "___@example.com";
-
-void TestingDeviceTokenFetcher::SimulateLogin(const std::string& username) {
- username_ = username;
-#if defined(OS_CHROMEOS)
- chromeos::UserManager::User user;
- user.set_email(username_);
- NotificationService::current()->Notify(
- NotificationType::LOGIN_USER_CHANGED,
- Source<chromeos::UserManager>(NULL),
- Details<const chromeos::UserManager::User>(&user));
-#else
- GoogleServiceSigninSuccessDetails details(username_, "");
- NotificationService::current()->Notify(
- NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
- Source<Profile>(profile_),
- Details<const GoogleServiceSigninSuccessDetails>(&details));
-#endif
-}
-
-std::string TestingDeviceTokenFetcher::GetCurrentUser() {
- return username_;
-}
-
-} // namespace policy
diff --git a/chrome/test/testing_device_token_fetcher.h b/chrome/test/testing_device_token_fetcher.h
deleted file mode 100644
index ab021f9..0000000
--- a/chrome/test/testing_device_token_fetcher.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2010 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_TEST_TESTING_DEVICE_TOKEN_FETCHER_H_
-#define CHROME_TEST_TESTING_DEVICE_TOKEN_FETCHER_H_
-#pragma once
-
-#include <string>
-
-#include "chrome/browser/policy/device_token_fetcher.h"
-
-class DeviceTokenService;
-class Profile;
-
-namespace policy {
-
-extern const char* kTestManagedDomainUsername;
-
-// Replacement for DeviceTokenFetcher in tests. The only difference in internal
-// logic is that the name of the currently logged in user is not fetched from
-// external objects, but stored internally.
-class TestingDeviceTokenFetcher
- : public DeviceTokenFetcher {
- public:
- TestingDeviceTokenFetcher(
- DeviceManagementBackend* backend,
- Profile* profile,
- const FilePath& token_path)
- : DeviceTokenFetcher(backend, profile, token_path) {}
-
- void SimulateLogin(const std::string& username);
-
- protected:
- virtual std::string GetCurrentUser();
-
- private:
- // This username will be reported as currently logged in.
- std::string username_;
-
- DISALLOW_COPY_AND_ASSIGN(TestingDeviceTokenFetcher);
-};
-
-} // namespace policy
-
-#endif // CHROME_TEST_TESTING_DEVICE_TOKEN_FETCHER_H_
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index d523541..dace243 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -766,7 +766,7 @@ PromoCounter* TestingProfile::GetInstantPromoCounter() {
return NULL;
}
-policy::ProfilePolicyContext* TestingProfile::GetPolicyContext() {
+policy::ProfilePolicyConnector* TestingProfile::GetPolicyConnector() {
return NULL;
}
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 822acb9..ad437d8 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -280,7 +280,7 @@ class TestingProfile : public Profile {
virtual ChromeBlobStorageContext* GetBlobStorageContext();
virtual ExtensionInfoMap* GetExtensionInfoMap();
virtual PromoCounter* GetInstantPromoCounter();
- virtual policy::ProfilePolicyContext* GetPolicyContext();
+ virtual policy::ProfilePolicyConnector* GetPolicyConnector();
virtual ChromeURLDataManager* GetChromeURLDataManager();
virtual prerender::PrerenderManager* GetPrerenderManager();
virtual PrefService* GetOffTheRecordPrefs();