Wire up component cloud policy to device local accounts.

Note: this is a reland of https://codereview.chromium.org/341043005 which was
reverted due to memory leaks in tests. Those leaks were fixed in
https://codereview.chromium.org/348713004.

This enables policy-for-extensions running in Public Sessions, and for
extensions running as Kiosk Apps too.

TBR=bartfab@chromium.org
BUG=224596

Review URL: https://codereview.chromium.org/335113008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278734 0039d316-1c4b-4281-b951-d872f2087c98
parent 0338bc66
...@@ -65,6 +65,9 @@ const char* kPublicSessionWhitelist[] = { ...@@ -65,6 +65,9 @@ const char* kPublicSessionWhitelist[] = {
"dhmdaeekeihmajjnmichlhiffffdbpde", // Store.app demo "dhmdaeekeihmajjnmichlhiffffdbpde", // Store.app demo
"jeabmjjifhfcejonjjhccaeigpnnjaak", // TweetDeck demo "jeabmjjifhfcejonjjhccaeigpnnjaak", // TweetDeck demo
"pbdihpaifchmclcmkfdgffnnpfbobefh", // YouTube demo "pbdihpaifchmclcmkfdgffnnpfbobefh", // YouTube demo
// Testing extensions:
"ongnjlefhnoajpbodoldndkbkdgfomlp", // Show Managed Storage
}; };
} // namespace } // namespace
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/location.h" #include "base/location.h"
...@@ -33,7 +32,6 @@ ...@@ -33,7 +32,6 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_path_override.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
...@@ -311,15 +309,6 @@ class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest, ...@@ -311,15 +309,6 @@ class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
PolicyBuilder::kFakeDeviceId); PolicyBuilder::kFakeDeviceId);
ASSERT_TRUE(test_server_.Start()); ASSERT_TRUE(test_server_.Start());
ASSERT_TRUE(extension_cache_root_dir_.CreateUniqueTempDir());
extension_cache_root_dir_override_.reset(new base::ScopedPathOverride(
chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
extension_cache_root_dir_.path()));
ASSERT_TRUE(external_data_cache_dir_.CreateUniqueTempDir());
external_data_cache_dir_override_.reset(new base::ScopedPathOverride(
chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA,
external_data_cache_dir_.path()));
BrowserList::AddObserver(this); BrowserList::AddObserver(this);
DevicePolicyCrosBrowserTest::SetUp(); DevicePolicyCrosBrowserTest::SetUp();
...@@ -433,8 +422,11 @@ class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest, ...@@ -433,8 +422,11 @@ class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
} }
base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) { base::FilePath GetCacheDirectoryForAccountID(const std::string& account_id) {
return extension_cache_root_dir_.path() base::FilePath extension_cache_root_dir;
.Append(base::HexEncode(account_id.c_str(), account_id.size())); PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
&extension_cache_root_dir);
return extension_cache_root_dir.Append(
base::HexEncode(account_id.c_str(), account_id.size()));
} }
base::FilePath GetCacheCRXFile(const std::string& account_id, base::FilePath GetCacheCRXFile(const std::string& account_id,
...@@ -459,11 +451,6 @@ class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest, ...@@ -459,11 +451,6 @@ class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
LocalPolicyTestServer test_server_; LocalPolicyTestServer test_server_;
private: private:
base::ScopedTempDir extension_cache_root_dir_;
base::ScopedTempDir external_data_cache_dir_;
scoped_ptr<base::ScopedPathOverride> extension_cache_root_dir_override_;
scoped_ptr<base::ScopedPathOverride> external_data_cache_dir_override_;
DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest); DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/chromeos/policy/device_local_account_policy_provider.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_provider.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_external_data_manager.h" #include "chrome/browser/chromeos/policy/device_local_account_external_data_manager.h"
...@@ -14,6 +15,9 @@ ...@@ -14,6 +15,9 @@
#include "components/policy/core/common/policy_bundle.h" #include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h" #include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_switches.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context_getter.h"
#include "policy/policy_constants.h" #include "policy/policy_constants.h"
namespace policy { namespace policy {
...@@ -94,10 +98,19 @@ DeviceLocalAccountPolicyProvider::Create( ...@@ -94,10 +98,19 @@ DeviceLocalAccountPolicyProvider::Create(
return provider.Pass(); return provider.Pass();
} }
void DeviceLocalAccountPolicyProvider::Init(SchemaRegistry* schema_registry) {
ConfigurationPolicyProvider::Init(schema_registry);
MaybeCreateComponentPolicyService();
}
bool DeviceLocalAccountPolicyProvider::IsInitializationComplete( bool DeviceLocalAccountPolicyProvider::IsInitializationComplete(
PolicyDomain domain) const { PolicyDomain domain) const {
if (domain == POLICY_DOMAIN_CHROME) if (domain == POLICY_DOMAIN_CHROME)
return store_initialized_; return store_initialized_;
if (ComponentCloudPolicyService::SupportsDomain(domain) &&
component_policy_service_) {
return component_policy_service_->is_initialized();
}
return true; return true;
} }
...@@ -113,13 +126,34 @@ void DeviceLocalAccountPolicyProvider::RefreshPolicies() { ...@@ -113,13 +126,34 @@ void DeviceLocalAccountPolicyProvider::RefreshPolicies() {
} }
} }
void DeviceLocalAccountPolicyProvider::Shutdown() {
component_policy_service_.reset();
ConfigurationPolicyProvider::Shutdown();
}
void DeviceLocalAccountPolicyProvider::OnPolicyUpdated( void DeviceLocalAccountPolicyProvider::OnPolicyUpdated(
const std::string& user_id) { const std::string& user_id) {
if (user_id == user_id_) if (user_id == user_id_) {
MaybeCreateComponentPolicyService();
UpdateFromBroker(); UpdateFromBroker();
}
} }
void DeviceLocalAccountPolicyProvider::OnDeviceLocalAccountsChanged() { void DeviceLocalAccountPolicyProvider::OnDeviceLocalAccountsChanged() {
MaybeCreateComponentPolicyService();
UpdateFromBroker();
}
void DeviceLocalAccountPolicyProvider::OnBrokerShutdown(
DeviceLocalAccountPolicyBroker* broker) {
if (broker->user_id() == user_id_) {
// The |component_policy_service_| relies on the broker's CloudPolicyCore,
// so destroy it if the broker is going away.
component_policy_service_.reset();
}
}
void DeviceLocalAccountPolicyProvider::OnComponentCloudPolicyUpdated() {
UpdateFromBroker(); UpdateFromBroker();
} }
...@@ -153,6 +187,9 @@ void DeviceLocalAccountPolicyProvider::UpdateFromBroker() { ...@@ -153,6 +187,9 @@ void DeviceLocalAccountPolicyProvider::UpdateFromBroker() {
bundle->CopyFrom(policies()); bundle->CopyFrom(policies());
} }
if (component_policy_service_)
bundle->MergeFrom(component_policy_service_->policy());
// Apply overrides. // Apply overrides.
if (chrome_policy_overrides_) { if (chrome_policy_overrides_) {
PolicyMap& chrome_policy = PolicyMap& chrome_policy =
...@@ -169,4 +206,35 @@ void DeviceLocalAccountPolicyProvider::UpdateFromBroker() { ...@@ -169,4 +206,35 @@ void DeviceLocalAccountPolicyProvider::UpdateFromBroker() {
UpdatePolicy(bundle.Pass()); UpdatePolicy(bundle.Pass());
} }
void DeviceLocalAccountPolicyProvider::MaybeCreateComponentPolicyService() {
if (component_policy_service_)
return; // Already started.
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableComponentCloudPolicy)) {
// Disabled via the command line.
return;
}
DeviceLocalAccountPolicyBroker* broker = GetBroker();
if (!broker || !schema_registry())
return; // Missing broker or not initialized yet.
scoped_ptr<ResourceCache> resource_cache(
new ResourceCache(broker->GetComponentPolicyCachePath(),
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::FILE)));
component_policy_service_.reset(new ComponentCloudPolicyService(
this,
schema_registry(),
broker->core(),
resource_cache.Pass(),
service_->request_context(),
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::FILE),
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO)));
}
} // namespace policy } // namespace policy
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/policy/device_local_account_external_data_manager.h" #include "chrome/browser/chromeos/policy/device_local_account_external_data_manager.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "components/policy/core/common/cloud/component_cloud_policy_service.h"
#include "components/policy/core/common/cloud/resource_cache.h"
#include "components/policy/core/common/configuration_policy_provider.h" #include "components/policy/core/common/configuration_policy_provider.h"
namespace policy { namespace policy {
...@@ -27,7 +29,8 @@ class PolicyMap; ...@@ -27,7 +29,8 @@ class PolicyMap;
// and RefreshPolicies becomes a no-op. // and RefreshPolicies becomes a no-op.
class DeviceLocalAccountPolicyProvider class DeviceLocalAccountPolicyProvider
: public ConfigurationPolicyProvider, : public ConfigurationPolicyProvider,
public DeviceLocalAccountPolicyService::Observer { public DeviceLocalAccountPolicyService::Observer,
public ComponentCloudPolicyService::Delegate {
public: public:
DeviceLocalAccountPolicyProvider( DeviceLocalAccountPolicyProvider(
const std::string& user_id, const std::string& user_id,
...@@ -43,12 +46,19 @@ class DeviceLocalAccountPolicyProvider ...@@ -43,12 +46,19 @@ class DeviceLocalAccountPolicyProvider
DeviceLocalAccountPolicyService* service); DeviceLocalAccountPolicyService* service);
// ConfigurationPolicyProvider: // ConfigurationPolicyProvider:
virtual void Init(SchemaRegistry* registry) OVERRIDE;
virtual bool IsInitializationComplete(PolicyDomain domain) const OVERRIDE; virtual bool IsInitializationComplete(PolicyDomain domain) const OVERRIDE;
virtual void RefreshPolicies() OVERRIDE; virtual void RefreshPolicies() OVERRIDE;
virtual void Shutdown() OVERRIDE;
// DeviceLocalAccountPolicyService::Observer: // DeviceLocalAccountPolicyService::Observer:
virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE;
virtual void OnDeviceLocalAccountsChanged() OVERRIDE; virtual void OnDeviceLocalAccountsChanged() OVERRIDE;
virtual void OnBrokerShutdown(
DeviceLocalAccountPolicyBroker* broker) OVERRIDE;
// ComponentCloudPolicyService::Delegate:
virtual void OnComponentCloudPolicyUpdated() OVERRIDE;
private: private:
// Returns the broker for |user_id_| or NULL if not available. // Returns the broker for |user_id_| or NULL if not available.
...@@ -62,6 +72,10 @@ class DeviceLocalAccountPolicyProvider ...@@ -62,6 +72,10 @@ class DeviceLocalAccountPolicyProvider
// policy from the broker if available or keeping the current policy. // policy from the broker if available or keeping the current policy.
void UpdateFromBroker(); void UpdateFromBroker();
// Creates the |component_policy_service_| if it hasn't been created yet
// and all the dependencies are in place.
void MaybeCreateComponentPolicyService();
const std::string user_id_; const std::string user_id_;
scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager_; scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager_;
...@@ -75,6 +89,8 @@ class DeviceLocalAccountPolicyProvider ...@@ -75,6 +89,8 @@ class DeviceLocalAccountPolicyProvider
bool store_initialized_; bool store_initialized_;
bool waiting_for_policy_refresh_; bool waiting_for_policy_refresh_;
scoped_ptr<ComponentCloudPolicyService> component_policy_service_;
base::WeakPtrFactory<DeviceLocalAccountPolicyProvider> weak_factory_; base::WeakPtrFactory<DeviceLocalAccountPolicyProvider> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyProvider); DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyProvider);
......
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/files/file_enumerator.h" #include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account.h"
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
#include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/cloud/device_management_service.h"
#include "components/policy/core/common/cloud/system_policy_request_context.h" #include "components/policy/core/common/cloud/system_policy_request_context.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
#include "policy/policy_constants.h" #include "policy/policy_constants.h"
#include "policy/proto/device_management_backend.pb.h" #include "policy/proto/device_management_backend.pb.h"
...@@ -72,30 +73,27 @@ scoped_ptr<CloudPolicyClient> CreateClient( ...@@ -72,30 +73,27 @@ scoped_ptr<CloudPolicyClient> CreateClient(
} }
// Get the subdirectory of the cache directory in which force-installed // Get the subdirectory of the cache directory in which force-installed
// extensions are cached for |account_id|. // extensions are cached for |account_id|. This is also used for the
std::string GetCacheSubdirectoryForAccountID(const std::string& account_id) { // component policy cache.
std::string EncodeAccountId(const std::string& account_id) {
return base::HexEncode(account_id.c_str(), account_id.size()); return base::HexEncode(account_id.c_str(), account_id.size());
} }
// Cleans up the cache directory by removing subdirectories that are not found // Cleans up the cache directory by removing subdirectories that are not found
// in |subdirectories_to_keep|. Only caches whose cache directory is found in // in |subdirectories_to_keep|. Only caches whose cache directory is found in
// |subdirectories_to_keep| may be running while the clean-up is in progress. // |subdirectories_to_keep| may be running while the clean-up is in progress.
void DeleteOrphanedExtensionCaches( void DeleteOrphanedCaches(
const base::FilePath& cache_root_dir,
const std::set<std::string>& subdirectories_to_keep) { const std::set<std::string>& subdirectories_to_keep) {
base::FilePath cache_root_dir;
CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
&cache_root_dir));
base::FileEnumerator enumerator(cache_root_dir, base::FileEnumerator enumerator(cache_root_dir,
false, false,
base::FileEnumerator::DIRECTORIES); base::FileEnumerator::DIRECTORIES);
for (base::FilePath path = enumerator.Next(); !path.empty(); for (base::FilePath path = enumerator.Next(); !path.empty();
path = enumerator.Next()) { path = enumerator.Next()) {
const std::string subdirectory(path.BaseName().MaybeAsASCII()); const std::string subdirectory(path.BaseName().MaybeAsASCII());
if (subdirectories_to_keep.find(subdirectory) == if (!ContainsKey(subdirectories_to_keep, subdirectory))
subdirectories_to_keep.end()) {
base::DeleteFile(path, true); base::DeleteFile(path, true);
} }
}
} }
// Removes the subdirectory belonging to |account_id_to_delete| from the cache // Removes the subdirectory belonging to |account_id_to_delete| from the cache
...@@ -105,8 +103,8 @@ void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) { ...@@ -105,8 +103,8 @@ void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) {
base::FilePath cache_root_dir; base::FilePath cache_root_dir;
CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
&cache_root_dir)); &cache_root_dir));
const base::FilePath path = cache_root_dir const base::FilePath path =
.Append(GetCacheSubdirectoryForAccountID(account_id_to_delete)); cache_root_dir.Append(EncodeAccountId(account_id_to_delete));
if (base::DirectoryExists(path)) if (base::DirectoryExists(path))
base::DeleteFile(path, true); base::DeleteFile(path, true);
} }
...@@ -115,11 +113,13 @@ void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) { ...@@ -115,11 +113,13 @@ void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) {
DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker( DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
const DeviceLocalAccount& account, const DeviceLocalAccount& account,
const base::FilePath& component_policy_cache_path,
scoped_ptr<DeviceLocalAccountPolicyStore> store, scoped_ptr<DeviceLocalAccountPolicyStore> store,
scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager, scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager,
const scoped_refptr<base::SequencedTaskRunner>& task_runner) const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: account_id_(account.account_id), : account_id_(account.account_id),
user_id_(account.user_id), user_id_(account.user_id),
component_policy_cache_path_(component_policy_cache_path),
store_(store.Pass()), store_(store.Pass()),
external_data_manager_(external_data_manager), external_data_manager_(external_data_manager),
core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType, core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
...@@ -130,9 +130,7 @@ DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker( ...@@ -130,9 +130,7 @@ DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
&cache_root_dir)); &cache_root_dir));
extension_loader_ = new chromeos::DeviceLocalAccountExternalPolicyLoader( extension_loader_ = new chromeos::DeviceLocalAccountExternalPolicyLoader(
store_.get(), store_.get(), cache_root_dir.Append(EncodeAccountId(account.account_id)));
cache_root_dir.Append(
GetCacheSubdirectoryForAccountID(account.account_id)));
} }
DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() { DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {
...@@ -182,6 +180,11 @@ std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const { ...@@ -182,6 +180,11 @@ std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
return display_name; return display_name;
} }
base::FilePath DeviceLocalAccountPolicyBroker::GetComponentPolicyCachePath()
const {
return component_policy_cache_path_;
}
DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService( DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
chromeos::SessionManagerClient* session_manager_client, chromeos::SessionManagerClient* session_manager_client,
chromeos::DeviceSettingsService* device_settings_service, chromeos::DeviceSettingsService* device_settings_service,
...@@ -207,6 +210,8 @@ DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService( ...@@ -207,6 +210,8 @@ DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
UpdateAccountListIfNonePending, UpdateAccountListIfNonePending,
base::Unretained(this)))), base::Unretained(this)))),
weak_factory_(this) { weak_factory_(this) {
CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_COMPONENT_POLICY,
&component_policy_cache_root_));
external_data_service_.reset(new DeviceLocalAccountExternalDataService( external_data_service_.reset(new DeviceLocalAccountExternalDataService(
this, this,
external_data_service_backend_task_runner, external_data_service_backend_task_runner,
...@@ -255,6 +260,11 @@ bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser( ...@@ -255,6 +260,11 @@ bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
return broker && broker->core()->store()->is_managed(); return broker && broker->core()->store()->is_managed();
} }
scoped_refptr<net::URLRequestContextGetter>
DeviceLocalAccountPolicyService::request_context() const {
return request_context_;
}
void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) { void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
observers_.AddObserver(observer); observers_.AddObserver(observer);
} }
...@@ -414,6 +424,7 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() { ...@@ -414,6 +424,7 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() {
store.get()); store.get());
broker.reset(new DeviceLocalAccountPolicyBroker( broker.reset(new DeviceLocalAccountPolicyBroker(
*it, *it,
component_policy_cache_root_.Append(EncodeAccountId(it->account_id)),
store.Pass(), store.Pass(),
external_data_manager, external_data_manager,
base::MessageLoopProxy::current())); base::MessageLoopProxy::current()));
...@@ -432,16 +443,7 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() { ...@@ -432,16 +443,7 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() {
policy_brokers_[it->user_id]->Initialize(); policy_brokers_[it->user_id]->Initialize();
} }
if (orphan_cache_deletion_state_ == NOT_STARTED) { subdirectories_to_keep.insert(EncodeAccountId(it->account_id));
subdirectories_to_keep.insert(
GetCacheSubdirectoryForAccountID(it->account_id));
}
}
std::set<std::string> obsolete_account_ids;
for (PolicyBrokerMap::const_iterator it = old_policy_brokers.begin();
it != old_policy_brokers.end(); ++it) {
obsolete_account_ids.insert(it->second->account_id());
} }
if (orphan_cache_deletion_state_ == NOT_STARTED) { if (orphan_cache_deletion_state_ == NOT_STARTED) {
...@@ -453,11 +455,16 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() { ...@@ -453,11 +455,16 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() {
// orphaned cache directories not found in |subdirectories_to_keep| from the // orphaned cache directories not found in |subdirectories_to_keep| from the
// cache directory. // cache directory.
orphan_cache_deletion_state_ = IN_PROGRESS; orphan_cache_deletion_state_ = IN_PROGRESS;
base::FilePath cache_root_dir;
CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
&cache_root_dir));
extension_cache_task_runner_->PostTaskAndReply( extension_cache_task_runner_->PostTaskAndReply(
FROM_HERE, FROM_HERE,
base::Bind(&DeleteOrphanedExtensionCaches, subdirectories_to_keep), base::Bind(
base::Bind(&DeviceLocalAccountPolicyService:: &DeleteOrphanedCaches, cache_root_dir, subdirectories_to_keep),
OnOrphanedExtensionCachesDeleted, base::Bind(
&DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
// Start the extension caches for all brokers. These belong to accounts in // Start the extension caches for all brokers. These belong to accounts in
...@@ -476,6 +483,16 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() { ...@@ -476,6 +483,16 @@ void DeviceLocalAccountPolicyService::UpdateAccountList() {
} }
} }
// Purge the component policy caches of any accounts that have been removed.
// Do this only after any obsolete brokers have been destroyed.
// TODO(joaodasilva): for now this must be posted to the FILE thread,
// to avoid racing with the ComponentCloudPolicyStore. Use a task runner
// once that class supports another background thread too.
content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
base::Bind(&DeleteOrphanedCaches,
component_policy_cache_root_,
subdirectories_to_keep));
FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged()); FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
} }
...@@ -492,6 +509,7 @@ void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) { ...@@ -492,6 +509,7 @@ void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr(),
it->second->account_id())); it->second->account_id()));
} }
FOR_EACH_OBSERVER(Observer, observers_, OnBrokerShutdown(it->second));
delete it->second; delete it->second;
} }
map->clear(); map->clear();
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
...@@ -48,6 +49,7 @@ class DeviceLocalAccountPolicyBroker { ...@@ -48,6 +49,7 @@ class DeviceLocalAccountPolicyBroker {
// |task_runner| is the runner for policy refresh tasks. // |task_runner| is the runner for policy refresh tasks.
DeviceLocalAccountPolicyBroker( DeviceLocalAccountPolicyBroker(
const DeviceLocalAccount& account, const DeviceLocalAccount& account,
const base::FilePath& component_policy_cache_path,
scoped_ptr<DeviceLocalAccountPolicyStore> store, scoped_ptr<DeviceLocalAccountPolicyStore> store,
scoped_refptr<DeviceLocalAccountExternalDataManager> scoped_refptr<DeviceLocalAccountExternalDataManager>
external_data_manager, external_data_manager,
...@@ -86,9 +88,15 @@ class DeviceLocalAccountPolicyBroker { ...@@ -86,9 +88,15 @@ class DeviceLocalAccountPolicyBroker {
// empty string if the policy is not present. // empty string if the policy is not present.
std::string GetDisplayName() const; std::string GetDisplayName() const;
// Returns a directory where component policy for this account can be cached.
// The DeviceLocalAccountPolicyService takes care of cleaning up caches of
// accounts that have been removed.
base::FilePath GetComponentPolicyCachePath() const;
private: private:
const std::string account_id_; const std::string account_id_;
const std::string user_id_; const std::string user_id_;
const base::FilePath component_policy_cache_path_;
const scoped_ptr<DeviceLocalAccountPolicyStore> store_; const scoped_ptr<DeviceLocalAccountPolicyStore> store_;
scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager_; scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager_;
scoped_refptr<chromeos::DeviceLocalAccountExternalPolicyLoader> scoped_refptr<chromeos::DeviceLocalAccountExternalPolicyLoader>
...@@ -114,6 +122,9 @@ class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer { ...@@ -114,6 +122,9 @@ class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer {
// The list of accounts has been updated. // The list of accounts has been updated.
virtual void OnDeviceLocalAccountsChanged() = 0; virtual void OnDeviceLocalAccountsChanged() = 0;
// The given |broker| is about to be destroyed.
virtual void OnBrokerShutdown(DeviceLocalAccountPolicyBroker* broker) {}
}; };
DeviceLocalAccountPolicyService( DeviceLocalAccountPolicyService(
...@@ -142,6 +153,8 @@ class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer { ...@@ -142,6 +153,8 @@ class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer {
// |user_id|. // |user_id|.
bool IsPolicyAvailableForUser(const std::string& user_id); bool IsPolicyAvailableForUser(const std::string& user_id);
scoped_refptr<net::URLRequestContextGetter> request_context() const;
void AddObserver(Observer* observer); void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer); void RemoveObserver(Observer* observer);
...@@ -229,6 +242,10 @@ class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer { ...@@ -229,6 +242,10 @@ class DeviceLocalAccountPolicyService : public CloudPolicyStore::Observer {
const scoped_ptr<chromeos::CrosSettings::ObserverSubscription> const scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
local_accounts_subscription_; local_accounts_subscription_;
// Path to the directory that contains the cached policies for components
// for device local accounts.
base::FilePath component_policy_cache_root_;
base::WeakPtrFactory<DeviceLocalAccountPolicyService> weak_factory_; base::WeakPtrFactory<DeviceLocalAccountPolicyService> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyService); DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyService);
......
...@@ -443,6 +443,14 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -443,6 +443,14 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.server.UpdateStateKeys(token_info['device_token'], self.server.UpdateStateKeys(token_info['device_token'],
key_update_request.server_backed_state_key) key_update_request.server_backed_state_key)
# If this is a publicaccount request then get the username now and use it
# in every PolicyFetchResponse produced. This is required to validate
# policy for extensions in public accounts.
username = self.server.GetPolicies().get('policy_user', None)
for request in msg.policy_request.request:
if request.policy_type == 'google/chromeos/publicaccount':
username = request.settings_entity_id
response = dm.DeviceManagementResponse() response = dm.DeviceManagementResponse()
for request in msg.policy_request.request: for request in msg.policy_request.request:
if (request.policy_type in if (request.policy_type in
...@@ -456,7 +464,7 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -456,7 +464,7 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.ProcessCloudPolicy(request, token_info, fetch_response) self.ProcessCloudPolicy(request, token_info, fetch_response)
elif request.policy_type == 'google/chrome/extension': elif request.policy_type == 'google/chrome/extension':
self.ProcessCloudPolicyForExtensions( self.ProcessCloudPolicyForExtensions(
request, response.policy_response, token_info) request, response.policy_response, token_info, username)
else: else:
fetch_response.error_code = 400 fetch_response.error_code = 400
fetch_response.error_message = 'Invalid policy_type' fetch_response.error_message = 'Invalid policy_type'
...@@ -628,7 +636,8 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -628,7 +636,8 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.SetProtobufMessageField(policy_message, field_descriptor, value) self.SetProtobufMessageField(policy_message, field_descriptor, value)
settings.__getattribute__(field.name).CopyFrom(policy_message) settings.__getattribute__(field.name).CopyFrom(policy_message)
def ProcessCloudPolicyForExtensions(self, request, response, token_info): def ProcessCloudPolicyForExtensions(self, request, response, token_info,
username):
"""Handles a request for policy for extensions. """Handles a request for policy for extensions.
A request for policy for extensions is slightly different from the other A request for policy for extensions is slightly different from the other
...@@ -640,6 +649,7 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -640,6 +649,7 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
response: The DevicePolicyResponse message for the response. Multiple response: The DevicePolicyResponse message for the response. Multiple
PolicyFetchResponses will be appended to this message. PolicyFetchResponses will be appended to this message.
token_info: The token extracted from the request. token_info: The token extracted from the request.
username: The username for the response.
""" """
# Send one PolicyFetchResponse for each extension that has # Send one PolicyFetchResponse for each extension that has
# configuration data at the server. # configuration data at the server.
...@@ -649,13 +659,13 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -649,13 +659,13 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# type in the response. # type in the response.
request.settings_entity_id = settings_entity_id request.settings_entity_id = settings_entity_id
fetch_response = response.response.add() fetch_response = response.response.add()
self.ProcessCloudPolicy(request, token_info, fetch_response) self.ProcessCloudPolicy(request, token_info, fetch_response, username)
# Don't do key rotations for these messages. # Don't do key rotations for these messages.
fetch_response.ClearField('new_public_key') fetch_response.ClearField('new_public_key')
fetch_response.ClearField('new_public_key_signature') fetch_response.ClearField('new_public_key_signature')
fetch_response.ClearField('new_public_key_verification_signature') fetch_response.ClearField('new_public_key_verification_signature')
def ProcessCloudPolicy(self, msg, token_info, response): def ProcessCloudPolicy(self, msg, token_info, response, username=None):
"""Handles a cloud policy request. (New protocol for policy requests.) """Handles a cloud policy request. (New protocol for policy requests.)
Encodes the policy into protobuf representation, signs it and constructs Encodes the policy into protobuf representation, signs it and constructs
...@@ -666,6 +676,7 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -666,6 +676,7 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
token_info: The token extracted from the request. token_info: The token extracted from the request.
response: A PolicyFetchResponse message that should be filled with the response: A PolicyFetchResponse message that should be filled with the
response data. response data.
username: The username for the response. May be None.
""" """
if msg.machine_id: if msg.machine_id:
...@@ -746,7 +757,10 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -746,7 +757,10 @@ class PolicyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if signing_key: if signing_key:
policy_data.public_key_version = current_key_index + 1 policy_data.public_key_version = current_key_index + 1
if msg.policy_type == 'google/chromeos/publicaccount':
if username:
policy_data.username = username
elif msg.policy_type == 'google/chromeos/publicaccount':
policy_data.username = msg.settings_entity_id policy_data.username = msg.settings_entity_id
else: else:
# For regular user/device policy, there is no way for the testserver to # For regular user/device policy, there is no way for the testserver to
...@@ -960,7 +974,8 @@ class PolicyTestServer(testserver_base.BrokenPipeHandlerMixIn, ...@@ -960,7 +974,8 @@ class PolicyTestServer(testserver_base.BrokenPipeHandlerMixIn,
], ],
dm.DeviceRegisterRequest.DEVICE: [ dm.DeviceRegisterRequest.DEVICE: [
'google/chromeos/device', 'google/chromeos/device',
'google/chromeos/publicaccount' 'google/chromeos/publicaccount',
'google/chrome/extension'
], ],
dm.DeviceRegisterRequest.ANDROID_BROWSER: [ dm.DeviceRegisterRequest.ANDROID_BROWSER: [
'google/android/user' 'google/android/user'
......
...@@ -41,6 +41,9 @@ const base::FilePath::CharType kDeviceLocalAccountExtensionDir[] = ...@@ -41,6 +41,9 @@ const base::FilePath::CharType kDeviceLocalAccountExtensionDir[] =
const base::FilePath::CharType kDeviceLocalAccountExternalDataDir[] = const base::FilePath::CharType kDeviceLocalAccountExternalDataDir[] =
FILE_PATH_LITERAL("/var/cache/device_local_account_external_policy_data"); FILE_PATH_LITERAL("/var/cache/device_local_account_external_policy_data");
const base::FilePath::CharType kDeviceLocalAccountComponentPolicy[] =
FILE_PATH_LITERAL("/var/cache/device_local_account_component_policy");
bool PathProvider(int key, base::FilePath* result) { bool PathProvider(int key, base::FilePath* result) {
switch (key) { switch (key) {
case FILE_DEFAULT_APP_ORDER: case FILE_DEFAULT_APP_ORDER:
...@@ -67,6 +70,9 @@ bool PathProvider(int key, base::FilePath* result) { ...@@ -67,6 +70,9 @@ bool PathProvider(int key, base::FilePath* result) {
case DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA: case DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA:
*result = base::FilePath(kDeviceLocalAccountExternalDataDir); *result = base::FilePath(kDeviceLocalAccountExternalDataDir);
break; break;
case DIR_DEVICE_LOCAL_ACCOUNT_COMPONENT_POLICY:
*result = base::FilePath(kDeviceLocalAccountComponentPolicy);
break;
default: default:
return false; return false;
} }
...@@ -99,6 +105,15 @@ void RegisterStubPathOverrides(const base::FilePath& stubs_dir) { ...@@ -99,6 +105,15 @@ void RegisterStubPathOverrides(const base::FilePath& stubs_dir) {
parent.AppendASCII("stub_install_attributes.pb"), parent.AppendASCII("stub_install_attributes.pb"),
is_absolute, is_absolute,
create); create);
PathService::Override(
DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
parent.AppendASCII("stub_device_local_account_extensions"));
PathService::Override(
DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA,
parent.AppendASCII("stub_device_local_account_external_data"));
PathService::Override(
DIR_DEVICE_LOCAL_ACCOUNT_COMPONENT_POLICY,
parent.AppendASCII("stub_device_local_account_component_policy"));
} }
} // namespace chromeos } // namespace chromeos
...@@ -38,6 +38,11 @@ enum { ...@@ -38,6 +38,11 @@ enum {
DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA, // Directory where external data DIR_DEVICE_LOCAL_ACCOUNT_EXTERNAL_DATA, // Directory where external data
// referenced by policies is cached // referenced by policies is cached
// for device-local accounts. // for device-local accounts.
DIR_DEVICE_LOCAL_ACCOUNT_COMPONENT_POLICY, // Directory where policy for the
// components of device-local
// account is stored. Currently
// this is used for policy for
// extensions.
PATH_END PATH_END
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment