1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/policy/browser_policy_connector.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/message_loop/message_loop_proxy.h"
17 #include "base/path_service.h"
18 #include "base/prefs/pref_registry_simple.h"
19 #include "base/prefs/pref_service.h"
20 #include "base/sequenced_task_runner.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/sys_string_conversions.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/sys_info.h"
26 #include "base/threading/sequenced_worker_pool.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/policy/configuration_policy_handler_list_factory.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/chrome_version_info.h"
32 #include "chrome/common/pref_names.h"
33 #include "components/policy/core/common/async_policy_provider.h"
34 #include "components/policy/core/common/cloud/cloud_policy_client.h"
35 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
36 #include "components/policy/core/common/cloud/cloud_policy_service.h"
37 #include "components/policy/core/common/cloud/device_management_service.h"
38 #include "components/policy/core/common/configuration_policy_provider.h"
39 #include "components/policy/core/common/policy_namespace.h"
40 #include "components/policy/core/common/policy_pref_names.h"
41 #include "components/policy/core/common/policy_service_impl.h"
42 #include "components/policy/core/common/policy_statistics_collector.h"
43 #include "components/policy/core/common/schema.h"
44 #include "content/public/browser/browser_thread.h"
45 #include "content/public/common/content_client.h"
46 #include "google_apis/gaia/gaia_auth_util.h"
47 #include "google_apis/gaia/gaia_constants.h"
48 #include "grit/generated_resources.h"
49 #include "net/url_request/url_request_context_getter.h"
50 #include "policy/policy_constants.h"
51 #include "third_party/icu/source/i18n/unicode/regex.h"
55 #include "components/policy/core/common/policy_loader_win.h"
56 #elif defined(OS_MACOSX) && !defined(OS_IOS)
57 #include <CoreFoundation/CoreFoundation.h>
58 #include "components/policy/core/common/policy_loader_mac.h"
59 #include "components/policy/core/common/preferences_mac.h"
60 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
61 #include "components/policy/core/common/config_dir_policy_loader.h"
64 #if defined(OS_CHROMEOS)
65 #include "chrome/browser/chromeos/login/user_manager.h"
66 #include "chrome/browser/chromeos/policy/app_pack_updater.h"
67 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
68 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
69 #include "chrome/browser/chromeos/policy/device_local_account.h"
70 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
71 #include "chrome/browser/chromeos/policy/device_network_configuration_updater.h"
72 #include "chrome/browser/chromeos/policy/device_status_collector.h"
73 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
74 #include "chrome/browser/chromeos/settings/cros_settings.h"
75 #include "chrome/browser/chromeos/settings/device_settings_service.h"
76 #include "chromeos/chromeos_paths.h"
77 #include "chromeos/chromeos_switches.h"
78 #include "chromeos/cryptohome/system_salt_getter.h"
79 #include "chromeos/dbus/cryptohome_client.h"
80 #include "chromeos/dbus/dbus_thread_manager.h"
81 #include "chromeos/network/network_handler.h"
82 #include "chromeos/network/onc/onc_certificate_importer_impl.h"
83 #include "chromeos/settings/cros_settings_provider.h"
84 #include "chromeos/settings/timezone_settings.h"
85 #include "chromeos/system/statistics_provider.h"
88 using content::BrowserThread
;
94 // The following constants define delays applied before the initial policy fetch
95 // on startup. (So that displaying Chrome's GUI does not get delayed.)
96 // Delay in milliseconds from startup.
97 const int64 kServiceInitializationStartupDelay
= 5000;
99 // The URL for the device management server.
100 const char kDefaultDeviceManagementServerUrl
[] =
101 "https://m.google.com/devicemanagement/data/api";
103 #if defined(OS_CHROMEOS)
104 // Install attributes for tests.
105 EnterpriseInstallAttributes
* g_testing_install_attributes
= NULL
;
106 #endif // defined(OS_CHROMEOS)
108 // Used in BrowserPolicyConnector::SetPolicyProviderForTesting.
109 ConfigurationPolicyProvider
* g_testing_provider
= NULL
;
111 #if defined(OS_CHROMEOS)
112 // Helper that returns a new SequencedTaskRunner backed by the blocking pool.
113 // Each SequencedTaskRunner returned is independent from the others.
114 scoped_refptr
<base::SequencedTaskRunner
> GetBackgroundTaskRunner() {
115 base::SequencedWorkerPool
* pool
= BrowserThread::GetBlockingPool();
117 return pool
->GetSequencedTaskRunnerWithShutdownBehavior(
118 pool
->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
);
120 #endif // defined(OS_CHROMEOS)
122 #if defined(OS_MACOSX) && !defined(OS_IOS)
123 base::FilePath
GetManagedPolicyPath() {
124 // This constructs the path to the plist file in which Mac OS X stores the
125 // managed preference for the application. This is undocumented and therefore
126 // fragile, but if it doesn't work out, AsyncPolicyLoader has a task that
127 // polls periodically in order to reload managed preferences later even if we
128 // missed the change.
130 if (!PathService::Get(chrome::DIR_MANAGED_PREFS
, &path
))
131 return base::FilePath();
133 CFBundleRef
bundle(CFBundleGetMainBundle());
135 return base::FilePath();
137 CFStringRef bundle_id
= CFBundleGetIdentifier(bundle
);
139 return base::FilePath();
141 return path
.Append(base::SysCFStringRefToUTF8(bundle_id
) + ".plist");
143 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
145 class DeviceManagementServiceConfiguration
146 : public DeviceManagementService::Configuration
{
148 DeviceManagementServiceConfiguration() {}
149 virtual ~DeviceManagementServiceConfiguration() {}
151 virtual std::string
GetServerUrl() OVERRIDE
{
152 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
153 if (command_line
->HasSwitch(switches::kDeviceManagementUrl
))
154 return command_line
->GetSwitchValueASCII(switches::kDeviceManagementUrl
);
156 return kDefaultDeviceManagementServerUrl
;
159 virtual std::string
GetAgentParameter() OVERRIDE
{
160 chrome::VersionInfo version_info
;
161 return base::StringPrintf("%s %s(%s)",
162 version_info
.Name().c_str(),
163 version_info
.Version().c_str(),
164 version_info
.LastChange().c_str());
167 virtual std::string
GetPlatformParameter() OVERRIDE
{
168 std::string os_name
= base::SysInfo::OperatingSystemName();
169 std::string os_hardware
= base::SysInfo::OperatingSystemArchitecture();
171 #if defined(OS_CHROMEOS)
172 chromeos::system::StatisticsProvider
* provider
=
173 chromeos::system::StatisticsProvider::GetInstance();
176 if (!provider
->GetMachineStatistic(chromeos::system::kHardwareClassKey
,
178 LOG(ERROR
) << "Failed to get machine information";
180 os_name
+= ",CrOS," + base::SysInfo::GetLsbReleaseBoard();
181 os_hardware
+= "," + hwclass
;
184 std::string
os_version("-");
185 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
186 int32 os_major_version
= 0;
187 int32 os_minor_version
= 0;
188 int32 os_bugfix_version
= 0;
189 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version
,
192 os_version
= base::StringPrintf("%d.%d.%d",
198 return base::StringPrintf(
199 "%s|%s|%s", os_name
.c_str(), os_hardware
.c_str(), os_version
.c_str());
205 BrowserPolicyConnector::BrowserPolicyConnector()
206 : is_initialized_(false),
208 handler_list_(BuildHandlerList().Pass()),
209 weak_ptr_factory_(this) {
210 // GetPolicyService() must be ready after the constructor is done.
211 // The connector is created very early during startup, when the browser
212 // threads aren't running yet; initialize components that need local_state,
213 // the system request context or other threads (e.g. FILE) at Init().
215 // Initialize the SchemaRegistry with the Chrome schema before creating any
216 // of the policy providers.
217 chrome_schema_
= Schema::Wrap(GetChromeSchemaData());
218 schema_registry_
.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME
, ""),
221 platform_provider_
.reset(CreatePlatformProvider());
223 #if defined(OS_CHROMEOS)
224 if (g_testing_install_attributes
)
225 install_attributes_
.reset(g_testing_install_attributes
);
227 // SystemSaltGetter or DBusThreadManager may be uninitialized on unit tests.
229 // TODO(satorux): Remove SystemSaltGetter::IsInitialized() when it's ready
230 // (removing it now breaks tests). crbug.com/141016.
231 if (chromeos::SystemSaltGetter::IsInitialized() &&
232 chromeos::DBusThreadManager::IsInitialized()) {
233 chromeos::CryptohomeClient
* cryptohome_client
=
234 chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
235 if (!g_testing_install_attributes
) {
236 install_attributes_
.reset(
237 new EnterpriseInstallAttributes(cryptohome_client
));
239 base::FilePath install_attrs_file
;
240 CHECK(PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES
,
241 &install_attrs_file
));
242 install_attributes_
->ReadCacheFile(install_attrs_file
);
244 scoped_ptr
<DeviceCloudPolicyStoreChromeOS
> device_cloud_policy_store(
245 new DeviceCloudPolicyStoreChromeOS(
246 chromeos::DeviceSettingsService::Get(),
247 install_attributes_
.get(),
248 GetBackgroundTaskRunner()));
249 device_cloud_policy_manager_
.reset(
250 new DeviceCloudPolicyManagerChromeOS(
251 device_cloud_policy_store
.Pass(),
252 base::MessageLoopProxy::current(),
253 GetBackgroundTaskRunner(),
254 install_attributes_
.get()));
259 BrowserPolicyConnector::~BrowserPolicyConnector() {
260 if (is_initialized()) {
261 // Shutdown() wasn't invoked by our owner after having called Init().
262 // This usually means it's an early shutdown and
263 // BrowserProcessImpl::StartTearDown() wasn't invoked.
264 // Cleanup properly in those cases and avoid crashing the ToastCrasher test.
269 void BrowserPolicyConnector::Init(
270 PrefService
* local_state
,
271 scoped_refptr
<net::URLRequestContextGetter
> request_context
) {
272 // Initialization of some of the providers requires the FILE thread; make
273 // sure that threading is ready at this point.
274 DCHECK(BrowserThread::IsThreadInitialized(BrowserThread::FILE));
275 DCHECK(!is_initialized()) << "BrowserPolicyConnector::Init() called twice.";
277 local_state_
= local_state
;
278 request_context_
= request_context
;
280 scoped_ptr
<DeviceManagementService::Configuration
> configuration(
281 new DeviceManagementServiceConfiguration
);
282 device_management_service_
.reset(
283 new DeviceManagementService(configuration
.Pass()));
284 device_management_service_
->ScheduleInitialization(
285 kServiceInitializationStartupDelay
);
287 if (g_testing_provider
)
288 g_testing_provider
->Init(GetSchemaRegistry());
289 if (platform_provider_
)
290 platform_provider_
->Init(GetSchemaRegistry());
292 #if defined(OS_CHROMEOS)
293 global_user_cloud_policy_provider_
.Init(GetSchemaRegistry());
295 if (device_cloud_policy_manager_
) {
296 // For now the |device_cloud_policy_manager_| is using the global schema
297 // registry. Eventually it will have its own registry, once device cloud
298 // policy for extensions is introduced.
299 device_cloud_policy_manager_
->Init(GetSchemaRegistry());
300 scoped_ptr
<CloudPolicyClient::StatusProvider
> status_provider(
301 new DeviceStatusCollector(
303 chromeos::system::StatisticsProvider::GetInstance(),
305 device_cloud_policy_manager_
->Connect(
307 device_management_service_
.get(),
308 status_provider
.Pass());
311 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
312 if (!command_line
->HasSwitch(chromeos::switches::kDisableLocalAccounts
)) {
313 device_local_account_policy_service_
.reset(
314 new DeviceLocalAccountPolicyService(
315 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
316 chromeos::DeviceSettingsService::Get(),
317 chromeos::CrosSettings::Get(),
318 GetBackgroundTaskRunner(),
319 GetBackgroundTaskRunner(),
320 GetBackgroundTaskRunner(),
321 content::BrowserThread::GetMessageLoopProxyForThread(
322 content::BrowserThread::IO
),
324 device_local_account_policy_service_
->Connect(
325 device_management_service_
.get());
330 SetTimezoneIfPolicyAvailable();
333 policy_statistics_collector_
.reset(
334 new policy::PolicyStatisticsCollector(
335 base::Bind(&GetChromePolicyDetails
),
339 base::MessageLoop::current()->message_loop_proxy()));
340 policy_statistics_collector_
->Initialize();
342 #if defined(OS_CHROMEOS)
343 network_configuration_updater_
=
344 DeviceNetworkConfigurationUpdater::CreateForDevicePolicy(
345 scoped_ptr
<chromeos::onc::CertificateImporter
>(
346 new chromeos::onc::CertificateImporterImpl
),
348 chromeos::NetworkHandler::Get()
349 ->managed_network_configuration_handler(),
350 chromeos::NetworkHandler::Get()->network_device_handler(),
351 chromeos::CrosSettings::Get());
354 is_initialized_
= true;
357 void BrowserPolicyConnector::Shutdown() {
358 is_initialized_
= false;
360 if (g_testing_provider
)
361 g_testing_provider
->Shutdown();
362 // Drop g_testing_provider so that tests executed with --single_process can
363 // call SetPolicyProviderForTesting() again. It is still owned by the test.
364 g_testing_provider
= NULL
;
365 if (platform_provider_
)
366 platform_provider_
->Shutdown();
368 #if defined(OS_CHROMEOS)
369 // The AppPackUpdater may be observing the |device_cloud_policy_subsystem_|.
371 app_pack_updater_
.reset();
373 network_configuration_updater_
.reset();
375 if (device_cloud_policy_manager_
)
376 device_cloud_policy_manager_
->Shutdown();
377 if (device_local_account_policy_service_
)
378 device_local_account_policy_service_
->Shutdown();
379 global_user_cloud_policy_provider_
.Shutdown();
382 device_management_service_
.reset();
384 request_context_
= NULL
;
387 PolicyService
* BrowserPolicyConnector::GetPolicyService() {
388 if (!policy_service_
) {
389 // |providers| in decreasing order of priority.
390 std::vector
<ConfigurationPolicyProvider
*> providers
;
391 if (g_testing_provider
) {
392 providers
.push_back(g_testing_provider
);
394 if (platform_provider_
)
395 providers
.push_back(platform_provider_
.get());
396 #if defined(OS_CHROMEOS)
397 if (device_cloud_policy_manager_
)
398 providers
.push_back(device_cloud_policy_manager_
.get());
399 providers
.push_back(&global_user_cloud_policy_provider_
);
402 policy_service_
.reset(new PolicyServiceImpl(providers
));
404 return policy_service_
.get();
407 const Schema
& BrowserPolicyConnector::GetChromeSchema() const {
408 return chrome_schema_
;
411 CombinedSchemaRegistry
* BrowserPolicyConnector::GetSchemaRegistry() {
412 return &schema_registry_
;
415 ConfigurationPolicyProvider
* BrowserPolicyConnector::GetPlatformProvider() {
416 if (g_testing_provider
)
417 return g_testing_provider
;
418 return platform_provider_
.get();
421 #if defined(OS_CHROMEOS)
422 bool BrowserPolicyConnector::IsEnterpriseManaged() {
423 return install_attributes_
&& install_attributes_
->IsEnterpriseDevice();
426 std::string
BrowserPolicyConnector::GetEnterpriseDomain() {
427 return install_attributes_
? install_attributes_
->GetDomain() : std::string();
430 DeviceMode
BrowserPolicyConnector::GetDeviceMode() {
431 return install_attributes_
? install_attributes_
->GetMode()
432 : DEVICE_MODE_NOT_SET
;
436 void BrowserPolicyConnector::ScheduleServiceInitialization(
437 int64 delay_milliseconds
) {
438 // Skip device initialization if the BrowserPolicyConnector was never
439 // initialized (unit tests).
440 if (device_management_service_
)
441 device_management_service_
->ScheduleInitialization(delay_milliseconds
);
444 const ConfigurationPolicyHandlerList
*
445 BrowserPolicyConnector::GetHandlerList() const {
446 return handler_list_
.get();
449 UserAffiliation
BrowserPolicyConnector::GetUserAffiliation(
450 const std::string
& user_name
) {
451 #if defined(OS_CHROMEOS)
452 // An empty username means incognito user in case of ChromiumOS and
453 // no logged-in user in case of Chromium (SigninService). Many tests use
454 // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
456 if (user_name
.empty() || user_name
.find('@') == std::string::npos
)
457 return USER_AFFILIATION_NONE
;
458 if (install_attributes_
&&
459 (gaia::ExtractDomainName(gaia::CanonicalizeEmail(user_name
)) ==
460 install_attributes_
->GetDomain() ||
461 policy::IsDeviceLocalAccountUser(user_name
, NULL
))) {
462 return USER_AFFILIATION_MANAGED
;
466 return USER_AFFILIATION_NONE
;
469 #if defined(OS_CHROMEOS)
470 AppPackUpdater
* BrowserPolicyConnector::GetAppPackUpdater() {
471 // request_context_ is NULL in unit tests.
472 if (!app_pack_updater_
&& request_context_
.get()) {
473 app_pack_updater_
.reset(
474 new AppPackUpdater(request_context_
.get(), install_attributes_
.get()));
476 return app_pack_updater_
.get();
479 void BrowserPolicyConnector::SetUserPolicyDelegate(
480 ConfigurationPolicyProvider
* user_policy_provider
) {
481 global_user_cloud_policy_provider_
.SetDelegate(user_policy_provider
);
484 void BrowserPolicyConnector::SetInstallAttributesForTesting(
485 EnterpriseInstallAttributes
* attributes
) {
486 DCHECK(!g_testing_install_attributes
);
487 g_testing_install_attributes
= attributes
;
492 void BrowserPolicyConnector::SetPolicyProviderForTesting(
493 ConfigurationPolicyProvider
* provider
) {
494 CHECK(!g_browser_process
) << "Must be invoked before the browser is created";
495 DCHECK(!g_testing_provider
);
496 g_testing_provider
= provider
;
501 // Returns true if |domain| matches the regex |pattern|.
502 bool MatchDomain(const base::string16
& domain
, const base::string16
& pattern
) {
503 UErrorCode status
= U_ZERO_ERROR
;
504 const icu::UnicodeString
icu_pattern(pattern
.data(), pattern
.length());
505 icu::RegexMatcher
matcher(icu_pattern
, UREGEX_CASE_INSENSITIVE
, status
);
506 DCHECK(U_SUCCESS(status
)) << "Invalid domain pattern: " << pattern
;
507 icu::UnicodeString
icu_input(domain
.data(), domain
.length());
508 matcher
.reset(icu_input
);
509 status
= U_ZERO_ERROR
;
510 UBool match
= matcher
.matches(status
);
511 DCHECK(U_SUCCESS(status
));
512 return !!match
; // !! == convert from UBool to bool
518 bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string
& username
) {
519 if (username
.empty() || username
.find('@') == std::string::npos
) {
520 // An empty username means incognito user in case of ChromiumOS and
521 // no logged-in user in case of Chromium (SigninService). Many tests use
522 // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
527 // Exclude many of the larger public email providers as we know these users
528 // are not from hosted enterprise domains.
529 static const wchar_t* kNonManagedDomainPatterns
[] = {
533 L
"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk
538 L
"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw
541 const base::string16 domain
= base::UTF8ToUTF16(
542 gaia::ExtractDomainName(gaia::CanonicalizeEmail(username
)));
543 for (size_t i
= 0; i
< arraysize(kNonManagedDomainPatterns
); i
++) {
544 base::string16 pattern
= base::WideToUTF16(kNonManagedDomainPatterns
[i
]);
545 if (MatchDomain(domain
, pattern
))
552 void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple
* registry
) {
553 registry
->RegisterIntegerPref(
554 policy_prefs::kUserPolicyRefreshRate
,
555 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs
);
556 #if defined(OS_CHROMEOS)
557 registry
->RegisterIntegerPref(
558 prefs::kDevicePolicyRefreshRate
,
559 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs
);
563 void BrowserPolicyConnector::SetTimezoneIfPolicyAvailable() {
564 #if defined(OS_CHROMEOS)
565 typedef chromeos::CrosSettingsProvider Provider
;
566 Provider::TrustedStatus result
=
567 chromeos::CrosSettings::Get()->PrepareTrustedValues(
568 base::Bind(&BrowserPolicyConnector::SetTimezoneIfPolicyAvailable
,
569 weak_ptr_factory_
.GetWeakPtr()));
571 if (result
!= Provider::TRUSTED
)
574 std::string timezone
;
575 if (chromeos::CrosSettings::Get()->GetString(chromeos::kSystemTimezonePolicy
,
578 chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
579 base::UTF8ToUTF16(timezone
));
584 ConfigurationPolicyProvider
* BrowserPolicyConnector::CreatePlatformProvider() {
586 scoped_ptr
<AsyncPolicyLoader
> loader(PolicyLoaderWin::Create(
587 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
588 kRegistryChromePolicyKey
));
589 return new AsyncPolicyProvider(GetSchemaRegistry(), loader
.Pass());
590 #elif defined(OS_MACOSX) && !defined(OS_IOS)
591 scoped_ptr
<AsyncPolicyLoader
> loader(new PolicyLoaderMac(
592 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
593 GetManagedPolicyPath(),
594 new MacPreferences()));
595 return new AsyncPolicyProvider(GetSchemaRegistry(), loader
.Pass());
596 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
597 base::FilePath config_dir_path
;
598 if (PathService::Get(chrome::DIR_POLICY_FILES
, &config_dir_path
)) {
599 scoped_ptr
<AsyncPolicyLoader
> loader(new ConfigDirPolicyLoader(
600 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
602 POLICY_SCOPE_MACHINE
));
603 return new AsyncPolicyProvider(GetSchemaRegistry(), loader
.Pass());
612 } // namespace policy