blob: 394c74ea40173da72126316e5ce4b1d873639550 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/chromeos/policy/app_pack_updater.h"
#include "chrome/browser/chromeos/policy/consumer_enrollment_handler.h"
#include "chrome/browser/chromeos/policy/consumer_management_service.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_invalidator.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "chrome/browser/chromeos/policy/device_network_configuration_updater.h"
#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
#include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/policy/device_management_service_configuration.h"
#include "chrome/common/pref_names.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/system_salt_getter.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/onc/onc_certificate_importer_impl.h"
#include "chromeos/settings/cros_settings_names.h"
#include "chromeos/settings/cros_settings_provider.h"
#include "chromeos/settings/timezone_settings.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
#include "components/policy/core/common/proxy_policy_provider.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "net/url_request/url_request_context_getter.h"
using content::BrowserThread;
namespace policy {
namespace {
// TODO(davidyu): Update the URL to the real one once it is ready.
// http://crbug.com/366491.
//
// The URL for the consumer device management server.
const char kDefaultConsumerDeviceManagementServerUrl[] =
"https://m.google.com/devicemanagement/data/api";
// Install attributes for tests.
EnterpriseInstallAttributes* g_testing_install_attributes = NULL;
// Helper that returns a new SequencedTaskRunner backed by the blocking pool.
// Each SequencedTaskRunner returned is independent from the others.
scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() {
base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
CHECK(pool);
return pool->GetSequencedTaskRunnerWithShutdownBehavior(
pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
}
std::string GetDeviceManagementServerUrlForConsumer() {
const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(
chromeos::switches::kConsumerDeviceManagementUrl)) {
return command_line->GetSwitchValueASCII(
chromeos::switches::kConsumerDeviceManagementUrl);
}
return kDefaultConsumerDeviceManagementServerUrl;
}
} // namespace
BrowserPolicyConnectorChromeOS::BrowserPolicyConnectorChromeOS()
: device_cloud_policy_manager_(NULL),
global_user_cloud_policy_provider_(NULL),
weak_ptr_factory_(this) {
if (g_testing_install_attributes) {
install_attributes_.reset(g_testing_install_attributes);
g_testing_install_attributes = NULL;
}
// SystemSaltGetter or DBusThreadManager may be uninitialized on unit tests.
// TODO(satorux): Remove SystemSaltGetter::IsInitialized() when it's ready
// (removing it now breaks tests). crbug.com/141016.
if (chromeos::SystemSaltGetter::IsInitialized() &&
chromeos::DBusThreadManager::IsInitialized()) {
state_keys_broker_.reset(new ServerBackedStateKeysBroker(
chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
base::MessageLoopProxy::current()));
chromeos::CryptohomeClient* cryptohome_client =
chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
if (!install_attributes_) {
install_attributes_.reset(
new EnterpriseInstallAttributes(cryptohome_client));
}
base::FilePath install_attrs_file;
CHECK(PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES,
&install_attrs_file));
install_attributes_->ReadCacheFile(install_attrs_file);
const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(
chromeos::switches::kEnableConsumerManagement)) {
consumer_management_service_.reset(
new ConsumerManagementService(
cryptohome_client,
chromeos::DeviceSettingsService::Get()));
}
scoped_ptr<DeviceCloudPolicyStoreChromeOS> device_cloud_policy_store(
new DeviceCloudPolicyStoreChromeOS(
chromeos::DeviceSettingsService::Get(),
install_attributes_.get(),
GetBackgroundTaskRunner()));
device_cloud_policy_manager_ =
new DeviceCloudPolicyManagerChromeOS(device_cloud_policy_store.Pass(),
base::MessageLoopProxy::current(),
state_keys_broker_.get());
AddPolicyProvider(
scoped_ptr<ConfigurationPolicyProvider>(device_cloud_policy_manager_));
}
global_user_cloud_policy_provider_ = new ProxyPolicyProvider();
AddPolicyProvider(scoped_ptr<ConfigurationPolicyProvider>(
global_user_cloud_policy_provider_));
}
BrowserPolicyConnectorChromeOS::~BrowserPolicyConnectorChromeOS() {}
void BrowserPolicyConnectorChromeOS::Init(
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> request_context) {
ChromeBrowserPolicyConnector::Init(local_state, request_context);
const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(chromeos::switches::kEnableConsumerManagement)) {
scoped_ptr<DeviceManagementService::Configuration> configuration(
new DeviceManagementServiceConfiguration(
GetDeviceManagementServerUrlForConsumer()));
consumer_device_management_service_.reset(
new DeviceManagementService(configuration.Pass()));
consumer_device_management_service_->ScheduleInitialization(
kServiceInitializationStartupDelay);
if (consumer_management_service_->GetStatus() ==
ConsumerManagementService::STATUS_ENROLLING ||
consumer_management_service_->HasPendingEnrollmentNotification()) {
consumer_enrollment_handler_.reset(
new ConsumerEnrollmentHandler(
consumer_management_service_.get(),
consumer_device_management_service_.get()));
}
}
if (device_cloud_policy_manager_) {
// Note: for now the |device_cloud_policy_manager_| is using the global
// schema registry. Eventually it will have its own registry, once device
// cloud policy for extensions is introduced. That means it'd have to be
// initialized from here instead of BrowserPolicyConnector::Init().
device_cloud_policy_manager_->Initialize(local_state);
device_cloud_policy_initializer_.reset(
new DeviceCloudPolicyInitializer(
local_state,
device_management_service(),
consumer_device_management_service_.get(),
GetBackgroundTaskRunner(),
install_attributes_.get(),
state_keys_broker_.get(),
device_cloud_policy_manager_->device_store(),
device_cloud_policy_manager_,
chromeos::DeviceSettingsService::Get(),
base::Bind(&BrowserPolicyConnectorChromeOS::
OnDeviceCloudPolicyManagerConnected,
base::Unretained(this))));
device_cloud_policy_initializer_->Init();
}
device_local_account_policy_service_.reset(
new DeviceLocalAccountPolicyService(
chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
chromeos::DeviceSettingsService::Get(),
chromeos::CrosSettings::Get(),
GetBackgroundTaskRunner(),
GetBackgroundTaskRunner(),
GetBackgroundTaskRunner(),
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO),
request_context));
device_local_account_policy_service_->Connect(device_management_service());
device_cloud_policy_invalidator_.reset(new DeviceCloudPolicyInvalidator);
// request_context is NULL in unit tests.
if (request_context.get() && install_attributes_) {
app_pack_updater_.reset(
new AppPackUpdater(request_context.get(), install_attributes_.get()));
}
SetTimezoneIfPolicyAvailable();
network_configuration_updater_ =
DeviceNetworkConfigurationUpdater::CreateForDevicePolicy(
GetPolicyService(),
chromeos::NetworkHandler::Get()
->managed_network_configuration_handler(),
chromeos::NetworkHandler::Get()->network_device_handler(),
chromeos::CrosSettings::Get());
}
void BrowserPolicyConnectorChromeOS::PreShutdown() {
// Let the |device_cloud_policy_invalidator_| unregister itself as an
// observer of per-Profile InvalidationServices and the device-global
// invalidation::TiclInvalidationService it may have created as an observer of
// the DeviceOAuth2TokenService that is destroyed before Shutdown() is called.
device_cloud_policy_invalidator_.reset();
// The |consumer_enrollment_handler_| may be observing a
// ProfileOAuth2TokenService and needs to be destroyed before the token
// service.
consumer_enrollment_handler_.reset();
}
void BrowserPolicyConnectorChromeOS::Shutdown() {
// Verify that PreShutdown() has been called first.
DCHECK(!device_cloud_policy_invalidator_);
DCHECK(!consumer_enrollment_handler_);
// The AppPackUpdater may be observing the |device_cloud_policy_manager_|.
// Delete it first.
app_pack_updater_.reset();
network_configuration_updater_.reset();
if (device_local_account_policy_service_)
device_local_account_policy_service_->Shutdown();
if (device_cloud_policy_initializer_)
device_cloud_policy_initializer_->Shutdown();
ChromeBrowserPolicyConnector::Shutdown();
}
bool BrowserPolicyConnectorChromeOS::IsEnterpriseManaged() {
return install_attributes_ && install_attributes_->IsEnterpriseDevice();
}
std::string BrowserPolicyConnectorChromeOS::GetEnterpriseDomain() {
return install_attributes_ ? install_attributes_->GetDomain() : std::string();
}
DeviceMode BrowserPolicyConnectorChromeOS::GetDeviceMode() {
return install_attributes_ ? install_attributes_->GetMode()
: DEVICE_MODE_NOT_SET;
}
UserAffiliation BrowserPolicyConnectorChromeOS::GetUserAffiliation(
const std::string& user_name) {
// An empty username means incognito user in case of ChromiumOS and
// no logged-in user in case of Chromium (SigninService). Many tests use
// nonsense email addresses (e.g. 'test') so treat those as non-enterprise
// users.
if (user_name.empty() || user_name.find('@') == std::string::npos)
return USER_AFFILIATION_NONE;
if (install_attributes_ &&
(gaia::ExtractDomainName(gaia::CanonicalizeEmail(user_name)) ==
install_attributes_->GetDomain() ||
policy::IsDeviceLocalAccountUser(user_name, NULL))) {
return USER_AFFILIATION_MANAGED;
}
return USER_AFFILIATION_NONE;
}
AppPackUpdater* BrowserPolicyConnectorChromeOS::GetAppPackUpdater() {
return app_pack_updater_.get();
}
void BrowserPolicyConnectorChromeOS::SetUserPolicyDelegate(
ConfigurationPolicyProvider* user_policy_provider) {
global_user_cloud_policy_provider_->SetDelegate(user_policy_provider);
}
void BrowserPolicyConnectorChromeOS::SetDeviceCloudPolicyInitializerForTesting(
scoped_ptr<DeviceCloudPolicyInitializer> initializer) {
device_cloud_policy_initializer_ = initializer.Pass();
}
void BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
EnterpriseInstallAttributes* attributes) {
DCHECK(!g_testing_install_attributes);
g_testing_install_attributes = attributes;
}
void BrowserPolicyConnectorChromeOS::RemoveInstallAttributesForTesting() {
if (g_testing_install_attributes) {
delete g_testing_install_attributes;
g_testing_install_attributes = NULL;
}
}
// static
void BrowserPolicyConnectorChromeOS::RegisterPrefs(
PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(
prefs::kDevicePolicyRefreshRate,
CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
}
void BrowserPolicyConnectorChromeOS::SetTimezoneIfPolicyAvailable() {
typedef chromeos::CrosSettingsProvider Provider;
Provider::TrustedStatus result =
chromeos::CrosSettings::Get()->PrepareTrustedValues(base::Bind(
&BrowserPolicyConnectorChromeOS::SetTimezoneIfPolicyAvailable,
weak_ptr_factory_.GetWeakPtr()));
if (result != Provider::TRUSTED)
return;
std::string timezone;
if (chromeos::CrosSettings::Get()->GetString(chromeos::kSystemTimezonePolicy,
&timezone) &&
!timezone.empty()) {
chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
base::UTF8ToUTF16(timezone));
}
}
void BrowserPolicyConnectorChromeOS::OnDeviceCloudPolicyManagerConnected() {
// This function is invoked by DCPInitializer, so we should release the
// initializer after this function returns.
if (device_cloud_policy_initializer_) {
device_cloud_policy_initializer_->Shutdown();
base::MessageLoop::current()->DeleteSoon(
FROM_HERE, device_cloud_policy_initializer_.release());
}
}
} // namespace policy