browser_policy_connector.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2014 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. 4 5#include "components/policy/core/browser/browser_policy_connector.h" 6 7#include <algorithm> 8#include <vector> 9 10#include "base/command_line.h" 11#include "base/logging.h" 12#include "base/message_loop/message_loop.h" 13#include "base/message_loop/message_loop_proxy.h" 14#include "base/prefs/pref_registry_simple.h" 15#include "base/strings/string16.h" 16#include "base/strings/utf_string_conversions.h" 17#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" 18#include "components/policy/core/common/cloud/device_management_service.h" 19#include "components/policy/core/common/configuration_policy_provider.h" 20#include "components/policy/core/common/policy_namespace.h" 21#include "components/policy/core/common/policy_pref_names.h" 22#include "components/policy/core/common/policy_service_impl.h" 23#include "components/policy/core/common/policy_statistics_collector.h" 24#include "components/policy/core/common/policy_switches.h" 25#include "google_apis/gaia/gaia_auth_util.h" 26#include "net/url_request/url_request_context_getter.h" 27#include "policy/policy_constants.h" 28#include "third_party/icu/source/i18n/unicode/regex.h" 29 30namespace policy { 31 32namespace { 33 34// The URL for the device management server. 35const char kDefaultDeviceManagementServerUrl[] = 36 "https://m.google.com/devicemanagement/data/api"; 37 38// Used in BrowserPolicyConnector::SetPolicyProviderForTesting. 39bool g_created_policy_service = false; 40ConfigurationPolicyProvider* g_testing_provider = NULL; 41 42// Returns true if |domain| matches the regex |pattern|. 43bool MatchDomain(const base::string16& domain, const base::string16& pattern) { 44 UErrorCode status = U_ZERO_ERROR; 45 const icu::UnicodeString icu_pattern(pattern.data(), pattern.length()); 46 icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status); 47 DCHECK(U_SUCCESS(status)) << "Invalid domain pattern: " << pattern; 48 icu::UnicodeString icu_input(domain.data(), domain.length()); 49 matcher.reset(icu_input); 50 status = U_ZERO_ERROR; 51 UBool match = matcher.matches(status); 52 DCHECK(U_SUCCESS(status)); 53 return !!match; // !! == convert from UBool to bool. 54} 55 56} // namespace 57 58BrowserPolicyConnector::BrowserPolicyConnector( 59 const HandlerListFactory& handler_list_factory) 60 : is_initialized_(false), 61 platform_policy_provider_(NULL) { 62 // GetPolicyService() must be ready after the constructor is done. 63 // The connector is created very early during startup, when the browser 64 // threads aren't running yet; initialize components that need local_state, 65 // the system request context or other threads (e.g. FILE) at Init(). 66 67 // Initialize the SchemaRegistry with the Chrome schema before creating any 68 // of the policy providers in subclasses. 69 chrome_schema_ = Schema::Wrap(GetChromeSchemaData()); 70 handler_list_ = handler_list_factory.Run(chrome_schema_); 71 schema_registry_.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""), 72 chrome_schema_); 73} 74 75BrowserPolicyConnector::~BrowserPolicyConnector() { 76 if (is_initialized()) { 77 // Shutdown() wasn't invoked by our owner after having called Init(). 78 // This usually means it's an early shutdown and 79 // BrowserProcessImpl::StartTearDown() wasn't invoked. 80 // Cleanup properly in those cases and avoid crashing the ToastCrasher test. 81 Shutdown(); 82 } 83} 84 85void BrowserPolicyConnector::Init( 86 PrefService* local_state, 87 scoped_refptr<net::URLRequestContextGetter> request_context, 88 scoped_ptr<DeviceManagementService> device_management_service) { 89 DCHECK(!is_initialized()); 90 91 device_management_service_ = device_management_service.Pass(); 92 93 if (g_testing_provider) 94 g_testing_provider->Init(GetSchemaRegistry()); 95 for (size_t i = 0; i < policy_providers_.size(); ++i) 96 policy_providers_[i]->Init(GetSchemaRegistry()); 97 98 policy_statistics_collector_.reset( 99 new policy::PolicyStatisticsCollector( 100 base::Bind(&GetChromePolicyDetails), 101 GetChromeSchema(), 102 GetPolicyService(), 103 local_state, 104 base::MessageLoop::current()->message_loop_proxy())); 105 policy_statistics_collector_->Initialize(); 106 107 is_initialized_ = true; 108} 109 110void BrowserPolicyConnector::Shutdown() { 111 is_initialized_ = false; 112 if (g_testing_provider) 113 g_testing_provider->Shutdown(); 114 for (size_t i = 0; i < policy_providers_.size(); ++i) 115 policy_providers_[i]->Shutdown(); 116 // Drop g_testing_provider so that tests executed with --single_process can 117 // call SetPolicyProviderForTesting() again. It is still owned by the test. 118 g_testing_provider = NULL; 119 device_management_service_.reset(); 120} 121 122PolicyService* BrowserPolicyConnector::GetPolicyService() { 123 if (!policy_service_) { 124 g_created_policy_service = true; 125 std::vector<ConfigurationPolicyProvider*> providers; 126 if (g_testing_provider) { 127 providers.push_back(g_testing_provider); 128 } else { 129 providers.resize(policy_providers_.size()); 130 std::copy(policy_providers_.begin(), 131 policy_providers_.end(), 132 providers.begin()); 133 } 134 policy_service_.reset(new PolicyServiceImpl(providers)); 135 } 136 return policy_service_.get(); 137} 138 139ConfigurationPolicyProvider* BrowserPolicyConnector::GetPlatformProvider() { 140 if (g_testing_provider) 141 return g_testing_provider; 142 return platform_policy_provider_; 143} 144 145const Schema& BrowserPolicyConnector::GetChromeSchema() const { 146 return chrome_schema_; 147} 148 149CombinedSchemaRegistry* BrowserPolicyConnector::GetSchemaRegistry() { 150 return &schema_registry_; 151} 152 153void BrowserPolicyConnector::ScheduleServiceInitialization( 154 int64 delay_milliseconds) { 155 // Skip device initialization if the BrowserPolicyConnector was never 156 // initialized (unit tests). 157 if (device_management_service_) 158 device_management_service_->ScheduleInitialization(delay_milliseconds); 159} 160 161const ConfigurationPolicyHandlerList* 162 BrowserPolicyConnector::GetHandlerList() const { 163 return handler_list_.get(); 164} 165 166// static 167void BrowserPolicyConnector::SetPolicyProviderForTesting( 168 ConfigurationPolicyProvider* provider) { 169 // If this function is used by a test then it must be called before the 170 // browser is created, and GetPolicyService() gets called. 171 CHECK(!g_created_policy_service); 172 DCHECK(!g_testing_provider); 173 g_testing_provider = provider; 174} 175 176// static 177bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) { 178 if (username.empty() || username.find('@') == std::string::npos) { 179 // An empty username means incognito user in case of ChromiumOS and 180 // no logged-in user in case of Chromium (SigninService). Many tests use 181 // nonsense email addresses (e.g. 'test') so treat those as non-enterprise 182 // users. 183 return true; 184 } 185 186 // Exclude many of the larger public email providers as we know these users 187 // are not from hosted enterprise domains. 188 static const wchar_t* kNonManagedDomainPatterns[] = { 189 L"aol\\.com", 190 L"googlemail\\.com", 191 L"gmail\\.com", 192 L"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk 193 L"live\\.com", 194 L"mail\\.ru", 195 L"msn\\.com", 196 L"qq\\.com", 197 L"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw 198 L"yandex\\.ru", 199 }; 200 const base::string16 domain = base::UTF8ToUTF16( 201 gaia::ExtractDomainName(gaia::CanonicalizeEmail(username))); 202 for (size_t i = 0; i < arraysize(kNonManagedDomainPatterns); i++) { 203 base::string16 pattern = base::WideToUTF16(kNonManagedDomainPatterns[i]); 204 if (MatchDomain(domain, pattern)) 205 return true; 206 } 207 return false; 208} 209 210// static 211std::string BrowserPolicyConnector::GetDeviceManagementUrl() { 212 CommandLine* command_line = CommandLine::ForCurrentProcess(); 213 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) 214 return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl); 215 else 216 return kDefaultDeviceManagementServerUrl; 217} 218 219// static 220void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) { 221 registry->RegisterIntegerPref( 222 policy_prefs::kUserPolicyRefreshRate, 223 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs); 224} 225 226void BrowserPolicyConnector::AddPolicyProvider( 227 scoped_ptr<ConfigurationPolicyProvider> provider) { 228 policy_providers_.push_back(provider.release()); 229} 230 231void BrowserPolicyConnector::SetPlatformPolicyProvider( 232 scoped_ptr<ConfigurationPolicyProvider> provider) { 233 CHECK(!platform_policy_provider_); 234 platform_policy_provider_ = provider.get(); 235 AddPolicyProvider(provider.Pass()); 236} 237 238} // namespace policy 239