auto_enrollment_client.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/auto_enrollment_client.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/guid.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/metrics/sparse_histogram.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/chromeos/policy/server_backed_device_state.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/chrome_content_client.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/chromeos_switches.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/browser/browser_policy_connector.h" 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/device_management_service.h" 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/system_policy_request_context.h" 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/sha2.h" 3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "policy/proto/device_management_backend.pb.h" 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h" 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)using content::BrowserThread; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace policy { 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// UMA histogram names. 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kUMAProtocolTime[] = "Enterprise.AutoEnrollmentProtocolTime"; 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kUMAExtraTime[] = "Enterprise.AutoEnrollmentExtraTime"; 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kUMARequestStatus[] = "Enterprise.AutoEnrollmentRequestStatus"; 46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kUMANetworkErrorCode[] = 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) "Enterprise.AutoEnrollmentRequestNetworkErrorCode"; 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The modulus value is sent in an int64 field in the protobuf, whose maximum 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value is 2^63-1. So 2^64 and 2^63 can't be represented as moduli and the 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// max is 2^62 (when the moduli are restricted to powers-of-2). 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaximumPower = 62; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the int value of the |switch_name| argument, clamped to the [0, 62] 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interval. Returns 0 if the argument doesn't exist or isn't an int value. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetSanitizedArg(const std::string& switch_name) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine* command_line = CommandLine::ForCurrentProcess(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!command_line->HasSwitch(switch_name)) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value = command_line->GetSwitchValueASCII(switch_name); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int int_value; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt(value, &int_value)) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Switch \"" << switch_name << "\" is not a valid int. " 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Defaulting to 0."; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int_value < 0) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Switch \"" << switch_name << "\" can't be negative. " 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Using 0"; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int_value > kMaximumPower) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Switch \"" << switch_name << "\" can't be greater than " 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << kMaximumPower << ". Using " << kMaximumPower; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kMaximumPower; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return int_value; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the power of the next power-of-2 starting at |value|. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NextPowerOf2(int64 value) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i <= kMaximumPower; ++i) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((GG_INT64_C(1) << i) >= value) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other value can be represented in an int64. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kMaximumPower + 1; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Sets or clears a value in a dictionary. 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void UpdateDict(base::DictionaryValue* dict, 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const char* pref_path, 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool set_or_clear, 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Value* value) { 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<base::Value> scoped_value(value); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (set_or_clear) 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dict->Set(pref_path, scoped_value.release()); 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) else 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dict->Remove(pref_path, NULL); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Converts a restore mode enum value from the DM protocol into the 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// corresponding prefs string constant. 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string ConvertRestoreMode( 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) em::DeviceStateRetrievalResponse::RestoreMode restore_mode) { 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (restore_mode) { 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case em::DeviceStateRetrievalResponse::RESTORE_MODE_NONE: 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::string(); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_REQUESTED: 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kDeviceStateRestoreModeReEnrollmentRequested; 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED: 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kDeviceStateRestoreModeReEnrollmentEnforced; 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED() << "Bad restore mode " << restore_mode; 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::string(); 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)AutoEnrollmentClient::AutoEnrollmentClient( 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ProgressCallback& callback, 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementService* service, 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) PrefService* local_state, 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> system_request_context, 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& server_backed_state_key, 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool retrieve_device_state, 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int power_initial, 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int power_limit) 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : progress_callback_(callback), 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state_(STATE_PENDING), 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) has_server_state_(false), 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_state_available_(false), 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_id_(base::GenerateGUID()), 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) server_backed_state_key_(server_backed_state_key), 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) retrieve_device_state_(retrieve_device_state), 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_power_(power_initial), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) power_limit_(power_limit), 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modulus_updates_received_(0), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_management_service_(service), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_state_(local_state) { 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_context_ = new SystemPolicyRequestContext( 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) system_request_context, GetUserAgent()); 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_LE(current_power_, power_limit_); 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!progress_callback_.is_null()); 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!server_backed_state_key_.empty()) { 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) server_backed_state_key_hash_ = 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) crypto::SHA256HashString(server_backed_state_key_); 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 151bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 154bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochAutoEnrollmentClient::~AutoEnrollmentClient() { 155bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 156bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutoEnrollmentClient::RegisterPrefs(PrefRegistrySimple* registry) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterBooleanPref(prefs::kShouldAutoEnroll, false); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterIntegerPref(prefs::kAutoEnrollmentPowerLimit, -1); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutoEnrollmentClient::IsDisabled() { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine* command_line = CommandLine::ForCurrentProcess(); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do not communicate auto-enrollment data to the server if 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 1. we are running integration or perf tests with telemetry. 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 2. modulus configuration is not present. 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return command_line->HasSwitch(chromeos::switches::kOobeSkipPostLogin) || 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (!command_line->HasSwitch( 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chromeos::switches::kEnterpriseEnrollmentInitialModulus) && 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !command_line->HasSwitch( 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chromeos::switches::kEnterpriseEnrollmentModulusLimit)); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutoEnrollmentClient* AutoEnrollmentClient::Create( 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ProgressCallback& progress_callback) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client won't do anything if |service| is NULL. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceManagementService* service = NULL; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsDisabled()) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Auto-enrollment is disabled"; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BrowserPolicyConnector* connector = 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) g_browser_process->browser_policy_connector(); 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) service = connector->device_management_service(); 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) service->ScheduleInitialization(0); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int power_initial = GetSanitizedArg( 192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chromeos::switches::kEnterpriseEnrollmentInitialModulus); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int power_limit = GetSanitizedArg( 194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chromeos::switches::kEnterpriseEnrollmentModulusLimit); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (power_initial > power_limit) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Initial auto-enrollment modulus is larger than the limit, " 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "clamping to the limit."; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) power_initial = power_limit; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool retrieve_device_state = false; 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string device_id; 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chromeos::switches::kEnterpriseEnableForcedReEnrollment)) { 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) retrieve_device_state = true; 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_id = DeviceCloudPolicyManagerChromeOS::GetDeviceStateKey(); 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_id = DeviceCloudPolicyManagerChromeOS::GetMachineID(); 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new AutoEnrollmentClient( 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress_callback, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browser_process->local_state(), 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) g_browser_process->system_request_context(), 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_id, 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) retrieve_device_state, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) power_initial, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) power_limit); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutoEnrollmentClient::CancelAutoEnrollment() { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_state->SetBoolean(prefs::kShouldAutoEnroll, false); 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) local_state->ClearPref(prefs::kServerBackedDeviceState); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_state->CommitPendingWrite(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutoEnrollmentClient::Start() { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drop the previous job and reset state. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_job_.reset(); 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state_ = STATE_PENDING; 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) time_start_ = base::Time::Now(); 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modulus_updates_received_ = 0; 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) has_server_state_ = false; 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_state_available_ = false; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NextStep(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutoEnrollmentClient::CancelAndDeleteSoon() { 243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (time_start_.is_null() || !request_job_) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client isn't running, just delete it. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client still running, but our owner isn't interested in the result 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // anymore. Wait until the protocol completes to measure the extra time 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // needed. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_extra_start_ = base::Time::Now(); 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress_callback_.Reset(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid AutoEnrollmentClient::OnNetworkChanged( 256bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch net::NetworkChangeNotifier::ConnectionType type) { 257bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (type != net::NetworkChangeNotifier::CONNECTION_NONE && 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !progress_callback_.is_null()) { 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RetryStep(); 260bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 261bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 262bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutoEnrollmentClient::GetCachedDecision() { 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const PrefService::Preference* has_server_state_pref = 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_state_->FindPreference(prefs::kShouldAutoEnroll); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PrefService::Preference* previous_limit_pref = 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_state_->FindPreference(prefs::kAutoEnrollmentPowerLimit); 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool has_server_state = false; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int previous_limit = -1; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!has_server_state_pref || 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) has_server_state_pref->IsDefaultValue() || 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !has_server_state_pref->GetValue()->GetAsBoolean(&has_server_state) || 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !previous_limit_pref || 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_limit_pref->IsDefaultValue() || 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !previous_limit_pref->GetValue()->GetAsInteger(&previous_limit) || 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) power_limit_ > previous_limit) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) has_server_state_ = has_server_state; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutoEnrollmentClient::RetryStep() { 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If there is a pending request job, let it finish. 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (request_job_) 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (GetCachedDecision()) { 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The bucket download check has completed already. If it came back 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // positive, then device state should be (re-)downloaded. 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (has_server_state_) { 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (retrieve_device_state_ && !device_state_available_ && 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendDeviceStateRequest()) { 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Start bucket download. 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (SendBucketDownloadRequest()) 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AutoEnrollmentClient::ReportProgress(State state) { 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state_ = state; 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (progress_callback_.is_null()) { 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this); 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress_callback_.Run(state_); 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AutoEnrollmentClient::NextStep() { 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!RetryStep()) { 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Protocol finished successfully, report result. 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool trigger_enrollment = false; 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (retrieve_device_state_) { 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::DictionaryValue* device_state_dict = 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) local_state_->GetDictionary(prefs::kServerBackedDeviceState); 324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string restore_mode; 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_state_dict->GetString(kDeviceStateRestoreMode, &restore_mode); 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) trigger_enrollment = 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (restore_mode == kDeviceStateRestoreModeReEnrollmentRequested || 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) restore_mode == kDeviceStateRestoreModeReEnrollmentEnforced); 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) trigger_enrollment = has_server_state_; 331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReportProgress(trigger_enrollment ? STATE_TRIGGER_ENROLLMENT 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : STATE_NO_ENROLLMENT); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutoEnrollmentClient::SendBucketDownloadRequest() { 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (server_backed_state_key_hash_.empty()) 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only power-of-2 moduli are supported for now. These are computed by taking 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the lower |current_power_| bits of the hash. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 remainder = 0; 345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; 8 * i < current_power_; ++i) { 346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint64 byte = server_backed_state_key_hash_[31 - i] & 0xff; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remainder = remainder | (byte << (8 * i)); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) remainder = remainder & ((GG_UINT64_C(1) << current_power_) - 1); 350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReportProgress(STATE_PENDING); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_job_.reset( 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_management_service_->CreateJob( 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, 356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_context_.get())); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_job_->SetClientID(device_id_); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) em::DeviceAutoEnrollmentRequest* request = 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_job_->GetRequest()->mutable_auto_enrollment_request(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_remainder(remainder); 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request->set_modulus(GG_INT64_C(1) << current_power_); 362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_->Start( 363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AutoEnrollmentClient::HandleRequestCompletion, 364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &AutoEnrollmentClient::OnBucketDownloadRequestCompletion)); 366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutoEnrollmentClient::SendDeviceStateRequest() { 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReportProgress(STATE_PENDING); 371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_.reset( 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_management_service_->CreateJob( 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL, 375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_context_.get())); 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_->SetClientID(device_id_); 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) em::DeviceStateRetrievalRequest* request = 378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_->GetRequest()->mutable_device_state_retrieval_request(); 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request->set_server_backed_state_key(server_backed_state_key_); 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_->Start( 381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AutoEnrollmentClient::HandleRequestCompletion, 382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &AutoEnrollmentClient::OnDeviceStateRequestCompletion)); 384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AutoEnrollmentClient::HandleRequestCompletion( 388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RequestCompletionHandler handler, 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceManagementStatus status, 390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int net_error, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const em::DeviceManagementResponse& response) { 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY(kUMARequestStatus, status); 393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (status != DM_STATUS_SUCCESS) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Auto enrollment error: " << status; 395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (status == DM_STATUS_REQUEST_FAILED) 396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY(kUMANetworkErrorCode, -net_error); 397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_.reset(); 398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Abort if CancelAndDeleteSoon has been called meanwhile. 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (progress_callback_.is_null()) { 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this); 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReportProgress(status == DM_STATUS_REQUEST_FAILED ? STATE_CONNECTION_ERROR 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : STATE_SERVER_ERROR); 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool progress = (this->*handler)(status, net_error, response); 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_job_.reset(); 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (progress) 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NextStep(); 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) else 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReportProgress(STATE_SERVER_ERROR); 415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutoEnrollmentClient::OnBucketDownloadRequestCompletion( 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeviceManagementStatus status, 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int net_error, 420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const em::DeviceManagementResponse& response) { 421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool progress = false; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const em::DeviceAutoEnrollmentResponse& enrollment_response = 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.auto_enrollment_response(); 424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!response.has_auto_enrollment_response()) { 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Server failed to provide auto-enrollment response."; 426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (enrollment_response.has_expected_modulus()) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Server is asking us to retry with a different modulus. 428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modulus_updates_received_++; 429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 modulus = enrollment_response.expected_modulus(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int power = NextPowerOf2(modulus); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((GG_INT64_C(1) << power) != modulus) { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Auto enrollment: the server didn't ask for a power-of-2 " 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "modulus. Using the closest power-of-2 instead " 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "(" << modulus << " vs 2^" << power << ")"; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (modulus_updates_received_ >= 2) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Auto enrollment error: already retried with an updated " 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "modulus but the server asked for a new one again: " 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << power; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (power > power_limit_) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Auto enrollment error: the server asked for a larger " 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "modulus than the client accepts (" << power << " vs " 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << power_limit_ << ")."; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retry at most once with the modulus that the server requested. 447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (power <= current_power_) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Auto enrollment: the server asked to use a modulus (" 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << power << ") that isn't larger than the first used (" 450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << current_power_ << "). Retrying anyway."; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 452bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Remember this value, so that eventual retries start with the correct 453bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // modulus. 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_power_ = power; 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Server should have sent down a list of hashes to try. 459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) has_server_state_ = IsIdHashInProtobuf(enrollment_response.hash()); 46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Cache the current decision in local_state, so that it is reused in case 46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the device reboots before enrolling. 462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) local_state_->SetBoolean(prefs::kShouldAutoEnroll, has_server_state_); 46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) local_state_->SetInteger(prefs::kAutoEnrollmentPowerLimit, power_limit_); 46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) local_state_->CommitPendingWrite(); 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << "Auto enrollment check complete, has_server_state_ = " 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << has_server_state_; 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress = true; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Bucket download done, update UMA. 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UpdateBucketDownloadTimingHistograms(); 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return progress; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutoEnrollmentClient::OnDeviceStateRequestCompletion( 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeviceManagementStatus status, 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int net_error, 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const enterprise_management::DeviceManagementResponse& response) { 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool progress = false; 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!response.has_device_state_retrieval_response()) { 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Server failed to provide auto-enrollment response."; 482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const em::DeviceStateRetrievalResponse& state_response = 484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) response.device_state_retrieval_response(); 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DictionaryPrefUpdate dict(local_state_, prefs::kServerBackedDeviceState); 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UpdateDict(dict.Get(), 488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kDeviceStateManagementDomain, 489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state_response.has_management_domain(), 490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new base::StringValue(state_response.management_domain())); 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string restore_mode = 493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ConvertRestoreMode(state_response.restore_mode()); 494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UpdateDict(dict.Get(), 495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kDeviceStateRestoreMode, 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !restore_mode.empty(), 497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new base::StringValue(restore_mode)); 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) local_state_->CommitPendingWrite(); 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_state_available_ = true; 501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress = true; 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return progress; 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutoEnrollmentClient::IsIdHashInProtobuf( 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const google::protobuf::RepeatedPtrField<std::string>& hashes) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < hashes.size(); ++i) { 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (hashes.Get(i) == server_backed_state_key_hash_) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AutoEnrollmentClient::UpdateBucketDownloadTimingHistograms() { 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The mininum time can't be 0, must be at least 1. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const base::TimeDelta kMin = base::TimeDelta::FromMilliseconds(1); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const base::TimeDelta kMax = base::TimeDelta::FromMinutes(5); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, 0 can still be sampled. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const base::TimeDelta kZero = base::TimeDelta::FromMilliseconds(0); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kBuckets = 50; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time now = base::Time::Now(); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!time_start_.is_null()) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta delta = now - time_start_; 527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES(kUMAProtocolTime, delta, kMin, kMax, kBuckets); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta delta = kZero; 530bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!time_extra_start_.is_null()) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delta = now - time_extra_start_; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This samples |kZero| when there was no need for extra time, so that we can 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // measure the ratio of users that succeeded without needing a delay to the 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // total users going through OOBE. 535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES(kUMAExtraTime, delta, kMin, kMax, kBuckets); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 539