1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be 3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file. 4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/policy/cloud_policy_controller.h" 6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <algorithm> 8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h" 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/message_loop.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/rand_util.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/string_util.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/policy/cloud_policy_cache_base.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/policy/cloud_policy_subsystem.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/policy/device_management_backend.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/policy/device_management_service.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/policy/proto/device_management_constants.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Domain names that are known not to be managed. 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// We don't register the device when such a user logs in. 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const char* kNonManagedDomains[] = { 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen "@googlemail.com", 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen "@gmail.com" 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Checks the domain part of the given username against the list of known 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// non-managed domain names. Returns false if |username| is empty or 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// in a domain known not to be managed. 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic bool CanBeInManagedDomain(const std::string& username) { 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (username.empty()) { 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This means incognito user in case of ChromiumOS and 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // no logged-in user in case of Chromium (SigninService). 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) { 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (EndsWith(username, kNonManagedDomains[i], true)) { 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace policy { 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace em = enterprise_management; 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// The maximum ratio in percent of the policy refresh rate we use for adjusting 48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// the policy refresh time instant. The rationale is to avoid load spikes from 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// many devices that were set up in sync for some reason. 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const int kPolicyRefreshDeviationFactorPercent = 10; 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Maximum deviation we are willing to accept. 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// These are the base values for delays before retrying after an error. They 55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// will be doubled each time they are used. 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const int64 kPolicyRefreshErrorDelayInMilliseconds = 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5 * 60 * 1000; // 5 minutes 58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Default value for the policy refresh rate. 60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const int kPolicyRefreshRateInMilliseconds = 61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 3 * 60 * 60 * 1000; // 3 hours. 62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 63dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCloudPolicyController::CloudPolicyController( 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeviceManagementService* service, 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicyCacheBase* cache, 66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeviceTokenFetcher* token_fetcher, 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicyIdentityStrategy* identity_strategy, 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier* notifier) 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Initialize(service, 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cache, 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen token_fetcher, 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy, 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier, 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kPolicyRefreshRateInMilliseconds, 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kPolicyRefreshDeviationFactorPercent, 77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kPolicyRefreshDeviationMaxInMilliseconds, 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kPolicyRefreshErrorDelayInMilliseconds); 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 81dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCloudPolicyController::~CloudPolicyController() { 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen token_fetcher_->RemoveObserver(this); 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy_->RemoveObserver(this); 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CancelDelayedWork(); 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::SetRefreshRate(int64 refresh_rate_milliseconds) { 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_rate_ms_ = refresh_rate_milliseconds; 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Reschedule the refresh task if necessary. 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (state_ == STATE_POLICY_VALID) 92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetState(STATE_POLICY_VALID); 93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CloudPolicyController::Retry() { 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CancelDelayedWork(); 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoWork(); 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CloudPolicyController::StopAutoRetry() { 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CancelDelayedWork(); 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen backend_.reset(); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::HandlePolicyResponse( 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const em::DevicePolicyResponse& response) { 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (response.response_size() > 0) { 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (response.response_size() > 1) { 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(WARNING) << "More than one policy in the response of the device " 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "management server, discarding."; 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (response.response(0).error_code() != 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeviceManagementBackend::kErrorServicePolicyNotFound) { 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cache_->SetPolicy(response.response(0)); 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(STATE_POLICY_VALID); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(STATE_POLICY_UNAVAILABLE); 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) { 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (code) { 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorServiceDeviceNotFound: 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: { 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(WARNING) << "The device token was either invalid or unknown to the " 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << "device manager, re-registering device."; 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Will retry fetching a token but gracefully backing off. 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(STATE_TOKEN_ERROR); 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorServiceManagementNotSupported: { 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "The device is no longer managed."; 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen token_fetcher_->SetUnmanagedState(); 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(STATE_TOKEN_UNMANAGED); 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorServicePolicyNotFound: 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorRequestInvalid: 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorServiceActivationPending: 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorResponseDecoding: 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorHttpStatus: { 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "An error in the communication with the policy server occurred" 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << ", will retry in a few hours."; 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(STATE_POLICY_UNAVAILABLE); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorRequestFailed: 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DeviceManagementBackend::kErrorTemporaryUnavailable: { 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "A temporary error in the communication with the policy server" 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " occurred."; 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Will retry last operation but gracefully backing off. 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(STATE_POLICY_ERROR); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::OnDeviceTokenAvailable() { 159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy_->OnDeviceTokenAvailable(token_fetcher_->GetDeviceToken()); 160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::OnDeviceTokenChanged() { 163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (identity_strategy_->GetDeviceToken().empty()) 164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetState(STATE_TOKEN_UNAVAILABLE); 165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else 166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetState(STATE_TOKEN_VALID); 167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::OnCredentialsChanged() { 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_; 171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetState(STATE_TOKEN_UNAVAILABLE); 172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 174dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCloudPolicyController::CloudPolicyController( 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeviceManagementService* service, 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicyCacheBase* cache, 177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeviceTokenFetcher* token_fetcher, 178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CloudPolicyIdentityStrategy* identity_strategy, 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier* notifier, 180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 policy_refresh_rate_ms, 181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int policy_refresh_deviation_factor_percent, 182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 policy_refresh_deviation_max_ms, 183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 policy_refresh_error_delay_ms) 184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Initialize(service, 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cache, 187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen token_fetcher, 188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy, 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier, 190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_rate_ms, 191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_deviation_factor_percent, 192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_deviation_max_ms, 193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_error_delay_ms); 194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::Initialize( 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeviceManagementService* service, 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicyCacheBase* cache, 199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DeviceTokenFetcher* token_fetcher, 200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CloudPolicyIdentityStrategy* identity_strategy, 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier* notifier, 202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 policy_refresh_rate_ms, 203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int policy_refresh_deviation_factor_percent, 204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 policy_refresh_deviation_max_ms, 205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 policy_refresh_error_delay_ms) { 206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(cache); 207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen service_ = service; 209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cache_ = cache; 210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen token_fetcher_ = token_fetcher; 211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy_ = identity_strategy; 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier_ = notifier; 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen state_ = STATE_TOKEN_UNAVAILABLE; 214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delayed_work_task_ = NULL; 215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_rate_ms_ = policy_refresh_rate_ms; 216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_deviation_factor_percent_ = 217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_deviation_factor_percent; 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms; 219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms; 220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms; 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen token_fetcher_->AddObserver(this); 223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy_->AddObserver(this); 224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!identity_strategy_->GetDeviceToken().empty()) 225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetState(STATE_TOKEN_VALID); 226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else 227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetState(STATE_TOKEN_UNAVAILABLE); 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::FetchToken() { 231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string username; 232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string auth_token; 233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string device_id = identity_strategy_->GetDeviceID(); 234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string machine_id = identity_strategy_->GetMachineID(); 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string machine_model = identity_strategy_->GetMachineModel(); 236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen em::DeviceRegisterRequest_Type policy_type = 237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy_->GetPolicyRegisterType(); 238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (identity_strategy_->GetCredentials(&username, &auth_token) && 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CanBeInManagedDomain(username)) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen token_fetcher_->FetchToken(auth_token, device_id, policy_type, 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen machine_id, machine_model); 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::SendPolicyRequest() { 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen backend_.reset(service_->CreateBackend()); 247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!identity_strategy_->GetDeviceToken().empty()); 248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen em::DevicePolicyRequest policy_request; 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen em::PolicyFetchRequest* fetch_request = policy_request.add_request(); 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); 251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen fetch_request->set_policy_type(identity_strategy_->GetPolicyType()); 252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!cache_->is_unmanaged() && 253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen !cache_->last_policy_refresh_time().is_null()) { 254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::TimeDelta timestamp = 255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); 256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen fetch_request->set_timestamp(timestamp.InMilliseconds()); 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int key_version = 0; 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (cache_->GetPublicKeyVersion(&key_version)) 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen fetch_request->set_public_key_version(key_version); 261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen backend_->ProcessPolicyRequest(identity_strategy_->GetDeviceToken(), 263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen identity_strategy_->GetDeviceID(), 264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_request, this); 265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::DoDelayedWork() { 268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(delayed_work_task_); 269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delayed_work_task_ = NULL; 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoWork(); 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CloudPolicyController::DoWork() { 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen switch (state_) { 275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_TOKEN_UNAVAILABLE: 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case STATE_TOKEN_ERROR: 277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FetchToken(); 278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_TOKEN_VALID: 280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_POLICY_VALID: 281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_POLICY_ERROR: 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case STATE_POLICY_UNAVAILABLE: 283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendPolicyRequest(); 284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case STATE_TOKEN_UNMANAGED: 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED() << "Unhandled state" << state_; 290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::CancelDelayedWork() { 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (delayed_work_task_) { 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delayed_work_task_->Cancel(); 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delayed_work_task_ = NULL; 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CloudPolicyController::SetState( 300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CloudPolicyController::ControllerState new_state) { 301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen state_ = new_state; 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen backend_.reset(); // Discard any pending requests. 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::Time now(base::Time::NowFromSystemTime()); 305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::Time refresh_at; 306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::Time last_refresh(cache_->last_policy_refresh_time()); 307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (last_refresh.is_null()) 308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen last_refresh = now; 309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Determine when to take the next step. 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool inform_notifier_done = false; 312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen switch (state_) { 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case STATE_TOKEN_UNMANAGED: 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier_->Inform(CloudPolicySubsystem::UNMANAGED, 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicySubsystem::NO_DETAILS, 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier::POLICY_CONTROLLER); 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_TOKEN_UNAVAILABLE: 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The controller is not yet initialized and needs to immediately fetch 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // token and policy if present. 321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_TOKEN_VALID: 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Immediately try to fetch the token on initialization or policy after a 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // token update. Subsequent retries will respect the back-off strategy. 324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen refresh_at = now; 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |notifier_| isn't informed about anything at this point, we wait for 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the result of the next action first. 327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_POLICY_VALID: 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Delay is only reset if the policy fetch operation was successful. This 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will ensure the server won't get overloaded with retries in case of 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a bug on either side. 332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_; 333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen refresh_at = 334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay()); 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier_->Inform(CloudPolicySubsystem::SUCCESS, 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicySubsystem::NO_DETAILS, 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier::POLICY_CONTROLLER); 338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case STATE_TOKEN_ERROR: 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR, 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicySubsystem::BAD_DMTOKEN, 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier::POLICY_CONTROLLER); 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen inform_notifier_done = true; 344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case STATE_POLICY_ERROR: 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!inform_notifier_done) { 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR, 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicySubsystem::POLICY_NETWORK_ERROR, 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier::POLICY_CONTROLLER); 349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen refresh_at = now + base::TimeDelta::FromMilliseconds( 351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen effective_policy_refresh_error_delay_ms_); 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen effective_policy_refresh_error_delay_ms_ = 353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::min(effective_policy_refresh_error_delay_ms_ * 2, 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen policy_refresh_rate_ms_); 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case STATE_POLICY_UNAVAILABLE: 357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_; 358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen refresh_at = now + base::TimeDelta::FromMilliseconds( 359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen effective_policy_refresh_error_delay_ms_); 360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR, 361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloudPolicySubsystem::POLICY_NETWORK_ERROR, 362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PolicyNotifier::POLICY_CONTROLLER); 363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Update the delayed work task. 367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CancelDelayedWork(); 368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!refresh_at.is_null()) { 369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0); 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delayed_work_task_ = method_factory_.NewRunnableMethod( 371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &CloudPolicyController::DoDelayedWork); 372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MessageLoop::current()->PostDelayedTask(FROM_HERE, delayed_work_task_, 373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delay); 374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint64 CloudPolicyController::GetRefreshDelay() { 378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 deviation = (policy_refresh_deviation_factor_percent_ * 379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen policy_refresh_rate_ms_) / 100; 380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen deviation = std::min(deviation, policy_refresh_deviation_max_ms_); 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); 382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace policy 385