browser_policy_connector.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 if (!U_SUCCESS(status)) { 48 // http://crbug.com/365351 - if for some reason the matcher creation fails 49 // just return that the pattern doesn't match the domain. This is safe 50 // because the calling method (IsNonEnterpriseUser()) is just used to enable 51 // an optimization for non-enterprise users - better to skip the 52 // optimization than crash. 53 DLOG(ERROR) << "Possible invalid domain pattern: " << pattern 54 << " - Error: " << status; 55 return false; 56 } 57 icu::UnicodeString icu_input(domain.data(), domain.length()); 58 matcher.reset(icu_input); 59 status = U_ZERO_ERROR; 60 UBool match = matcher.matches(status); 61 DCHECK(U_SUCCESS(status)); 62 return !!match; // !! == convert from UBool to bool. 63} 64 65} // namespace 66 67BrowserPolicyConnector::BrowserPolicyConnector( 68 const HandlerListFactory& handler_list_factory) 69 : is_initialized_(false), 70 platform_policy_provider_(NULL) { 71 // GetPolicyService() must be ready after the constructor is done. 72 // The connector is created very early during startup, when the browser 73 // threads aren't running yet; initialize components that need local_state, 74 // the system request context or other threads (e.g. FILE) at Init(). 75 76 // Initialize the SchemaRegistry with the Chrome schema before creating any 77 // of the policy providers in subclasses. 78 chrome_schema_ = Schema::Wrap(GetChromeSchemaData()); 79 handler_list_ = handler_list_factory.Run(chrome_schema_); 80 schema_registry_.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""), 81 chrome_schema_); 82} 83 84BrowserPolicyConnector::~BrowserPolicyConnector() { 85 if (is_initialized()) { 86 // Shutdown() wasn't invoked by our owner after having called Init(). 87 // This usually means it's an early shutdown and 88 // BrowserProcessImpl::StartTearDown() wasn't invoked. 89 // Cleanup properly in those cases and avoid crashing the ToastCrasher test. 90 Shutdown(); 91 } 92} 93 94void BrowserPolicyConnector::Init( 95 PrefService* local_state, 96 scoped_refptr<net::URLRequestContextGetter> request_context, 97 scoped_ptr<DeviceManagementService> device_management_service) { 98 DCHECK(!is_initialized()); 99 100 device_management_service_ = device_management_service.Pass(); 101 102 if (g_testing_provider) 103 g_testing_provider->Init(GetSchemaRegistry()); 104 for (size_t i = 0; i < policy_providers_.size(); ++i) 105 policy_providers_[i]->Init(GetSchemaRegistry()); 106 107 policy_statistics_collector_.reset( 108 new policy::PolicyStatisticsCollector( 109 base::Bind(&GetChromePolicyDetails), 110 GetChromeSchema(), 111 GetPolicyService(), 112 local_state, 113 base::MessageLoop::current()->message_loop_proxy())); 114 policy_statistics_collector_->Initialize(); 115 116 is_initialized_ = true; 117} 118 119void BrowserPolicyConnector::Shutdown() { 120 is_initialized_ = false; 121 if (g_testing_provider) 122 g_testing_provider->Shutdown(); 123 for (size_t i = 0; i < policy_providers_.size(); ++i) 124 policy_providers_[i]->Shutdown(); 125 // Drop g_testing_provider so that tests executed with --single_process can 126 // call SetPolicyProviderForTesting() again. It is still owned by the test. 127 g_testing_provider = NULL; 128 g_created_policy_service = false; 129 device_management_service_.reset(); 130} 131 132PolicyService* BrowserPolicyConnector::GetPolicyService() { 133 if (!policy_service_) { 134 g_created_policy_service = true; 135 std::vector<ConfigurationPolicyProvider*> providers; 136 if (g_testing_provider) { 137 providers.push_back(g_testing_provider); 138 } else { 139 providers.resize(policy_providers_.size()); 140 std::copy(policy_providers_.begin(), 141 policy_providers_.end(), 142 providers.begin()); 143 } 144 policy_service_.reset(new PolicyServiceImpl(providers)); 145 } 146 return policy_service_.get(); 147} 148 149ConfigurationPolicyProvider* BrowserPolicyConnector::GetPlatformProvider() { 150 if (g_testing_provider) 151 return g_testing_provider; 152 return platform_policy_provider_; 153} 154 155const Schema& BrowserPolicyConnector::GetChromeSchema() const { 156 return chrome_schema_; 157} 158 159CombinedSchemaRegistry* BrowserPolicyConnector::GetSchemaRegistry() { 160 return &schema_registry_; 161} 162 163void BrowserPolicyConnector::ScheduleServiceInitialization( 164 int64 delay_milliseconds) { 165 // Skip device initialization if the BrowserPolicyConnector was never 166 // initialized (unit tests). 167 if (device_management_service_) 168 device_management_service_->ScheduleInitialization(delay_milliseconds); 169} 170 171const ConfigurationPolicyHandlerList* 172 BrowserPolicyConnector::GetHandlerList() const { 173 return handler_list_.get(); 174} 175 176// static 177void BrowserPolicyConnector::SetPolicyProviderForTesting( 178 ConfigurationPolicyProvider* provider) { 179 // If this function is used by a test then it must be called before the 180 // browser is created, and GetPolicyService() gets called. 181 CHECK(!g_created_policy_service); 182 DCHECK(!g_testing_provider); 183 g_testing_provider = provider; 184} 185 186// static 187bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) { 188 if (username.empty() || username.find('@') == std::string::npos) { 189 // An empty username means incognito user in case of ChromiumOS and 190 // no logged-in user in case of Chromium (SigninService). Many tests use 191 // nonsense email addresses (e.g. 'test') so treat those as non-enterprise 192 // users. 193 return true; 194 } 195 196 // Exclude many of the larger public email providers as we know these users 197 // are not from hosted enterprise domains. 198 static const wchar_t* kNonManagedDomainPatterns[] = { 199 L"aol\\.com", 200 L"googlemail\\.com", 201 L"gmail\\.com", 202 L"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk 203 L"live\\.com", 204 L"mail\\.ru", 205 L"msn\\.com", 206 L"qq\\.com", 207 L"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw 208 L"yandex\\.ru", 209 }; 210 const base::string16 domain = base::UTF8ToUTF16( 211 gaia::ExtractDomainName(gaia::CanonicalizeEmail(username))); 212 for (size_t i = 0; i < arraysize(kNonManagedDomainPatterns); i++) { 213 base::string16 pattern = base::WideToUTF16(kNonManagedDomainPatterns[i]); 214 if (MatchDomain(domain, pattern)) 215 return true; 216 } 217 return false; 218} 219 220// static 221std::string BrowserPolicyConnector::GetDeviceManagementUrl() { 222 CommandLine* command_line = CommandLine::ForCurrentProcess(); 223 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) 224 return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl); 225 else 226 return kDefaultDeviceManagementServerUrl; 227} 228 229// static 230void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) { 231 registry->RegisterIntegerPref( 232 policy_prefs::kUserPolicyRefreshRate, 233 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs); 234} 235 236void BrowserPolicyConnector::AddPolicyProvider( 237 scoped_ptr<ConfigurationPolicyProvider> provider) { 238 policy_providers_.push_back(provider.release()); 239} 240 241void BrowserPolicyConnector::SetPlatformPolicyProvider( 242 scoped_ptr<ConfigurationPolicyProvider> provider) { 243 CHECK(!platform_policy_provider_); 244 platform_policy_provider_ = provider.get(); 245 AddPolicyProvider(provider.Pass()); 246} 247 248} // namespace policy 249