diff options
author | gfeher@chromium.org <gfeher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-29 15:44:37 +0000 |
---|---|---|
committer | gfeher@chromium.org <gfeher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-29 15:44:37 +0000 |
commit | fcf53571062bd52559112684f18989965bda607d (patch) | |
tree | e64c7a1e1c1b303ad03513b6716f7ee2d5680440 /chrome/browser/policy | |
parent | 03c7f66c2cd69c42078e807c3835c5b510fed253 (diff) | |
download | chromium_src-fcf53571062bd52559112684f18989965bda607d.zip chromium_src-fcf53571062bd52559112684f18989965bda607d.tar.gz chromium_src-fcf53571062bd52559112684f18989965bda607d.tar.bz2 |
Move user cloud policy to BrowserProcess (was 6979011)
This CL basically does the following things:
* Remove final dependencies of ProfilePolicyConnector on Profile
* Take ProfilePolicyConnector away from Profile and put it into BrowserPolicyConnector.
* Make BrowserPolicyConnector instance persistant and allow to
exchange the CloudPolicySubsystem backend instead.
* Introduce a new CloudPolicyProvider which combines two
(or more) CloudPolicyCacheBase backends and applies their policies in a well defined order.
That is the order in which the CloudPolicyCacheBases appear in
the List of CloudPolicyProvider determines the precedence,
early Providers get applied first and block the applied policies
for later Caches.
* Handles ProxyPolicies in CloudPolicyProvider making
the old infrastructure around MergingPolicyConnector obsolete.
* Consequently this means that user cloud policy can now serve local_state.
Continuation of http://codereview.chromium.org/6979011/
Patch from sfeuz@chromium.org with additional work from gfeher@chromium.org
BUG=none
TEST=Unittests CloudPolicyProvider.*
Review URL: http://codereview.chromium.org/7147015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90957 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/policy')
32 files changed, 988 insertions, 906 deletions
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc index cd42d59..a2d3112 100644 --- a/chrome/browser/policy/browser_policy_connector.cc +++ b/chrome/browser/policy/browser_policy_connector.cc @@ -6,14 +6,22 @@ #include "base/command_line.h" #include "base/path_service.h" -#include "chrome/browser/browser_process.h" +#include "chrome/browser/net/gaia/token_service.h" +#include "chrome/browser/policy/cloud_policy_provider.h" +#include "chrome/browser/policy/cloud_policy_provider_impl.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_cloud_policy_provider.h" #include "chrome/browser/policy/dummy_configuration_policy_provider.h" +#include "chrome/browser/policy/user_policy_cache.h" +#include "chrome/browser/policy/user_policy_identity_strategy.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/pref_names.h" +#include "content/common/notification_details.h" +#include "content/common/notification_source.h" #if defined(OS_WIN) #include "chrome/browser/policy/configuration_policy_provider_win.h" @@ -27,13 +35,20 @@ #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/policy/device_policy_cache.h" #include "chrome/browser/policy/device_policy_identity_strategy.h" -#include "chrome/browser/policy/enterprise_install_attributes.h" +#include "content/common/notification_service.h" #endif namespace policy { namespace { +// Subdirectory in the user's profile for storing user policies. +const FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("Device Management"); +// File in the above directory for stroing user policy dmtokens. +const FilePath::CharType kTokenCacheFile[] = FILE_PATH_LITERAL("Token"); +// File in the above directory for storing user policy data. +const FilePath::CharType kPolicyCacheFile[] = FILE_PATH_LITERAL("Policy"); + // The following constants define delays applied before the initial policy fetch // on startup. (So that displaying Chrome's GUI does not get delayed.) // Delay in milliseconds from startup. @@ -52,8 +67,10 @@ BrowserPolicyConnector* BrowserPolicyConnector::CreateForTests() { policy_list = ConfigurationPolicyPrefStore:: GetChromePolicyDefinitionList(); return new BrowserPolicyConnector( - new DummyConfigurationPolicyProvider(policy_list), - new DummyConfigurationPolicyProvider(policy_list)); + new policy::DummyConfigurationPolicyProvider(policy_list), + new policy::DummyConfigurationPolicyProvider(policy_list), + new policy::DummyCloudPolicyProvider(policy_list), + new policy::DummyCloudPolicyProvider(policy_list)); } BrowserPolicyConnector::BrowserPolicyConnector() @@ -61,39 +78,43 @@ BrowserPolicyConnector::BrowserPolicyConnector() managed_platform_provider_.reset(CreateManagedPlatformProvider()); recommended_platform_provider_.reset(CreateRecommendedPlatformProvider()); -#if defined(OS_CHROMEOS) - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kEnableDevicePolicy)) { - identity_strategy_.reset(new DevicePolicyIdentityStrategy()); - install_attributes_.reset(new EnterpriseInstallAttributes( - chromeos::CrosLibrary::Get()->GetCryptohomeLibrary())); - cloud_policy_subsystem_.reset(new CloudPolicySubsystem( - identity_strategy_.get(), - new DevicePolicyCache(identity_strategy_.get(), - install_attributes_.get()))); + managed_cloud_provider_.reset(new CloudPolicyProviderImpl( + ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY)); + recommended_cloud_provider_.reset(new CloudPolicyProviderImpl( + ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), + CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED)); - // Initialize the subsystem once the message loops are spinning. - MessageLoop::current()->PostTask( - FROM_HERE, - method_factory_.NewRunnableMethod(&BrowserPolicyConnector::Initialize)); - } +#if defined(OS_CHROMEOS) + InitializeDevicePolicy(); #endif } BrowserPolicyConnector::BrowserPolicyConnector( ConfigurationPolicyProvider* managed_platform_provider, - ConfigurationPolicyProvider* recommended_platform_provider) + ConfigurationPolicyProvider* recommended_platform_provider, + CloudPolicyProvider* managed_cloud_provider, + CloudPolicyProvider* recommended_cloud_provider) : managed_platform_provider_(managed_platform_provider), recommended_platform_provider_(recommended_platform_provider), + managed_cloud_provider_(managed_cloud_provider), + recommended_cloud_provider_(recommended_cloud_provider), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} BrowserPolicyConnector::~BrowserPolicyConnector() { - if (cloud_policy_subsystem_.get()) - cloud_policy_subsystem_->Shutdown(); - cloud_policy_subsystem_.reset(); + // Shutdown device cloud policy. #if defined(OS_CHROMEOS) - identity_strategy_.reset(); + if (device_cloud_policy_subsystem_.get()) + device_cloud_policy_subsystem_->Shutdown(); + device_cloud_policy_subsystem_.reset(); + device_identity_strategy_.reset(); #endif + + // Shutdown user cloud policy. + if (user_cloud_policy_subsystem_.get()) + user_cloud_policy_subsystem_->Shutdown(); + user_cloud_policy_subsystem_.reset(); + user_identity_strategy_.reset(); } ConfigurationPolicyProvider* @@ -103,10 +124,7 @@ ConfigurationPolicyProvider* ConfigurationPolicyProvider* BrowserPolicyConnector::GetManagedCloudProvider() const { - if (cloud_policy_subsystem_.get()) - return cloud_policy_subsystem_->GetManagedPolicyProvider(); - - return NULL; + return managed_cloud_provider_.get(); } ConfigurationPolicyProvider* @@ -116,10 +134,7 @@ ConfigurationPolicyProvider* ConfigurationPolicyProvider* BrowserPolicyConnector::GetRecommendedCloudProvider() const { - if (cloud_policy_subsystem_.get()) - return cloud_policy_subsystem_->GetRecommendedPolicyProvider(); - - return NULL; + return recommended_cloud_provider_.get(); } ConfigurationPolicyProvider* @@ -162,11 +177,12 @@ ConfigurationPolicyProvider* #endif } -void BrowserPolicyConnector::SetCredentials(const std::string& owner_email, - const std::string& gaia_token) { +void BrowserPolicyConnector::SetDeviceCredentials( + const std::string& owner_email, + const std::string& gaia_token) { #if defined(OS_CHROMEOS) - if (identity_strategy_.get()) - identity_strategy_->SetAuthCredentials(owner_email, gaia_token); + if (device_identity_strategy_.get()) + device_identity_strategy_->SetAuthCredentials(owner_email, gaia_token); #endif } @@ -197,30 +213,142 @@ std::string BrowserPolicyConnector::GetEnterpriseDomain() { return std::string(); } -void BrowserPolicyConnector::StopAutoRetry() { - if (cloud_policy_subsystem_.get()) - cloud_policy_subsystem_->StopAutoRetry(); +void BrowserPolicyConnector::DeviceStopAutoRetry() { +#if defined(OS_CHROMEOS) + if (device_cloud_policy_subsystem_.get()) + device_cloud_policy_subsystem_->StopAutoRetry(); +#endif } -void BrowserPolicyConnector::FetchPolicy() { +void BrowserPolicyConnector::FetchDevicePolicy() { #if defined(OS_CHROMEOS) - if (identity_strategy_.get()) - return identity_strategy_->FetchPolicy(); + if (device_identity_strategy_.get()) + return device_identity_strategy_->FetchPolicy(); #endif } -void BrowserPolicyConnector::Initialize() { - if (cloud_policy_subsystem_.get()) { - cloud_policy_subsystem_->CompleteInitialization( - prefs::kDevicePolicyRefreshRate, +void BrowserPolicyConnector::InitializeUserPolicy(const std::string& user_name, + const FilePath& policy_dir, + TokenService* token_service) { + DCHECK(token_service); + + // Throw away the old backend. + user_cloud_policy_subsystem_.reset(); + user_identity_strategy_.reset(); + registrar_.RemoveAll(); + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDeviceManagementUrl)) { + token_service_ = token_service; + registrar_.Add(this, + NotificationType::TOKEN_AVAILABLE, + Source<TokenService>(token_service_)); + + FilePath policy_cache_dir = policy_dir.Append(kPolicyDir); + UserPolicyCache* user_policy_cache = + new UserPolicyCache(policy_cache_dir.Append(kPolicyCacheFile)); + + // Prepending user caches meaning they will take precedence of device policy + // caches. + managed_cloud_provider_->PrependCache(user_policy_cache); + recommended_cloud_provider_->PrependCache(user_policy_cache); + user_identity_strategy_.reset( + new UserPolicyIdentityStrategy( + user_name, + policy_cache_dir.Append(kTokenCacheFile))); + user_cloud_policy_subsystem_.reset(new CloudPolicySubsystem( + user_identity_strategy_.get(), + user_policy_cache)); + + // Initiate the DM-Token load. + user_identity_strategy_->LoadTokenCache(); + + if (token_service_->HasTokenForService( + GaiaConstants::kDeviceManagementService)) { + user_identity_strategy_->SetAuthToken( + token_service_->GetTokenForService( + GaiaConstants::kDeviceManagementService)); + } + + user_cloud_policy_subsystem_->CompleteInitialization( + prefs::kUserPolicyRefreshRate, kServiceInitializationStartupDelay); } } void BrowserPolicyConnector::ScheduleServiceInitialization( int64 delay_milliseconds) { - if (cloud_policy_subsystem_.get()) - cloud_policy_subsystem_->ScheduleServiceInitialization(delay_milliseconds); + if (user_cloud_policy_subsystem_.get()) { + user_cloud_policy_subsystem_-> + ScheduleServiceInitialization(delay_milliseconds); + } +#if defined(OS_CHROMEOS) + if (device_cloud_policy_subsystem_.get()) { + device_cloud_policy_subsystem_-> + ScheduleServiceInitialization(delay_milliseconds); + } +#endif +} + +void BrowserPolicyConnector::InitializeDevicePolicy() { +#if defined(OS_CHROMEOS) + // Throw away the old backend. + device_cloud_policy_subsystem_.reset(); + device_identity_strategy_.reset(); + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kEnableDevicePolicy)) { + device_identity_strategy_.reset(new DevicePolicyIdentityStrategy()); + install_attributes_.reset(new EnterpriseInstallAttributes( + chromeos::CrosLibrary::Get()->GetCryptohomeLibrary())); + DevicePolicyCache* device_policy_cache = + new DevicePolicyCache(device_identity_strategy_.get(), + install_attributes_.get()); + + managed_cloud_provider_->AppendCache(device_policy_cache); + recommended_cloud_provider_->AppendCache(device_policy_cache); + + device_cloud_policy_subsystem_.reset(new CloudPolicySubsystem( + device_identity_strategy_.get(), + device_policy_cache)); + + // Initialize the subsystem once the message loops are spinning. + MessageLoop::current()->PostTask( + FROM_HERE, + method_factory_.NewRunnableMethod( + &BrowserPolicyConnector::InitializeDevicePolicySubsystem)); + } +#endif +} + +void BrowserPolicyConnector::InitializeDevicePolicySubsystem() { +#if defined(OS_CHROMEOS) + if (device_cloud_policy_subsystem_.get()) { + device_cloud_policy_subsystem_->CompleteInitialization( + prefs::kDevicePolicyRefreshRate, + kServiceInitializationStartupDelay); + } +#endif +} + +void BrowserPolicyConnector::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (type == NotificationType::TOKEN_AVAILABLE) { + const TokenService* token_source = + Source<const TokenService>(source).ptr(); + DCHECK_EQ(token_service_, token_source); + const TokenService::TokenAvailableDetails* token_details = + Details<const TokenService::TokenAvailableDetails>(details).ptr(); + if (token_details->service() == GaiaConstants::kDeviceManagementService) { + if (user_identity_strategy_.get()) { + user_identity_strategy_->SetAuthToken(token_details->token()); + } + } + } else { + NOTREACHED(); + } } } // namespace diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h index 0b01de8..55a2ff9 100644 --- a/chrome/browser/policy/browser_policy_connector.h +++ b/chrome/browser/policy/browser_policy_connector.h @@ -12,44 +12,61 @@ #include "base/memory/scoped_ptr.h" #include "base/task.h" #include "chrome/browser/policy/enterprise_install_attributes.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_registrar.h" -class PrefService; +class FilePath; class TestingBrowserProcess; class TokenService; -namespace net { -class URLRequestContextGetter; -} - namespace policy { +class CloudPolicyProvider; class CloudPolicySubsystem; class ConfigurationPolicyProvider; +class UserPolicyIdentityStrategy; + +#if defined(OS_CHROMEOS) class DevicePolicyIdentityStrategy; +#endif // Manages the lifecycle of browser-global policy infrastructure, such as the -// platform policy providers. -class BrowserPolicyConnector { +// platform policy providers, device- and the user-cloud policy infrastructure. +// TODO(gfeher,mnissler): Factor out device and user specific methods into their +// respective classes. +class BrowserPolicyConnector : public NotificationObserver { public: static BrowserPolicyConnector* Create(); - ~BrowserPolicyConnector(); + virtual ~BrowserPolicyConnector(); ConfigurationPolicyProvider* GetManagedPlatformProvider() const; ConfigurationPolicyProvider* GetManagedCloudProvider() const; ConfigurationPolicyProvider* GetRecommendedPlatformProvider() const; ConfigurationPolicyProvider* GetRecommendedCloudProvider() const; - // Returns a weak pointer to the CloudPolicySubsystem managed by this - // policy connector, or NULL if no such subsystem exists (i.e. when running - // outside ChromeOS). - CloudPolicySubsystem* cloud_policy_subsystem() { - return cloud_policy_subsystem_.get(); + // Returns a weak pointer to the CloudPolicySubsystem corresponding to the + // device policy managed by this policy connector, or NULL if no such + // subsystem exists (i.e. when running outside ChromeOS). + CloudPolicySubsystem* device_cloud_policy_subsystem() { +#if defined(OS_CHROMEOS) + return device_cloud_policy_subsystem_.get(); +#else + return NULL; +#endif + } + + // Returns a weak pointer to the CloudPolicySubsystem corresponding to the + // user policy managed by this policy connector, or NULL if no such + // subsystem exists (i.e. when user cloud policy is not active due to + // unmanaged or not logged in). + CloudPolicySubsystem* user_cloud_policy_subsystem() { + return user_cloud_policy_subsystem_.get(); } // Used to set the credentials stored in the identity strategy associated // with this policy connector. - void SetCredentials(const std::string& owner_email, - const std::string& gaia_token); + void SetDeviceCredentials(const std::string& owner_email, + const std::string& gaia_token); // Returns true if this device is managed by an enterprise (as opposed to // a local owner). @@ -64,15 +81,22 @@ class BrowserPolicyConnector { // Exposes the StopAutoRetry() method of the CloudPolicySubsystem managed // by this connector, which can be used to disable automatic // retrying behavior. - void StopAutoRetry(); + void DeviceStopAutoRetry(); // Initiates a policy fetch after a successful device registration. - void FetchPolicy(); + void FetchDevicePolicy(); - // Schedules initialization of the policy backend service, if the service is - // already constructed. + // Schedules initialization of the cloud policy backend services, if the + // services are already constructed. void ScheduleServiceInitialization(int64 delay_milliseconds); + // Initializes the user cloud policy infrasturcture. + // TODO(sfeuz): Listen to log-out or going-away messages of TokenService and + // reset the backend at that point. + void InitializeUserPolicy(const std::string& user_name, + const FilePath& policy_dir, + TokenService* token_service); + private: friend class ::TestingBrowserProcess; @@ -82,26 +106,51 @@ class BrowserPolicyConnector { static ConfigurationPolicyProvider* CreateManagedPlatformProvider(); static ConfigurationPolicyProvider* CreateRecommendedPlatformProvider(); - // Constructor for tests that allows tests to use fake platform policy - // providers instead of using the actual ones. + // Constructor for tests that allows tests to use fake platform and cloud + // policy providers instead of using the actual ones. BrowserPolicyConnector( ConfigurationPolicyProvider* managed_platform_provider, - ConfigurationPolicyProvider* recommended_platform_provider); + ConfigurationPolicyProvider* recommended_platform_provider, + CloudPolicyProvider* managed_cloud_provider, + CloudPolicyProvider* recommended_cloud_provider); + + // NotificationObserver method overrides: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE; - // Activates the cloud policy subsystem. - void Initialize(); + // Initializes the device cloud policy infrasturcture. + void InitializeDevicePolicy(); + + // Activates the device cloud policy subsystem. This will be posted as a task + // from InitializeDevicePolicy since it needs to wait for the message loops to + // be running. + void InitializeDevicePolicySubsystem(); scoped_ptr<ConfigurationPolicyProvider> managed_platform_provider_; scoped_ptr<ConfigurationPolicyProvider> recommended_platform_provider_; + scoped_ptr<CloudPolicyProvider> managed_cloud_provider_; + scoped_ptr<CloudPolicyProvider> recommended_cloud_provider_; + #if defined(OS_CHROMEOS) - scoped_ptr<DevicePolicyIdentityStrategy> identity_strategy_; + scoped_ptr<DevicePolicyIdentityStrategy> device_identity_strategy_; + scoped_ptr<CloudPolicySubsystem> device_cloud_policy_subsystem_; scoped_ptr<EnterpriseInstallAttributes> install_attributes_; #endif - scoped_ptr<CloudPolicySubsystem> cloud_policy_subsystem_; + + scoped_ptr<UserPolicyIdentityStrategy> user_identity_strategy_; + scoped_ptr<CloudPolicySubsystem> user_cloud_policy_subsystem_; ScopedRunnableMethodFactory<BrowserPolicyConnector> method_factory_; + // Registers the provider for notification of successful Gaia logins. + NotificationRegistrar registrar_; + + // Weak reference to the TokenService we are listening to for user cloud + // policy authentication tokens. + TokenService* token_service_; + DISALLOW_COPY_AND_ASSIGN(BrowserPolicyConnector); }; diff --git a/chrome/browser/policy/cloud_policy_cache_base.cc b/chrome/browser/policy/cloud_policy_cache_base.cc index 5fdf08e..1bf5c04 100644 --- a/chrome/browser/policy/cloud_policy_cache_base.cc +++ b/chrome/browser/policy/cloud_policy_cache_base.cc @@ -8,72 +8,38 @@ #include "base/logging.h" #include "base/values.h" -#include "chrome/browser/policy/configuration_policy_pref_store.h" #include "chrome/browser/policy/policy_notifier.h" namespace policy { -// A thin ConfigurationPolicyProvider implementation sitting on top of -// CloudPolicyCacheBase for hooking up with ConfigurationPolicyPrefStore. -class CloudPolicyCacheBase::CloudPolicyProvider - : public ConfigurationPolicyProvider { - public: - CloudPolicyProvider(const PolicyDefinitionList* policy_list, - CloudPolicyCacheBase* cache, - CloudPolicyCacheBase::PolicyLevel level) - : ConfigurationPolicyProvider(policy_list), - cache_(cache), - level_(level) {} - virtual ~CloudPolicyProvider() {} - - virtual bool Provide(ConfigurationPolicyStoreInterface* store) { - if (level_ == POLICY_LEVEL_MANDATORY) - ApplyPolicyMap(&cache_->mandatory_policy_, store); - else if (level_ == POLICY_LEVEL_RECOMMENDED) - ApplyPolicyMap(&cache_->recommended_policy_, 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. - CloudPolicyCacheBase* cache_; - // Policy level this provider will handle. - CloudPolicyCacheBase::PolicyLevel level_; - - DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider); -}; - CloudPolicyCacheBase::CloudPolicyCacheBase() : notifier_(NULL), initialization_complete_(false), is_unmanaged_(false) { public_key_version_.valid = 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)); } CloudPolicyCacheBase::~CloudPolicyCacheBase() { - FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, - observer_list_, OnProviderGoingAway()); + FOR_EACH_OBSERVER(Observer, observer_list_, OnCacheGoingAway(this)); +} + +void CloudPolicyCacheBase::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void CloudPolicyCacheBase::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +const PolicyMap* CloudPolicyCacheBase::policy(PolicyLevel level) { + switch (level) { + case POLICY_LEVEL_MANDATORY: + return &mandatory_policy_; + case POLICY_LEVEL_RECOMMENDED: + return &recommended_policy_; + } + NOTREACHED(); + return NULL; } bool CloudPolicyCacheBase::GetPublicKeyVersion(int* version) { @@ -119,8 +85,7 @@ bool CloudPolicyCacheBase::SetPolicyInternal( initialization_complete_ = true; if (new_policy_differs || initialization_was_not_complete) { - FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, - observer_list_, OnUpdatePolicy()); + FOR_EACH_OBSERVER(Observer, observer_list_, OnCacheUpdate(this)); } InformNotifier(CloudPolicySubsystem::SUCCESS, CloudPolicySubsystem::NO_DETAILS); @@ -135,19 +100,7 @@ void CloudPolicyCacheBase::SetUnmanagedInternal(const base::Time& timestamp) { recommended_policy_.Clear(); last_policy_refresh_time_ = timestamp; - FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, - observer_list_, OnUpdatePolicy()); -} - -ConfigurationPolicyProvider* CloudPolicyCacheBase::GetManagedPolicyProvider() { - DCHECK(CalledOnValidThread()); - return managed_policy_provider_.get(); -} - -ConfigurationPolicyProvider* - CloudPolicyCacheBase::GetRecommendedPolicyProvider() { - DCHECK(CalledOnValidThread()); - return recommended_policy_provider_.get(); + FOR_EACH_OBSERVER(Observer, observer_list_, OnCacheUpdate(this)); } bool CloudPolicyCacheBase::DecodePolicyResponse( diff --git a/chrome/browser/policy/cloud_policy_cache_base.h b/chrome/browser/policy/cloud_policy_cache_base.h index 0fd89fc..3a57ec2 100644 --- a/chrome/browser/policy/cloud_policy_cache_base.h +++ b/chrome/browser/policy/cloud_policy_cache_base.h @@ -6,19 +6,15 @@ #define CHROME_BROWSER_POLICY_CLOUD_POLICY_CACHE_BASE_H_ #pragma once -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/threading/non_thread_safe.h" #include "base/time.h" #include "chrome/browser/policy/cloud_policy_subsystem.h" -#include "chrome/browser/policy/configuration_policy_provider.h" #include "chrome/browser/policy/policy_map.h" #include "chrome/browser/policy/proto/device_management_backend.pb.h" namespace policy { -class PolicyMap; class PolicyNotifier; namespace em = enterprise_management; @@ -36,6 +32,13 @@ class CloudPolicyCacheBase : public base::NonThreadSafe { POLICY_LEVEL_RECOMMENDED, }; + class Observer { + public: + virtual ~Observer() {} + virtual void OnCacheGoingAway(CloudPolicyCacheBase*) = 0; + virtual void OnCacheUpdate(CloudPolicyCacheBase*) = 0; + }; + CloudPolicyCacheBase(); virtual ~CloudPolicyCacheBase(); @@ -49,9 +52,6 @@ class CloudPolicyCacheBase : public base::NonThreadSafe { // Resets the policy information. virtual void SetPolicy(const em::PolicyFetchResponse& policy) = 0; - ConfigurationPolicyProvider* GetManagedPolicyProvider(); - ConfigurationPolicyProvider* GetRecommendedPolicyProvider(); - virtual void SetUnmanaged() = 0; bool is_unmanaged() const { return is_unmanaged_; @@ -67,6 +67,19 @@ class CloudPolicyCacheBase : public base::NonThreadSafe { // in. bool GetPublicKeyVersion(int* version); + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Accessor for the underlying PolicyMaps. + const PolicyMap* policy(PolicyLevel level); + + // true if the cache contains data that is ready to be served as policies. + // This should mean that this method turns true as soon as a round-trip to + // the local policy storage is complete. The creation of the Profile is + // blocked on this method, so we shouldn't wait for successful network + // round trips. + virtual bool IsReady() = 0; + protected: // Wraps public key version and validity. struct PublicKeyVersion { @@ -103,29 +116,24 @@ class CloudPolicyCacheBase : public base::NonThreadSafe { void InformNotifier(CloudPolicySubsystem::PolicySubsystemState state, CloudPolicySubsystem::ErrorDetails error_details); + void set_last_policy_refresh_time(base::Time timestamp) { + last_policy_refresh_time_ = timestamp; + } + // See comment for |initialization_complete_|. bool initialization_complete() { return initialization_complete_; } - void set_last_policy_refresh_time(base::Time timestamp) { - last_policy_refresh_time_ = timestamp; - } - private: - class CloudPolicyProvider; - friend class DevicePolicyCacheTest; friend class UserPolicyCacheTest; + friend class MockCloudPolicyCache; // Policy key-value information. PolicyMap mandatory_policy_; PolicyMap recommended_policy_; - // Policy providers. - scoped_ptr<ConfigurationPolicyProvider> managed_policy_provider_; - scoped_ptr<ConfigurationPolicyProvider> recommended_policy_provider_; - PolicyNotifier* notifier_; // The time at which the policy was last refreshed. Is updated both upon @@ -143,8 +151,8 @@ class CloudPolicyCacheBase : public base::NonThreadSafe { // Currently used public key version, if available. PublicKeyVersion public_key_version_; - // Provider observers that are registered with this cache's providers. - ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_; + // Cache observers that are registered with this cache. + ObserverList<Observer, true> observer_list_; DISALLOW_COPY_AND_ASSIGN(CloudPolicyCacheBase); }; diff --git a/chrome/browser/policy/cloud_policy_controller_unittest.cc b/chrome/browser/policy/cloud_policy_controller_unittest.cc index a008a1e..7e828db 100644 --- a/chrome/browser/policy/cloud_policy_controller_unittest.cc +++ b/chrome/browser/policy/cloud_policy_controller_unittest.cc @@ -94,7 +94,6 @@ class CloudPolicyControllerTest : public testing::Test { controller_.reset(); // Unregisters observers. } - // Takes ownership of |backend|. void CreateNewController() { controller_.reset(new CloudPolicyController( &service_, cache_.get(), token_fetcher_.get(), &identity_strategy_, @@ -102,12 +101,10 @@ class CloudPolicyControllerTest : public testing::Test { } 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)); + const PolicyMap* policy_map = cache_->policy( + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY); + ASSERT_TRUE(Value::Equals(&expected, policy_map->Get(kPolicyDisableSpdy))); } void SetupIdentityStrategy( diff --git a/chrome/browser/policy/cloud_policy_provider.cc b/chrome/browser/policy/cloud_policy_provider.cc new file mode 100644 index 0000000..d8b3c79 --- /dev/null +++ b/chrome/browser/policy/cloud_policy_provider.cc @@ -0,0 +1,17 @@ +// 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_provider.h" + +namespace policy { + +CloudPolicyProvider::CloudPolicyProvider( + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list) + : ConfigurationPolicyProvider(policy_list) { +} + +CloudPolicyProvider::~CloudPolicyProvider() { +} + +} // namespace policy diff --git a/chrome/browser/policy/cloud_policy_provider.h b/chrome/browser/policy/cloud_policy_provider.h new file mode 100644 index 0000000..5fa6d98 --- /dev/null +++ b/chrome/browser/policy/cloud_policy_provider.h @@ -0,0 +1,47 @@ +// 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_PROVIDER_H_ +#define CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_H_ +#pragma once + +#include "base/basictypes.h" +#include "chrome/browser/policy/cloud_policy_cache_base.h" +#include "chrome/browser/policy/configuration_policy_provider.h" + +namespace policy { + +// A policy provider having multiple backend caches, combining their relevant +// PolicyMaps and keeping the result cached. The underlying caches are kept as +// weak references and can be added dynamically. Also the +// |CloudPolicyProvider| instance listens to cache-notifications and removes +// the caches automatically when they go away. The order in which the caches are +// stored matters! The first cache is applied as is and the following caches +// only contribute the not-yet applied policies. There are two functions to add +// a new cache: +// PrependCache(cache): adds |cache| to the front (i.e. most important cache). +// AppendCache(cache): adds |cache| to the back (i.e. least important cache). +class CloudPolicyProvider : public ConfigurationPolicyProvider { + public: + explicit CloudPolicyProvider( + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list); + virtual ~CloudPolicyProvider(); + + // Adds a new instance of CloudPolicyCacheBase to the end of |caches_|. + // Does not take ownership of |cache| and listens to OnCacheGoingAway to + // automatically remove it from |caches_|. + virtual void AppendCache(CloudPolicyCacheBase* cache) = 0; + + // Adds a new instance of CloudPolicyCacheBase to the beginning of |caches_|. + // Does not take ownership of |cache| and listens to OnCacheGoingAway to + // automatically remove it from |caches_|. + virtual void PrependCache(CloudPolicyCacheBase* cache) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_H_ diff --git a/chrome/browser/policy/cloud_policy_provider_impl.cc b/chrome/browser/policy/cloud_policy_provider_impl.cc new file mode 100644 index 0000000..8d0509b --- /dev/null +++ b/chrome/browser/policy/cloud_policy_provider_impl.cc @@ -0,0 +1,125 @@ +// 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_provider_impl.h" + +#include <set> + +#include "base/values.h" +#include "chrome/browser/policy/configuration_policy_pref_store.h" + +namespace policy { + +CloudPolicyProviderImpl::CloudPolicyProviderImpl( + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, + CloudPolicyCacheBase::PolicyLevel level) + : CloudPolicyProvider(policy_list), + level_(level) {} + +CloudPolicyProviderImpl::~CloudPolicyProviderImpl() { + for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i) + (*i)->RemoveObserver(this); + + FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, + observer_list_, OnProviderGoingAway()); +} + +bool CloudPolicyProviderImpl::Provide( + ConfigurationPolicyStoreInterface* store) { + ApplyPolicyMap(&combined_, store); + return true; +} + +bool CloudPolicyProviderImpl::IsInitializationComplete() const { + for (ListType::const_iterator i = caches_.begin(); i != caches_.end(); ++i) { + if (!(*i)->IsReady()) { + return false; + } + } + return true; +} + +void CloudPolicyProviderImpl::AddObserver( + ConfigurationPolicyProvider::Observer* observer) { + observer_list_.AddObserver(observer); +} + +void CloudPolicyProviderImpl::RemoveObserver( + ConfigurationPolicyProvider::Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +void CloudPolicyProviderImpl::OnCacheUpdate(CloudPolicyCacheBase* cache) { + RecombineCachesAndMaybeTriggerUpdate(); +} + +void CloudPolicyProviderImpl::OnCacheGoingAway(CloudPolicyCacheBase* cache) { + cache->RemoveObserver(this); + for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i) { + if (*i == cache) { + caches_.erase(i); + break; + } + } + + RecombineCachesAndMaybeTriggerUpdate(); +} + +void CloudPolicyProviderImpl::AppendCache(CloudPolicyCacheBase* cache) { + cache->AddObserver(this); + caches_.push_back(cache); + RecombineCachesAndMaybeTriggerUpdate(); +} + +void CloudPolicyProviderImpl::PrependCache(CloudPolicyCacheBase* cache) { + cache->AddObserver(this); + caches_.insert(caches_.begin(), cache); + RecombineCachesAndMaybeTriggerUpdate(); +} + +// static +void CloudPolicyProviderImpl::CombineTwoPolicyMaps(const PolicyMap& base, + const PolicyMap& overlay, + PolicyMap* out_map) { + bool added_proxy_policy = false; + out_map->Clear(); + + for (PolicyMap::const_iterator i = base.begin(); i != base.end(); ++i) { + out_map->Set(i->first, i->second->DeepCopy()); + added_proxy_policy = added_proxy_policy || + ConfigurationPolicyPrefStore::IsProxyPolicy(i->first); + } + + // Add every entry of |overlay| which has not been added by |base|. Only add + // proxy policies if none of them was added by |base|. + for (PolicyMap::const_iterator i = overlay.begin(); i != overlay.end(); ++i) { + if (ConfigurationPolicyPrefStore::IsProxyPolicy(i->first)) { + if (!added_proxy_policy) { + out_map->Set(i->first, i->second->DeepCopy()); + } + } else if (!out_map->Get(i->first)) { + out_map->Set(i->first, i->second->DeepCopy()); + } + } +} + +void CloudPolicyProviderImpl::RecombineCachesAndMaybeTriggerUpdate() { + PolicyMap newly_combined; + for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i) { + if (!(*i)->IsReady()) + continue; + PolicyMap tmp_map; + CombineTwoPolicyMaps(newly_combined, *(*i)->policy(level_), &tmp_map); + newly_combined.Swap(&tmp_map); + } + if (newly_combined.Equals(combined_)) + return; + + // Trigger a notification if there was a change. + combined_.Swap(&newly_combined); + FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, + observer_list_, OnUpdatePolicy()); +} + +} // namespace policy diff --git a/chrome/browser/policy/cloud_policy_provider_impl.h b/chrome/browser/policy/cloud_policy_provider_impl.h new file mode 100644 index 0000000..a1dc55e --- /dev/null +++ b/chrome/browser/policy/cloud_policy_provider_impl.h @@ -0,0 +1,75 @@ +// 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_PROVIDER_IMPL_H_ +#define CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_IMPL_H_ +#pragma once + +#include "base/observer_list.h" +#include "chrome/browser/policy/cloud_policy_cache_base.h" +#include "chrome/browser/policy/cloud_policy_provider.h" +#include "chrome/browser/policy/policy_map.h" + +namespace policy { + +class CloudPolicyProviderImpl : public CloudPolicyProvider, + public CloudPolicyCacheBase::Observer { + public: + CloudPolicyProviderImpl(const PolicyDefinitionList* policy_list, + CloudPolicyCacheBase::PolicyLevel level); + virtual ~CloudPolicyProviderImpl(); + + // ConfigurationPolicyProvider implementation. + virtual bool Provide(ConfigurationPolicyStoreInterface* store) OVERRIDE; + virtual bool IsInitializationComplete() const OVERRIDE; + virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer) + OVERRIDE; + virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer) + OVERRIDE; + + // CloudPolicyCacheBase::Observer implementation. + virtual void OnCacheUpdate(CloudPolicyCacheBase* cache) OVERRIDE; + virtual void OnCacheGoingAway(CloudPolicyCacheBase* cache) OVERRIDE; + virtual void AppendCache(CloudPolicyCacheBase* cache) OVERRIDE; + virtual void PrependCache(CloudPolicyCacheBase* cache) OVERRIDE; + + private: + friend class CloudPolicyProviderTest; + + // Combines two PolicyMap and stores the result in out_map. The policies in + // |base| take precedence over the policies in |overlay|. Proxy policies are + // only applied in groups, that is if at least one proxy policy is present in + // |base| then no proxy related policy of |overlay| will be applied. + static void CombineTwoPolicyMaps(const PolicyMap& base, + const PolicyMap& overlay, + PolicyMap* out_map); + + // Recompute |combined_| from |caches_| and trigger an OnUpdatePolicy if + // something changed. This is called whenever a change in one of the caches + // is observed. For i=0..n-1: |caches_[i]| will contribute all its policies + // except those already provided by |caches_[0]|..|caches_[i-1]|. Proxy + // related policies are handled as a special case: they are only applied in + // groups. + void RecombineCachesAndMaybeTriggerUpdate(); + + // The underlying policy caches. + typedef std::vector<CloudPolicyCacheBase*> ListType; + ListType caches_; + + // Policy level this provider will handle. + CloudPolicyCacheBase::PolicyLevel level_; + + // Provider observers that are registered with this provider. + ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_; + + // The currently valid combination of all the maps in |caches_|. Will be + // applied as is on call of Provide. + PolicyMap combined_; + + DISALLOW_COPY_AND_ASSIGN(CloudPolicyProviderImpl); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_IMPL_H_ diff --git a/chrome/browser/policy/cloud_policy_provider_unittest.cc b/chrome/browser/policy/cloud_policy_provider_unittest.cc new file mode 100644 index 0000000..63ee170 --- /dev/null +++ b/chrome/browser/policy/cloud_policy_provider_unittest.cc @@ -0,0 +1,240 @@ +// 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_provider.h" + +#include "base/basictypes.h" +#include "base/values.h" +#include "chrome/browser/policy/cloud_policy_cache_base.h" +#include "chrome/browser/policy/cloud_policy_provider_impl.h" +#include "chrome/browser/policy/configuration_policy_pref_store.h" +#include "chrome/browser/policy/mock_configuration_policy_store.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::AnyNumber; +using testing::_; + +namespace policy { + +class MockCloudPolicyCache : public CloudPolicyCacheBase { + public: + MockCloudPolicyCache() {} + virtual ~MockCloudPolicyCache() {} + + // CloudPolicyCacheBase implementation. + void Load() {} + void SetPolicy(const em::PolicyFetchResponse& policy) {} + bool DecodePolicyData(const em::PolicyData& policy_data, + PolicyMap* mandatory, + PolicyMap* recommended) { + return true; + } + bool IsReady() { + return true; + } + + // Non-const accessors for underlying PolicyMaps. + PolicyMap* raw_mandatory_policy() { + return &mandatory_policy_; + } + + PolicyMap* raw_recommended_policy() { + return &recommended_policy_; + } + + void SetUnmanaged() { + is_unmanaged_ = true; + } + + void set_initialized(bool initialized) { + initialization_complete_ = initialized; + } + + private: + DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyCache); +}; + +class CloudPolicyProviderTest : public testing::Test { + protected: + void CreateCloudPolicyProvider(CloudPolicyCacheBase::PolicyLevel level) { + cloud_policy_provider_.reset(new CloudPolicyProviderImpl( + ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), level)); + } + + // Appends the caches to a provider and then provides the policies to + // |store_|. + void RunCachesThroughProvider(MockCloudPolicyCache caches[], int n, + CloudPolicyCacheBase::PolicyLevel level) { + store_.reset(new MockConfigurationPolicyStore); + CloudPolicyProviderImpl provider( + policy::ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), + level); + for (int i = 0; i < n; i++) { + provider.AppendCache(&caches[i]); + } + EXPECT_CALL(*store_.get(), Apply(_, _)).Times(AnyNumber()); + provider.Provide(store_.get()); + } + + // Checks a string policy in |store_|. + void ExpectStringPolicy(const std::string& expected, + ConfigurationPolicyType type) { + const Value* value = store_->Get(type); + std::string string_value; + ASSERT_TRUE(value != NULL); + EXPECT_TRUE(value->GetAsString(&string_value)); + EXPECT_EQ(expected, string_value); + } + + // Checks a boolean policy in |store_|. + void ExpectBoolPolicy(bool expected, ConfigurationPolicyType type) { + const Value* value = store_->Get(type); + bool bool_value; + ASSERT_TRUE(value != NULL); + EXPECT_TRUE(value->GetAsBoolean(&bool_value)); + EXPECT_EQ(expected, bool_value); + } + + void ExpectNoPolicy(ConfigurationPolicyType type) { + EXPECT_TRUE(NULL == store_->Get(type)); + } + + void CombineTwoPolicyMaps(const PolicyMap& base, + const PolicyMap& overlay, + PolicyMap* out_map) { + DCHECK(cloud_policy_provider_.get()); + cloud_policy_provider_->CombineTwoPolicyMaps(base, overlay, out_map); + } + + private: + // Some tests need a list of policies that doesn't contain any proxy + // policies. Note: these policies will be handled as if they had the + // type of Value::TYPE_INTEGER. + static const ConfigurationPolicyType simple_policies[]; + + scoped_ptr<CloudPolicyProviderImpl> cloud_policy_provider_; + scoped_ptr<MockConfigurationPolicyStore> store_; +}; + +// Proxy setting distributed over multiple caches. +TEST_F(CloudPolicyProviderTest, + ProxySettingDistributedOverMultipleCaches) { + // There are proxy_policy_count()+1 = 6 caches and they are mixed together by + // one instance of CloudPolicyProvider. The first cache has some policies but + // no proxy-related ones. The following caches have each one proxy-policy set. + const int n = 6; + MockCloudPolicyCache caches[n]; + + // Prepare |cache[0]| to serve some non-proxy policies. + caches[0].raw_mandatory_policy()->Set(kPolicyShowHomeButton, + Value::CreateBooleanValue(true)); + caches[0].raw_mandatory_policy()->Set(kPolicyIncognitoEnabled, + Value::CreateBooleanValue(true)); + caches[0].raw_mandatory_policy()->Set(kPolicyTranslateEnabled, + Value::CreateBooleanValue(true)); + caches[0].set_initialized(true); + + // Prepare the other caches to serve one proxy-policy each. + caches[1].raw_mandatory_policy()->Set(kPolicyProxyMode, + Value::CreateStringValue("cache 1")); + caches[1].set_initialized(true); + caches[2].raw_mandatory_policy()->Set(kPolicyProxyServerMode, + Value::CreateIntegerValue(2)); + caches[2].set_initialized(true); + caches[3].raw_mandatory_policy()->Set(kPolicyProxyServer, + Value::CreateStringValue("cache 3")); + caches[3].set_initialized(true); + caches[4].raw_mandatory_policy()->Set(kPolicyProxyPacUrl, + Value::CreateStringValue("cache 4")); + caches[4].set_initialized(true); + caches[5].raw_mandatory_policy()->Set(kPolicyProxyMode, + Value::CreateStringValue("cache 5")); + caches[5].set_initialized(true); + + RunCachesThroughProvider( + caches, n, CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY); + + // Verify expectations. + ExpectStringPolicy("cache 1", kPolicyProxyMode); + ExpectNoPolicy(kPolicyProxyServerMode); + ExpectNoPolicy(kPolicyProxyServer); + ExpectNoPolicy(kPolicyProxyPacUrl); + ExpectBoolPolicy(true, kPolicyShowHomeButton); + ExpectBoolPolicy(true, kPolicyIncognitoEnabled); + ExpectBoolPolicy(true, kPolicyTranslateEnabled); +} + +// Combining two PolicyMaps. +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsSame) { + PolicyMap A, B, C; + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); + A.Set(kPolicyHomepageLocation, + Value::CreateStringValue("http://www.chromium.org")); + B.Set(kPolicyHomepageLocation, + Value::CreateStringValue("http://www.google.com")); + A.Set(kPolicyApplicationLocaleValue, Value::CreateStringValue("hu")); + B.Set(kPolicyApplicationLocaleValue, Value::CreateStringValue("us")); + A.Set(kPolicyDevicePolicyRefreshRate, new FundamentalValue(100)); + B.Set(kPolicyDevicePolicyRefreshRate, new FundamentalValue(200)); + CombineTwoPolicyMaps(A, B, &C); + EXPECT_TRUE(A.Equals(C)); +} + +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsEmpty) { + PolicyMap A, B, C; + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); + CombineTwoPolicyMaps(A, B, &C); + EXPECT_TRUE(C.empty()); +} + +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsPartial) { + PolicyMap A, B, C; + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); + + A.Set(kPolicyHomepageLocation, + Value::CreateStringValue("http://www.chromium.org")); + B.Set(kPolicyHomepageLocation, + Value::CreateStringValue("http://www.google.com")); + B.Set(kPolicyApplicationLocaleValue, Value::CreateStringValue("us")); + A.Set(kPolicyDevicePolicyRefreshRate, new FundamentalValue(100)); + B.Set(kPolicyDevicePolicyRefreshRate, new FundamentalValue(200)); + CombineTwoPolicyMaps(A, B, &C); + + const Value* value; + std::string string_value; + int int_value; + value = C.Get(kPolicyHomepageLocation); + ASSERT_TRUE(NULL != value); + EXPECT_TRUE(value->GetAsString(&string_value)); + EXPECT_EQ("http://www.chromium.org", string_value); + value = C.Get(kPolicyApplicationLocaleValue); + ASSERT_TRUE(NULL != value); + EXPECT_TRUE(value->GetAsString(&string_value)); + EXPECT_EQ("us", string_value); + value = C.Get(kPolicyDevicePolicyRefreshRate); + ASSERT_TRUE(NULL != value); + EXPECT_TRUE(value->GetAsInteger(&int_value)); + EXPECT_EQ(100, int_value); +} + +TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsProxies) { + const int a_value = 1; + const int b_value = -1; + PolicyMap A, B, C; + CreateCloudPolicyProvider(CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED); + + A.Set(policy::kPolicyProxyMode, Value::CreateIntegerValue(a_value)); + + B.Set(policy::kPolicyProxyServerMode, Value::CreateIntegerValue(b_value)); + B.Set(policy::kPolicyProxyServer, Value::CreateIntegerValue(b_value)); + B.Set(policy::kPolicyProxyPacUrl, Value::CreateIntegerValue(b_value)); + B.Set(policy::kPolicyProxyBypassList, Value::CreateIntegerValue(b_value)); + + CombineTwoPolicyMaps(A, B, &C); + + EXPECT_TRUE(A.Equals(C)); + EXPECT_FALSE(B.Equals(C)); +} + +} // namespace policy diff --git a/chrome/browser/policy/cloud_policy_subsystem.cc b/chrome/browser/policy/cloud_policy_subsystem.cc index b85b7c9..ffbcfce 100644 --- a/chrome/browser/policy/cloud_policy_subsystem.cc +++ b/chrome/browser/policy/cloud_policy_subsystem.cc @@ -12,7 +12,6 @@ #include "chrome/browser/policy/cloud_policy_cache_base.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/browser/policy/policy_notifier.h" @@ -136,21 +135,6 @@ void CloudPolicySubsystem::StopAutoRetry() { device_token_fetcher_->StopAutoRetry(); } -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; -} - // static void CloudPolicySubsystem::RegisterPrefs(PrefService* pref_service) { pref_service->RegisterIntegerPref(prefs::kDevicePolicyRefreshRate, @@ -176,10 +160,9 @@ void CloudPolicySubsystem::Observe(NotificationType type, if (type == NotificationType::PREF_CHANGED) { DCHECK_EQ(*(Details<std::string>(details).ptr()), std::string(refresh_pref_name_)); - PrefService* pref_service = Source<PrefService>(source).ptr(); - // Temporarily also consider the profile preference service as a valid - // source, since we cannot yet push user cloud policy to |local_state|. - UpdatePolicyRefreshRate(pref_service->GetInteger(refresh_pref_name_)); + PrefService* local_state = g_browser_process->local_state(); + DCHECK_EQ(Source<PrefService>(source).ptr(), local_state); + UpdatePolicyRefreshRate(local_state->GetInteger(refresh_pref_name_)); } else { NOTREACHED(); } diff --git a/chrome/browser/policy/cloud_policy_subsystem.h b/chrome/browser/policy/cloud_policy_subsystem.h index f50eff9..d886216 100644 --- a/chrome/browser/policy/cloud_policy_subsystem.h +++ b/chrome/browser/policy/cloud_policy_subsystem.h @@ -7,7 +7,6 @@ #pragma once #include "base/memory/scoped_ptr.h" -#include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "content/common/notification_observer.h" #include "net/base/network_change_notifier.h" @@ -19,7 +18,6 @@ namespace policy { class CloudPolicyCacheBase; class CloudPolicyController; class CloudPolicyIdentityStrategy; -class ConfigurationPolicyProvider; class DeviceManagementService; class DeviceTokenFetcher; class PolicyNotifier; @@ -94,9 +92,6 @@ class CloudPolicySubsystem // subsystem. void StopAutoRetry(); - ConfigurationPolicyProvider* GetManagedPolicyProvider(); - ConfigurationPolicyProvider* GetRecommendedPolicyProvider(); - // Registers cloud policy related prefs. static void RegisterPrefs(PrefService* pref_service); diff --git a/chrome/browser/policy/cloud_policy_subsystem_unittest.cc b/chrome/browser/policy/cloud_policy_subsystem_unittest.cc index e2f3167..9d91783 100644 --- a/chrome/browser/policy/cloud_policy_subsystem_unittest.cc +++ b/chrome/browser/policy/cloud_policy_subsystem_unittest.cc @@ -19,6 +19,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/testing_browser_process.h" #include "chrome/test/testing_pref_service.h" +#include "content/browser/browser_thread.h" #include "content/common/url_fetcher.h" #include "policy/policy_constants.h" #include "testing/gmock/include/gmock/gmock.h" @@ -243,10 +244,9 @@ class CloudPolicySubsystemTestBase : public TESTBASE { private: // Verifies for a given policy that it is provided by the subsystem. void VerifyPolicy(enum ConfigurationPolicyType type, Value* expected) { - MockConfigurationPolicyStore store; - EXPECT_CALL(store, Apply(_, _)).Times(AtLeast(1)); - cache_->GetManagedPolicyProvider()->Provide(&store); - ASSERT_TRUE(Value::Equals(expected, store.Get(type))); + const PolicyMap* policy_map = cache_->policy( + CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY); + ASSERT_TRUE(Value::Equals(expected, policy_map->Get(type))); } // Verifies that the last recorded run of the subsystem did not issue diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc index b7a29cf..ccba75b 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.cc +++ b/chrome/browser/policy/configuration_policy_pref_store.cc @@ -21,11 +21,8 @@ #include "chrome/browser/policy/browser_policy_connector.h" #include "chrome/browser/policy/configuration_policy_provider.h" #include "chrome/browser/policy/policy_path_parser.h" -#include "chrome/browser/policy/profile_policy_connector.h" -#include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chrome/browser/prefs/pref_value_map.h" #include "chrome/browser/prefs/proxy_config_dictionary.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/search_terms_data.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/common/pref_names.h" @@ -404,11 +401,7 @@ bool ConfigurationPolicyPrefKeeper::ApplyProxyPolicy( // We only collect the values until we have sufficient information when // FinalizeProxyPolicySettings() is called to determine whether the presented // values were correct and apply them in that case. - if (policy == kPolicyProxyMode || - policy == kPolicyProxyServerMode || - policy == kPolicyProxyServer || - policy == kPolicyProxyPacUrl || - policy == kPolicyProxyBypassList) { + if (ConfigurationPolicyPrefStore::IsProxyPolicy(policy)) { delete proxy_policies_[policy]; proxy_policies_[policy] = value; return true; @@ -900,20 +893,9 @@ ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() { // static ConfigurationPolicyPrefStore* -ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore( - Profile* profile) { - ConfigurationPolicyProvider* provider = NULL; - if (profile) { - // For user policy, return the profile's policy provider. - provider = policy::ProfilePolicyConnectorFactory::GetForProfile(profile)-> - 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(provider); +ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore() { + return new ConfigurationPolicyPrefStore( + g_browser_process->browser_policy_connector()->GetManagedCloudProvider()); } // static @@ -927,20 +909,10 @@ ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() { // static ConfigurationPolicyPrefStore* -ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore( - Profile* profile) { - ConfigurationPolicyProvider* provider = NULL; - if (profile) { - // For user policy, return the profile's policy provider. - provider = policy::ProfilePolicyConnectorFactory::GetForProfile(profile)-> - 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); +ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore() { + return new ConfigurationPolicyPrefStore( + g_browser_process->browser_policy_connector()-> + GetRecommendedCloudProvider()); } /* static */ @@ -1107,6 +1079,15 @@ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() { return &policy_list; } +bool +ConfigurationPolicyPrefStore::IsProxyPolicy(ConfigurationPolicyType policy) { + return policy == kPolicyProxyMode || + policy == kPolicyProxyServerMode || + policy == kPolicyProxyServer || + policy == kPolicyProxyPacUrl || + policy == kPolicyProxyBypassList; +} + ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore( ConfigurationPolicyProvider* provider) : provider_(provider), diff --git a/chrome/browser/policy/configuration_policy_pref_store.h b/chrome/browser/policy/configuration_policy_pref_store.h index 6b752e1..44459eb 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.h +++ b/chrome/browser/policy/configuration_policy_pref_store.h @@ -17,8 +17,6 @@ #include "chrome/browser/policy/configuration_policy_store_interface.h" #include "chrome/common/pref_store.h" -class Profile; - namespace policy { class ConfigurationPolicyPrefKeeper; @@ -50,8 +48,7 @@ class ConfigurationPolicyPrefStore static ConfigurationPolicyPrefStore* CreateManagedPlatformPolicyPrefStore(); // Creates a ConfigurationPolicyPrefStore that reads managed cloud policy. - static ConfigurationPolicyPrefStore* CreateManagedCloudPolicyPrefStore( - Profile* profile); + static ConfigurationPolicyPrefStore* CreateManagedCloudPolicyPrefStore(); // Creates a ConfigurationPolicyPrefStore that reads recommended platform // policy. @@ -59,13 +56,15 @@ class ConfigurationPolicyPrefStore CreateRecommendedPlatformPolicyPrefStore(); // Creates a ConfigurationPolicyPrefStore that reads recommended cloud policy. - static ConfigurationPolicyPrefStore* CreateRecommendedCloudPolicyPrefStore( - Profile* profile); + static ConfigurationPolicyPrefStore* CreateRecommendedCloudPolicyPrefStore(); // Returns the default policy definition list for Chrome. static const ConfigurationPolicyProvider::PolicyDefinitionList* GetChromePolicyDefinitionList(); + // Returns true if the given policy is a proxy policy. + static bool IsProxyPolicy(ConfigurationPolicyType policy); + private: explicit ConfigurationPolicyPrefStore(ConfigurationPolicyProvider* provider); diff --git a/chrome/browser/policy/configuration_policy_store_interface.cc b/chrome/browser/policy/configuration_policy_store_interface.cc deleted file mode 100644 index 40cf472..0000000 --- a/chrome/browser/policy/configuration_policy_store_interface.cc +++ /dev/null @@ -1,40 +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_store_interface.h" - -#include "base/values.h" - -namespace { - -bool IsProxyPolicy(policy::ConfigurationPolicyType policy) { - return policy == policy::kPolicyProxyMode || - policy == policy::kPolicyProxyServerMode || - policy == policy::kPolicyProxyServer || - policy == policy::kPolicyProxyPacUrl || - policy == policy::kPolicyProxyBypassList; -} - -} // namespace - -namespace policy { - -void ObservingPolicyStoreInterface::Apply(ConfigurationPolicyType policy, - Value* value) { - next_->Apply(policy, value); - - if (IsProxyPolicy(policy)) - proxy_policy_applied_ = true; -} - -void FilteringPolicyStoreInterface::Apply(ConfigurationPolicyType policy, - Value* value) { - // Apply() takes ownership of |value|. - if (IsProxyPolicy(policy) && apply_proxy_policies_) - next_->Apply(policy, value); - else - delete value; -} - -} // namespace policy diff --git a/chrome/browser/policy/configuration_policy_store_interface.h b/chrome/browser/policy/configuration_policy_store_interface.h index b05fab4..1d3bf43 100644 --- a/chrome/browser/policy/configuration_policy_store_interface.h +++ b/chrome/browser/policy/configuration_policy_store_interface.h @@ -7,7 +7,6 @@ #pragma once #include "base/basictypes.h" -#include "base/compiler_specific.h" #include "policy/configuration_policy_type.h" class Value; @@ -50,48 +49,6 @@ class ConfigurationPolicyStoreInterface { DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyStoreInterface); }; -// Helper class. A pass-through ConfigurationPolicyStoreInterface, that observes -// the application of well-known policies. -class ObservingPolicyStoreInterface: public ConfigurationPolicyStoreInterface { - public: - explicit ObservingPolicyStoreInterface( - ConfigurationPolicyStoreInterface* next) - : next_(next), - proxy_policy_applied_(false) {} - - // ConfigurationPolicyStoreInterface methods: - virtual void Apply(ConfigurationPolicyType policy, Value* value) OVERRIDE; - - bool IsProxyPolicyApplied() const { - return proxy_policy_applied_; - } - - private: - ConfigurationPolicyStoreInterface* next_; - bool proxy_policy_applied_; - - DISALLOW_COPY_AND_ASSIGN(ObservingPolicyStoreInterface); -}; - -// Helper class. A ConfigurationPolicyStoreInterface that filters out most -// policies, and only applies well-known policies. -class FilteringPolicyStoreInterface: public ConfigurationPolicyStoreInterface { - public: - FilteringPolicyStoreInterface(ConfigurationPolicyStoreInterface* next, - bool apply_proxy_policies) - : next_(next), - apply_proxy_policies_(apply_proxy_policies) {} - - // ConfigurationPolicyStoreInterface methods: - virtual void Apply(ConfigurationPolicyType policy, Value* value) OVERRIDE; - - private: - ConfigurationPolicyStoreInterface* next_; - bool apply_proxy_policies_; - - DISALLOW_COPY_AND_ASSIGN(FilteringPolicyStoreInterface); -}; - } // namespace policy #endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_STORE_INTERFACE_H_ diff --git a/chrome/browser/policy/configuration_policy_store_interface_unittest.cc b/chrome/browser/policy/configuration_policy_store_interface_unittest.cc deleted file mode 100644 index c976372..0000000 --- a/chrome/browser/policy/configuration_policy_store_interface_unittest.cc +++ /dev/null @@ -1,57 +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_store_interface.h" -#include "chrome/browser/policy/mock_configuration_policy_store.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; - -namespace policy { - -TEST(ConfigurationPolicyStoreInterfaceTest, Observer) { - MockConfigurationPolicyStore store; - EXPECT_CALL(store, Apply(_, _)).Times(3); - ObservingPolicyStoreInterface observer(&store); - - EXPECT_FALSE(observer.IsProxyPolicyApplied()); - observer.Apply(kPolicyJavascriptEnabled, Value::CreateBooleanValue(true)); - EXPECT_FALSE(observer.IsProxyPolicyApplied()); - observer.Apply(kPolicyProxyMode, Value::CreateStringValue("direct")); - EXPECT_TRUE(observer.IsProxyPolicyApplied()); - observer.Apply(kPolicyIncognitoEnabled, Value::CreateBooleanValue(true)); - EXPECT_TRUE(observer.IsProxyPolicyApplied()); - - EXPECT_TRUE(store.Get(kPolicyJavascriptEnabled) != NULL); - EXPECT_TRUE(store.Get(kPolicyProxyMode) != NULL); - EXPECT_TRUE(store.Get(kPolicyIncognitoEnabled) != NULL); - EXPECT_TRUE(store.Get(kPolicyPrintingEnabled) == NULL); -} - -TEST(ConfigurationPolicyStoreInterfaceTest, Filter) { - MockConfigurationPolicyStore store_pass; - EXPECT_CALL(store_pass, Apply(_, _)).Times(1); - FilteringPolicyStoreInterface filter_pass(&store_pass, true); - - EXPECT_TRUE(store_pass.policy_map().empty()); - filter_pass.Apply(kPolicyJavascriptEnabled, Value::CreateBooleanValue(true)); - EXPECT_TRUE(store_pass.policy_map().empty()); - filter_pass.Apply(kPolicyProxyMode, Value::CreateStringValue("direct")); - EXPECT_FALSE(store_pass.policy_map().empty()); - EXPECT_EQ(store_pass.policy_map().size(), 1u); - EXPECT_TRUE(store_pass.Get(kPolicyJavascriptEnabled) == NULL); - EXPECT_TRUE(store_pass.Get(kPolicyProxyMode) != NULL); - - MockConfigurationPolicyStore store_block; - EXPECT_CALL(store_block, Apply(_, _)).Times(0); - FilteringPolicyStoreInterface filter_block(&store_block, false); - - EXPECT_TRUE(store_block.policy_map().empty()); - filter_block.Apply(kPolicyJavascriptEnabled, Value::CreateBooleanValue(true)); - EXPECT_TRUE(store_block.policy_map().empty()); - filter_block.Apply(kPolicyProxyMode, Value::CreateStringValue("direct")); - EXPECT_TRUE(store_block.policy_map().empty()); -} - -} // namespace policy diff --git a/chrome/browser/policy/device_policy_cache.cc b/chrome/browser/policy/device_policy_cache.cc index bb9f533..de68940 100644 --- a/chrome/browser/policy/device_policy_cache.cc +++ b/chrome/browser/policy/device_policy_cache.cc @@ -11,7 +11,6 @@ #include "base/values.h" #include "chrome/browser/chromeos/cros_settings_names.h" #include "chrome/browser/chromeos/login/ownership_service.h" -#include "chrome/browser/chromeos/login/signed_settings_helper.h" #include "chrome/browser/chromeos/user_cros_settings_provider.h" #include "chrome/browser/policy/configuration_policy_pref_store.h" #include "chrome/browser/policy/device_policy_identity_strategy.h" @@ -181,6 +180,10 @@ void DevicePolicyCache::SetUnmanaged() { // This is not supported for DevicePolicyCache. } +bool DevicePolicyCache::IsReady() { + return initialization_complete() || !starting_up_; +} + void DevicePolicyCache::OnRetrievePolicyCompleted( chromeos::SignedSettings::ReturnCode code, const em::PolicyFetchResponse& policy) { diff --git a/chrome/browser/policy/device_policy_cache.h b/chrome/browser/policy/device_policy_cache.h index ce29c97..7e1082d 100644 --- a/chrome/browser/policy/device_policy_cache.h +++ b/chrome/browser/policy/device_policy_cache.h @@ -35,6 +35,7 @@ class DevicePolicyCache : public CloudPolicyCacheBase, virtual void Load() OVERRIDE; virtual void SetPolicy(const em::PolicyFetchResponse& policy) OVERRIDE; virtual void SetUnmanaged() OVERRIDE; + virtual bool IsReady() OVERRIDE; // SignedSettingsHelper::Callback implementation: virtual void OnRetrievePolicyCompleted( diff --git a/chrome/browser/policy/dummy_cloud_policy_provider.cc b/chrome/browser/policy/dummy_cloud_policy_provider.cc new file mode 100644 index 0000000..6646fc1 --- /dev/null +++ b/chrome/browser/policy/dummy_cloud_policy_provider.cc @@ -0,0 +1,40 @@ +// 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/dummy_cloud_policy_provider.h" + +namespace policy { + +DummyCloudPolicyProvider::DummyCloudPolicyProvider( + const PolicyDefinitionList* policy_list) + : CloudPolicyProvider(policy_list) { +} + +DummyCloudPolicyProvider::~DummyCloudPolicyProvider() { + FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, + observer_list_, + OnProviderGoingAway()); +} + +void DummyCloudPolicyProvider::AppendCache(CloudPolicyCacheBase* cache) { +} + +void DummyCloudPolicyProvider::PrependCache(CloudPolicyCacheBase* cache) { +} + +bool DummyCloudPolicyProvider::Provide( + ConfigurationPolicyStoreInterface* store) { + return true; +} +void DummyCloudPolicyProvider::AddObserver( + ConfigurationPolicyProvider::Observer* observer) { + observer_list_.AddObserver(observer); +} + +void DummyCloudPolicyProvider::RemoveObserver( + ConfigurationPolicyProvider::Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +} // namespace policy diff --git a/chrome/browser/policy/dummy_cloud_policy_provider.h b/chrome/browser/policy/dummy_cloud_policy_provider.h new file mode 100644 index 0000000..269b5f2 --- /dev/null +++ b/chrome/browser/policy/dummy_cloud_policy_provider.h @@ -0,0 +1,40 @@ +// 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_DUMMY_CLOUD_POLICY_PROVIDER_H_ +#define CHROME_BROWSER_POLICY_DUMMY_CLOUD_POLICY_PROVIDER_H_ +#pragma once + +#include "chrome/browser/policy/cloud_policy_provider.h" + +namespace policy { + +// A cloud policy provider for tests, that provides 0 policies, but always +// reports that it is initialized. +class DummyCloudPolicyProvider : public CloudPolicyProvider { + public: + explicit DummyCloudPolicyProvider(const PolicyDefinitionList* policy_list); + virtual ~DummyCloudPolicyProvider(); + + // CloudPolicyProvider overrides: + virtual void AppendCache(CloudPolicyCacheBase* cache) OVERRIDE; + virtual void PrependCache(CloudPolicyCacheBase* cache) OVERRIDE; + + virtual bool Provide(ConfigurationPolicyStoreInterface* store); + + private: + // ConfigurationPolicyProvider overrides: + virtual void AddObserver( + ConfigurationPolicyProvider::Observer* observer) OVERRIDE; + virtual void RemoveObserver( + ConfigurationPolicyProvider::Observer* observer) OVERRIDE; + + ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_; + + DISALLOW_COPY_AND_ASSIGN(DummyCloudPolicyProvider); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_DUMMY_CLOUD_POLICY_PROVIDER_H_ diff --git a/chrome/browser/policy/profile_policy_connector.cc b/chrome/browser/policy/profile_policy_connector.cc deleted file mode 100644 index ce589a0..0000000 --- a/chrome/browser/policy/profile_policy_connector.cc +++ /dev/null @@ -1,175 +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 "base/file_util.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/policy/browser_policy_connector.h" -#include "chrome/browser/policy/cloud_policy_subsystem.h" -#include "chrome/browser/policy/configuration_policy_pref_store.h" -#include "chrome/browser/policy/profile_policy_connector.h" -#include "chrome/browser/policy/user_policy_cache.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/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"); - -const int64 kServiceInitializationStartupDelay = 2000; - -} // namespace - -namespace policy { - -ProfilePolicyConnector::ProfilePolicyConnector(Profile* profile) - : profile_(profile) { - 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); - - identity_strategy_.reset(new UserPolicyIdentityStrategy( - profile_, - policy_cache_dir.Append(kTokenCacheFile))); - cloud_policy_subsystem_.reset(new CloudPolicySubsystem( - identity_strategy_.get(), - new UserPolicyCache(policy_cache_dir.Append(kPolicyCacheFile)))); - - BrowserPolicyConnector* browser_connector = - g_browser_process->browser_policy_connector(); - - managed_cloud_provider_.reset(new MergingPolicyProvider( - browser_connector->GetManagedCloudProvider(), - cloud_policy_subsystem_->GetManagedPolicyProvider())); - recommended_cloud_provider_.reset(new MergingPolicyProvider( - browser_connector->GetRecommendedCloudProvider(), - cloud_policy_subsystem_->GetRecommendedPolicyProvider())); - } -} - -ProfilePolicyConnector::~ProfilePolicyConnector() { - managed_cloud_provider_.reset(); - recommended_cloud_provider_.reset(); - cloud_policy_subsystem_.reset(); - identity_strategy_.reset(); -} - -void ProfilePolicyConnector::ScheduleServiceInitialization( - int64 delay_milliseconds) { - if (cloud_policy_subsystem_.get()) - cloud_policy_subsystem_->ScheduleServiceInitialization(delay_milliseconds); -} - -void ProfilePolicyConnector::Initialize() { - if (identity_strategy_.get()) - identity_strategy_->LoadTokenCache(); - if (cloud_policy_subsystem_.get()) { - cloud_policy_subsystem_->CompleteInitialization( - prefs::kUserPolicyRefreshRate, - kServiceInitializationStartupDelay); - // Temporarily set the subsystem to listen to profile pref service, since - // we cannot yet serve user cloud policy to |local_state| and we don't want - // the profile reference in the subsystem. - profile_pref_registrar_.Init(profile_->GetPrefs()); - profile_pref_registrar_.Add(prefs::kUserPolicyRefreshRate, - cloud_policy_subsystem_.get()); - } -} - -void ProfilePolicyConnector::Shutdown() { - if (cloud_policy_subsystem_.get()) { - // Remove the temporary profile observer. - profile_pref_registrar_.RemoveAll(); - cloud_policy_subsystem_->Shutdown(); - } -} - -ConfigurationPolicyProvider* - ProfilePolicyConnector::GetManagedCloudProvider() { - return managed_cloud_provider_.get(); -} - -ConfigurationPolicyProvider* - ProfilePolicyConnector::GetRecommendedCloudProvider() { - return recommended_cloud_provider_.get(); -} - -MergingPolicyProvider::MergingPolicyProvider( - ConfigurationPolicyProvider* browser_policy_provider, - ConfigurationPolicyProvider* profile_policy_provider) - : ConfigurationPolicyProvider( - ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList()), - browser_policy_provider_(browser_policy_provider), - profile_policy_provider_(profile_policy_provider), - browser_registrar_(new ConfigurationPolicyObserverRegistrar()), - profile_registrar_(new ConfigurationPolicyObserverRegistrar()) { - if (browser_policy_provider_) - browser_registrar_->Init(browser_policy_provider_, this); - if (profile_policy_provider_) - profile_registrar_->Init(profile_policy_provider_, this); -} - -MergingPolicyProvider::~MergingPolicyProvider() { - if (browser_policy_provider_ || profile_policy_provider_) { - FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, - observer_list_, OnProviderGoingAway()); - } -} - -bool MergingPolicyProvider::Provide(ConfigurationPolicyStoreInterface* store) { - // First, apply the profile policies and observe if interesting policies - // have been applied. - ObservingPolicyStoreInterface observe(store); - bool rv = true; - if (profile_policy_provider_) - rv = profile_policy_provider_->Provide(&observe); - - // Now apply policies from the browser provider, if they were not applied - // by the profile provider. - // Currently, these include only the proxy settings. - if (browser_policy_provider_) { - FilteringPolicyStoreInterface filter(store, - !observe.IsProxyPolicyApplied()); - rv = rv && browser_policy_provider_->Provide(&filter); - } - - return rv; -} - -void MergingPolicyProvider::AddObserver( - ConfigurationPolicyProvider::Observer* observer) { - observer_list_.AddObserver(observer); -} - -void MergingPolicyProvider::RemoveObserver( - ConfigurationPolicyProvider::Observer* observer) { - observer_list_.RemoveObserver(observer); -} - -void MergingPolicyProvider::OnUpdatePolicy() { - FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, - observer_list_, OnUpdatePolicy()); -} - -void MergingPolicyProvider::OnProviderGoingAway() { - if (browser_policy_provider_ || profile_policy_provider_) { - FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, - observer_list_, OnProviderGoingAway()); - browser_registrar_.reset(); - profile_registrar_.reset(); - browser_policy_provider_ = NULL; - profile_policy_provider_ = NULL; - } -} - -} // namespace policy diff --git a/chrome/browser/policy/profile_policy_connector.h b/chrome/browser/policy/profile_policy_connector.h deleted file mode 100644 index 6687078..0000000 --- a/chrome/browser/policy/profile_policy_connector.h +++ /dev/null @@ -1,106 +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_PROFILE_POLICY_CONNECTOR_H_ -#define CHROME_BROWSER_POLICY_PROFILE_POLICY_CONNECTOR_H_ -#pragma once - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "chrome/browser/policy/configuration_policy_provider.h" -#include "chrome/browser/prefs/pref_change_registrar.h" -#include "chrome/browser/profiles/profile_keyed_service.h" - -class Profile; - -namespace policy { - -class CloudPolicySubsystem; -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 ProfileKeyedService { - public: - explicit ProfilePolicyConnector(Profile* profile); - virtual ~ProfilePolicyConnector(); - - // Schedules initialization of the policy backend service if the service is - // already constructed. - void ScheduleServiceInitialization(int64 delay_milliseconds); - - // 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. - // - // TODO(jknotten): this will be called by ProfileDependencyManager -- - // ensure that it is dependent on the right services. See comment - // in ProfilePolicyConnectorFactory::ProfilePolicyConnectorFactory. - virtual void Shutdown() OVERRIDE; - - ConfigurationPolicyProvider* GetManagedCloudProvider(); - ConfigurationPolicyProvider* GetRecommendedCloudProvider(); - - private: - Profile* profile_; - - scoped_ptr<UserPolicyIdentityStrategy> identity_strategy_; - scoped_ptr<CloudPolicySubsystem> cloud_policy_subsystem_; - - scoped_ptr<ConfigurationPolicyProvider> managed_cloud_provider_; - scoped_ptr<ConfigurationPolicyProvider> recommended_cloud_provider_; - - // Temporarily needed until we can serve user policy to local state. - PrefChangeRegistrar profile_pref_registrar_; - - DISALLOW_COPY_AND_ASSIGN(ProfilePolicyConnector); -}; - -// A wrapper for the ProfilePolicyConnector's cloud providers. -// -// Some well-known policies that are not provided by the -// |profile_policy_provider_| are instead provided by the -// |browser_policy_provider_|, thus merging device policies into -// profile policies. -// -// Currently used to pass the device proxy settings into the profile -// preferences. -class MergingPolicyProvider: public ConfigurationPolicyProvider, - public ConfigurationPolicyProvider::Observer { - public: - MergingPolicyProvider(ConfigurationPolicyProvider* browser_policy_provider, - ConfigurationPolicyProvider* profile_policy_provider); - virtual ~MergingPolicyProvider(); - - // ConfigurationPolicyProvider methods: - virtual bool Provide(ConfigurationPolicyStoreInterface* store) OVERRIDE; - virtual void AddObserver( - ConfigurationPolicyProvider::Observer* observer) OVERRIDE; - virtual void RemoveObserver( - ConfigurationPolicyProvider::Observer* observer) OVERRIDE; - - // ConfigurationPolicyProvider::Observer methods: - virtual void OnUpdatePolicy() OVERRIDE; - virtual void OnProviderGoingAway() OVERRIDE; - - private: - ConfigurationPolicyProvider* browser_policy_provider_; - ConfigurationPolicyProvider* profile_policy_provider_; - scoped_ptr<ConfigurationPolicyObserverRegistrar> browser_registrar_; - scoped_ptr<ConfigurationPolicyObserverRegistrar> profile_registrar_; - ObserverList<ConfigurationPolicyProvider::Observer, true> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(MergingPolicyProvider); -}; - - -} // namespace policy - -#endif // CHROME_BROWSER_POLICY_PROFILE_POLICY_CONNECTOR_H_ diff --git a/chrome/browser/policy/profile_policy_connector_factory.cc b/chrome/browser/policy/profile_policy_connector_factory.cc deleted file mode 100644 index 5e89910..0000000 --- a/chrome/browser/policy/profile_policy_connector_factory.cc +++ /dev/null @@ -1,41 +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/profile_policy_connector_factory.h" - -#include "chrome/browser/policy/profile_policy_connector.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_dependency_manager.h" - -namespace policy { - -// static -ProfilePolicyConnector* ProfilePolicyConnectorFactory::GetForProfile( - Profile* profile) { - return static_cast<ProfilePolicyConnector*>( - GetInstance()->GetServiceForProfile(profile, true)); -} - -// static -ProfilePolicyConnectorFactory* ProfilePolicyConnectorFactory::GetInstance() { - return Singleton<ProfilePolicyConnectorFactory>::get(); -} - -ProfilePolicyConnectorFactory::ProfilePolicyConnectorFactory() - : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { - // TODO(jknotten): - // DependsOn(URLRequestContextGetterFactory::GetInstance()); - // DependsOn(PrefServiceFactory::GetInstance()); - // See comment in profile_policy_connector.h w.r.t. Shutdown() -} - -ProfilePolicyConnectorFactory::~ProfilePolicyConnectorFactory() { -} - -ProfileKeyedService* ProfilePolicyConnectorFactory::BuildServiceInstanceFor( - Profile* profile) const { - return new ProfilePolicyConnector(profile); -} - -} // namespace policy diff --git a/chrome/browser/policy/profile_policy_connector_factory.h b/chrome/browser/policy/profile_policy_connector_factory.h deleted file mode 100644 index b5a771b..0000000 --- a/chrome/browser/policy/profile_policy_connector_factory.h +++ /dev/null @@ -1,44 +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_PROFILE_POLICY_CONNECTOR_FACTORY_H_ -#define CHROME_BROWSER_POLICY_PROFILE_POLICY_CONNECTOR_FACTORY_H_ - -#include "base/compiler_specific.h" -#include "base/memory/singleton.h" -#include "chrome/browser/profiles/profile_keyed_service_factory.h" - -class Profile; - -namespace policy { - -class ProfilePolicyConnector; - -// Singleton that owns all ProfilePolicyConnectors and associates them with -// Profiles. Listens for the Profile's destruction notification and cleans up -// the associated ProfilePolicyConnector. - -class ProfilePolicyConnectorFactory : public ProfileKeyedServiceFactory { - public: - // Returns the ProfilePolicyConnector that contains profile-specific - // policy bits for |profile|. - static ProfilePolicyConnector* GetForProfile(Profile* profile); - - static ProfilePolicyConnectorFactory* GetInstance(); - - private: - friend struct DefaultSingletonTraits<ProfilePolicyConnectorFactory>; - - ProfilePolicyConnectorFactory(); - virtual ~ProfilePolicyConnectorFactory(); - - // ProfileKeyedServiceFactory: - virtual ProfileKeyedService* BuildServiceInstanceFor( - Profile* profile) const OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(ProfilePolicyConnectorFactory); -}; - -} // namespace policy - -#endif // CHROME_BROWSER_POLICY_PROFILE_POLICY_CONNECTOR_FACTORY_H_ diff --git a/chrome/browser/policy/profile_policy_connector_unittest.cc b/chrome/browser/policy/profile_policy_connector_unittest.cc deleted file mode 100644 index 7cef1e7..0000000 --- a/chrome/browser/policy/profile_policy_connector_unittest.cc +++ /dev/null @@ -1,57 +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/profile_policy_connector.h" -#include "chrome/browser/policy/mock_configuration_policy_provider.h" -#include "chrome/browser/policy/mock_configuration_policy_store.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; - -namespace policy { - -TEST(MergingPolicyProviderTest, MergeProxySettings) { - MockConfigurationPolicyProvider browser_provider; - MockConfigurationPolicyProvider profile_provider; - MergingPolicyProvider merging_provider(&browser_provider, &profile_provider); - - // First, test settings from profile and no proxy settings from browser. - // Only the profile policies should be forwarded. - browser_provider.AddPolicy(kPolicyJavascriptEnabled, - Value::CreateBooleanValue(true)); - profile_provider.AddPolicy(kPolicyPrintingEnabled, - Value::CreateBooleanValue(true)); - - MockConfigurationPolicyStore store0; - EXPECT_CALL(store0, Apply(_, _)).Times(1); - EXPECT_TRUE(merging_provider.Provide(&store0)); - EXPECT_EQ(store0.policy_map().size(), 1u); - EXPECT_TRUE(store0.Get(kPolicyPrintingEnabled) != NULL); - - // Now have a proxy policy that should be merged. - browser_provider.AddPolicy(kPolicyProxyMode, - Value::CreateStringValue("direct")); - - MockConfigurationPolicyStore store1; - EXPECT_CALL(store1, Apply(_, _)).Times(2); - EXPECT_TRUE(merging_provider.Provide(&store1)); - EXPECT_EQ(store1.policy_map().size(), 2u); - EXPECT_TRUE(store1.Get(kPolicyPrintingEnabled) != NULL); - EXPECT_TRUE(store1.Get(kPolicyProxyMode) != NULL); - - // If the profile includes any proxy policy, no proxy policies should be - // merged from the browser provider. - profile_provider.AddPolicy(kPolicyProxyServer, - Value::CreateStringValue("http://proxy:8080")); - - MockConfigurationPolicyStore store2; - EXPECT_CALL(store2, Apply(_, _)).Times(2); - EXPECT_TRUE(merging_provider.Provide(&store2)); - EXPECT_EQ(store2.policy_map().size(), 2u); - EXPECT_TRUE(store2.Get(kPolicyPrintingEnabled) != NULL); - EXPECT_TRUE(store2.Get(kPolicyProxyServer) != NULL); - EXPECT_TRUE(store2.Get(kPolicyProxyMode) == NULL); -} - -} // namespace policy diff --git a/chrome/browser/policy/user_policy_cache.cc b/chrome/browser/policy/user_policy_cache.cc index d0484f5..4ed00cc 100644 --- a/chrome/browser/policy/user_policy_cache.cc +++ b/chrome/browser/policy/user_policy_cache.cc @@ -10,7 +10,9 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/values.h" -#include "chrome/browser/policy/configuration_policy_pref_store.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/policy/browser_policy_connector.h" +#include "chrome/browser/policy/cloud_policy_provider.h" #include "chrome/browser/policy/policy_map.h" #include "chrome/browser/policy/proto/cloud_policy.pb.h" #include "chrome/browser/policy/proto/device_management_local.pb.h" @@ -26,7 +28,8 @@ void DecodePolicy(const em::CloudPolicySettings& policy, PolicyMap* mandatory, PolicyMap* recommended); UserPolicyCache::UserPolicyCache(const FilePath& backing_file_path) - : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), + first_load_complete_(false) { disk_cache_ = new UserPolicyDiskCache(weak_ptr_factory_.GetWeakPtr(), backing_file_path); } @@ -67,8 +70,13 @@ void UserPolicyCache::SetUnmanaged() { disk_cache_->Store(cached_policy); } +bool UserPolicyCache::IsReady() { + return initialization_complete() || first_load_complete_; +} + void UserPolicyCache::OnDiskCacheLoaded( const em::CachedCloudPolicyResponse& cached_response) { + first_load_complete_ = true; if (initialization_complete()) return; @@ -149,7 +157,8 @@ void UserPolicyCache::MaybeDecodeOldstylePolicy( // Hack: Let one of the providers do the transformation from DictionaryValue // to PolicyMap, since they have the required code anyway. PolicyMapProxy map_proxy(mandatory); - GetManagedPolicyProvider()->ApplyPolicyValueTree(&result, &map_proxy); + g_browser_process->browser_policy_connector()->GetManagedCloudProvider()-> + ApplyPolicyValueTree(&result, &map_proxy); } Value* UserPolicyCache::DecodeIntegerValue( diff --git a/chrome/browser/policy/user_policy_cache.h b/chrome/browser/policy/user_policy_cache.h index 307530c..0a1d725 100644 --- a/chrome/browser/policy/user_policy_cache.h +++ b/chrome/browser/policy/user_policy_cache.h @@ -37,6 +37,7 @@ class UserPolicyCache : public CloudPolicyCacheBase, virtual void Load() OVERRIDE; virtual void SetPolicy(const em::PolicyFetchResponse& policy) OVERRIDE; virtual void SetUnmanaged() OVERRIDE; + virtual bool IsReady() OVERRIDE; private: class DiskCache; @@ -73,6 +74,10 @@ class UserPolicyCache : public CloudPolicyCacheBase, // Used for constructing the weak ptr passed to |disk_cache_|. base::WeakPtrFactory<UserPolicyDiskCache::Delegate> weak_ptr_factory_; + // Starts as false, set to true when the first request for policies from + // disk is returned. + bool first_load_complete_; + DISALLOW_COPY_AND_ASSIGN(UserPolicyCache); }; diff --git a/chrome/browser/policy/user_policy_cache_unittest.cc b/chrome/browser/policy/user_policy_cache_unittest.cc index 7f327ea..426646a 100644 --- a/chrome/browser/policy/user_policy_cache_unittest.cc +++ b/chrome/browser/policy/user_policy_cache_unittest.cc @@ -20,6 +20,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::_; + namespace policy { // Decodes a CloudPolicySettings object into two maps with mandatory and @@ -32,13 +34,13 @@ void DecodePolicy(const em::CloudPolicySettings& policy, Value* DecodeIntegerValue(google::protobuf::int64 value); ListValue* DecodeStringList(const em::StringList& string_list); -class MockConfigurationPolicyProviderObserver - : public ConfigurationPolicyProvider::Observer { +class MockCloudPolicyCacheBaseObserver + : public CloudPolicyCacheBase::Observer { public: - MockConfigurationPolicyProviderObserver() {} - virtual ~MockConfigurationPolicyProviderObserver() {} - MOCK_METHOD0(OnUpdatePolicy, void()); - void OnProviderGoingAway() {} + MockCloudPolicyCacheBaseObserver() {} + virtual ~MockCloudPolicyCacheBaseObserver() {} + MOCK_METHOD1(OnCacheUpdate, void(CloudPolicyCacheBase*)); + void OnCacheGoingAway(CloudPolicyCacheBase*) {} }; // Tests the device management policy cache. @@ -103,14 +105,16 @@ class UserPolicyCacheTest : public testing::Test { em::PolicyFetchResponse* policy_response, bool expect_changed_policy) { scoped_ptr<em::PolicyFetchResponse> policy(policy_response); - ConfigurationPolicyObserverRegistrar registrar; - registrar.Init(cache->GetManagedPolicyProvider(), &observer); + cache->AddObserver(&observer); + if (expect_changed_policy) - EXPECT_CALL(observer, OnUpdatePolicy()).Times(1); + EXPECT_CALL(observer, OnCacheUpdate(_)).Times(1); else - EXPECT_CALL(observer, OnUpdatePolicy()).Times(0); + EXPECT_CALL(observer, OnCacheUpdate(_)).Times(0); cache->SetPolicy(*policy); testing::Mock::VerifyAndClearExpectations(&observer); + + cache->RemoveObserver(&observer); } FilePath test_file() { @@ -126,7 +130,7 @@ class UserPolicyCacheTest : public testing::Test { } MessageLoop loop_; - MockConfigurationPolicyProviderObserver observer; + MockCloudPolicyCacheBaseObserver observer; private: ScopedTempDir temp_dir_; diff --git a/chrome/browser/policy/user_policy_identity_strategy.cc b/chrome/browser/policy/user_policy_identity_strategy.cc index e599101..b0a20ff 100644 --- a/chrome/browser/policy/user_policy_identity_strategy.cc +++ b/chrome/browser/policy/user_policy_identity_strategy.cc @@ -4,47 +4,21 @@ #include "chrome/browser/policy/user_policy_identity_strategy.h" -#include "chrome/browser/browser_signin.h" -#include "chrome/browser/net/gaia/token_service.h" #include "chrome/browser/policy/proto/device_management_backend.pb.h" #include "chrome/browser/policy/proto/device_management_constants.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/common/guid.h" -#include "chrome/common/net/gaia/gaia_constants.h" -#include "content/browser/browser_thread.h" -#include "content/common/notification_details.h" -#include "content/common/notification_service.h" -#include "content/common/notification_source.h" - -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/login/user_manager.h" -#endif namespace policy { namespace em = enterprise_management; UserPolicyIdentityStrategy::UserPolicyIdentityStrategy( - Profile* profile, + const std::string& user_name, const FilePath& cache_file) - : profile_(profile), + : cache_loaded_(false), + user_name_(user_name), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { cache_ = new UserPolicyTokenCache(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 } UserPolicyIdentityStrategy::~UserPolicyIdentityStrategy() {} @@ -80,9 +54,8 @@ std::string UserPolicyIdentityStrategy::GetPolicyType() { bool UserPolicyIdentityStrategy::GetCredentials(std::string* username, std::string* auth_token) { - *username = GetCurrentUser(); - *auth_token = profile_->GetTokenService()->GetTokenForService( - GaiaConstants::kDeviceManagementService); + *username = user_name_; + *auth_token = auth_token_; return !username->empty() && !auth_token->empty() && !device_id_.empty(); } @@ -95,30 +68,32 @@ void UserPolicyIdentityStrategy::OnDeviceTokenAvailable( 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)) { + if (!user_name_.empty() && !auth_token_.empty() && cache_loaded_) { // For user tokens, there is no actual identifier. We generate a random // identifier instead each time we ask for the token. + // This shouldn't be done before the cache is loaded, because there may + // already be a device id and matching device token stored there. device_id_ = guid::GenerateGUID(); NotifyAuthChanged(); } } +void UserPolicyIdentityStrategy::SetAuthToken(const std::string& auth_token) { + auth_token_ = auth_token; + + // Request a new device management server token, but only in case we + // don't already have it. + if (device_token_.empty()) + CheckAndTriggerFetch(); +} + void UserPolicyIdentityStrategy::OnTokenCacheLoaded( const std::string& token, const std::string& device_id) { + if (cache_loaded_) + return; + cache_loaded_ = true; if (!token.empty() && !device_id.empty()) { device_token_ = token; device_id_ = device_id; @@ -128,32 +103,5 @@ void UserPolicyIdentityStrategy::OnTokenCacheLoaded( } } -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) - if (device_token_.empty()) { - // Request a new device management server token, but only in case we - // don't already have it. - 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 index c90011e..05b9e8a 100644 --- a/chrome/browser/policy/user_policy_identity_strategy.h +++ b/chrome/browser/policy/user_policy_identity_strategy.h @@ -14,28 +14,26 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/policy/cloud_policy_identity_strategy.h" #include "chrome/browser/policy/user_policy_token_cache.h" -#include "content/common/notification_observer.h" -#include "content/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. +// user corresponding to given credentials. class UserPolicyIdentityStrategy : public CloudPolicyIdentityStrategy, - public NotificationObserver, public UserPolicyTokenCache::Delegate { public: - UserPolicyIdentityStrategy(Profile* profile, + UserPolicyIdentityStrategy(const std::string& user_name, const FilePath& token_cache_file); virtual ~UserPolicyIdentityStrategy(); // Start loading the token cache. void LoadTokenCache(); + // Set a newly arriving auth_token and maybe trigger a fetch. + void SetAuthToken(const std::string& auth_token); + // CloudPolicyIdentityStrategy implementation: virtual std::string GetDeviceToken() OVERRIDE; virtual std::string GetDeviceID() OVERRIDE; @@ -59,25 +57,25 @@ class UserPolicyIdentityStrategy : public CloudPolicyIdentityStrategy, virtual void OnTokenCacheLoaded(const std::string& token, const std::string& device_id) OVERRIDE; - // NotificationObserver method overrides: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) OVERRIDE; - - // The profile this provider is associated with. - Profile* profile_; - // Keeps the on-disk copy of the token. scoped_refptr<UserPolicyTokenCache> cache_; + // false until cache_ reports being loaded for the first time, true + // afterwards. + bool cache_loaded_; + // 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_; + // Current auth token. Empty if not available. + std::string auth_token_; + + // Current user name. Empty if not available. This is set on creation and not + // changed afterwards. + std::string user_name_; // Allows to construct weak ptrs. base::WeakPtrFactory<UserPolicyTokenCache::Delegate> weak_ptr_factory_; |