Commit 055e83c3 authored by Pavol Marko's avatar Pavol Marko Committed by Commit Bot

Add support for forced initial enrollment check

Add support for the forced initial enrollment check in
AutoEnrollmentClient. This check uses a different identifier set, 8 byte
hashes and a different message for the state download.
The differences are abstracted by using two virtual classes with
different implementations for FRE/initial enrollment checks:
DeviceIdentifierProvider specifies the identifier set and hashes, and
StateDownloadMessageProcessor understands fills state download requests
and parses state download responses.

Bug: 839353
Test: unit_tests --gtest_filter=*AutoEnrollmentClientTest*
Change-Id: I83d041f568d84c42b9b8cf00a1e44955f9d5abe3
Reviewed-on: https://chromium-review.googlesource.com/1049929
Commit-Queue: Pavol Marko <pmarko@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557627}
parent cbbf0110
......@@ -267,7 +267,7 @@ void AutoEnrollmentController::StartClient(
power_initial = power_limit;
}
client_ = std::make_unique<policy::AutoEnrollmentClient>(
client_ = policy::AutoEnrollmentClient::CreateForFRE(
base::Bind(&AutoEnrollmentController::UpdateState,
weak_ptr_factory_.GetWeakPtr()),
service, g_browser_process->local_state(),
......
......@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chromeos/policy/server_backed_device_state.h"
#include "chrome/common/chrome_content_client.h"
......@@ -34,6 +35,9 @@ namespace policy {
namespace {
using EnrollmentCheckType =
em::DeviceAutoEnrollmentRequest::EnrollmentCheckType;
// UMA histogram names.
const char kUMAProtocolTime[] = "Enterprise.AutoEnrollmentProtocolTime";
const char kUMAExtraTime[] = "Enterprise.AutoEnrollmentExtraTime";
......@@ -62,7 +66,7 @@ void UpdateDict(base::DictionaryValue* dict,
dict->Remove(pref_path, NULL);
}
// Converts a restore mode enum value from the DM protocol into the
// Converts a restore mode enum value from the DM protocol for FRE into the
// corresponding prefs string constant.
std::string ConvertRestoreMode(
em::DeviceStateRetrievalResponse::RestoreMode restore_mode) {
......@@ -84,33 +88,278 @@ std::string ConvertRestoreMode(
return std::string();
}
// Converts an initial enrollment mode enum value from the DM protocol for
// initial enrollment into the corresponding prefs string constant. Note that we
// use the |kDeviceStateRestoreMode*| constants on the client for simplicity,
// because every initial enrollment mode has a matching restore mode (but not
// vice versa).
std::string ConvertInitialEnrollmentMode(
em::DeviceInitialEnrollmentStateResponse::InitialEnrollmentMode
initial_enrollment_mode) {
switch (initial_enrollment_mode) {
case em::DeviceInitialEnrollmentStateResponse::INITIAL_ENROLLMENT_MODE_NONE:
return std::string();
case em::DeviceInitialEnrollmentStateResponse::
INITIAL_ENROLLMENT_MODE_ENROLLMENT_ENFORCED:
return kDeviceStateRestoreModeReEnrollmentEnforced;
}
}
} // namespace
AutoEnrollmentClient::AutoEnrollmentClient(
const ProgressCallback& callback,
DeviceManagementService* service,
// Subclasses of this class provide an identifier and specify the identifier
// set for the DeviceAutoEnrollmentRequest,
class AutoEnrollmentClient::DeviceIdentifierProvider {
public:
virtual ~DeviceIdentifierProvider() {}
// Should return the EnrollmentCheckType to be used in the
// DeviceAutoEnrollmentRequest. This specifies the identifier set used on
// the server.
virtual enterprise_management::DeviceAutoEnrollmentRequest::
EnrollmentCheckType
GetEnrollmentCheckType() const = 0;
// Should return the hash of this device's identifier. The
// DeviceAutoEnrollmentRequest exchange will check if this hash is in the
// server-side identifier set specified by |GetEnrollmentCheckType()|
virtual const std::string& GetIdHash() const = 0;
};
// Subclasses of this class generate the request to download the device state
// (after determining that there is server-side device state) and parse the
// response.
class AutoEnrollmentClient::StateDownloadMessageProcessor {
public:
virtual ~StateDownloadMessageProcessor() {}
// Returns the request job type. This must match the request filled in
// |FillRequest|.
virtual DeviceManagementRequestJob::JobType GetJobType() const = 0;
// Fills the specific request type in |request|.
virtual void FillRequest(
enterprise_management::DeviceManagementRequest* request) = 0;
// Parses the |response|. If it is valid, extracts |restore_mode|,
// |management_domain| and |disabled_message| and returns true. Otherwise,
// returns false.
virtual bool ParseResponse(
const enterprise_management::DeviceManagementResponse& response,
std::string* restore_mode,
base::Optional<std::string>* management_domain,
base::Optional<std::string>* disabled_message) = 0;
};
namespace {
// Provides device identifier for Forced Re-Enrollment (FRE), where the
// server-backed state key is used.
class DeviceIdentifierProviderFRE
: public AutoEnrollmentClient::DeviceIdentifierProvider {
public:
explicit DeviceIdentifierProviderFRE(
const std::string& server_backed_state_key) {
CHECK(!server_backed_state_key.empty());
server_backed_state_key_hash_ =
crypto::SHA256HashString(server_backed_state_key);
}
EnrollmentCheckType GetEnrollmentCheckType() const override {
return em::DeviceAutoEnrollmentRequest::ENROLLMENT_CHECK_TYPE_FRE;
}
const std::string& GetIdHash() const override {
return server_backed_state_key_hash_;
}
private:
// SHA-256 digest of the stable identifier.
std::string server_backed_state_key_hash_;
};
// Provides device identifier for Forced Initial Enrollment, where the brand
// code and serial number is used.
class DeviceIdentifierProviderInitialEnrollment
: public AutoEnrollmentClient::DeviceIdentifierProvider {
public:
DeviceIdentifierProviderInitialEnrollment(
const std::string& device_serial_number,
const std::string& device_brand_code) {
CHECK(!device_serial_number.empty());
CHECK(!device_brand_code.empty());
// The hash for initial enrollment is the first 8 bytes of
// SHA256(<brnad_code>_<serial_number>).
id_hash_ =
crypto::SHA256HashString(device_brand_code + "_" + device_serial_number)
.substr(0, 8);
}
EnrollmentCheckType GetEnrollmentCheckType() const override {
return em::DeviceAutoEnrollmentRequest::
ENROLLMENT_CHECK_TYPE_FORCED_ENROLLMENT;
}
const std::string& GetIdHash() const override { return id_hash_; }
private:
// 8-byte Hash built from serial number and brand code passed to the
// constructor.
std::string id_hash_;
};
// Handles DeviceStateRetrievalRequest / DeviceStateRetrievalResponse for
// Forced Re-Enrollment (FRE).
class StateDownloadMessageProcessorFRE
: public AutoEnrollmentClient::StateDownloadMessageProcessor {
public:
explicit StateDownloadMessageProcessorFRE(
const std::string& server_backed_state_key)
: server_backed_state_key_(server_backed_state_key) {}
DeviceManagementRequestJob::JobType GetJobType() const override {
return DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL;
}
void FillRequest(em::DeviceManagementRequest* request) override {
request->mutable_device_state_retrieval_request()
->set_server_backed_state_key(server_backed_state_key_);
}
bool ParseResponse(const em::DeviceManagementResponse& response,
std::string* restore_mode,
base::Optional<std::string>* management_domain,
base::Optional<std::string>* disabled_message) override {
if (!response.has_device_state_retrieval_response()) {
LOG(ERROR) << "Server failed to provide auto-enrollment response.";
return false;
}
const em::DeviceStateRetrievalResponse& state_response =
response.device_state_retrieval_response();
*restore_mode = ConvertRestoreMode(state_response.restore_mode());
if (state_response.has_management_domain())
*management_domain = state_response.management_domain();
else
management_domain->reset();
if (state_response.has_disabled_state())
*disabled_message = state_response.disabled_state().message();
else
disabled_message->reset();
// Logging as "WARNING" to make sure it's preserved in the logs.
LOG(WARNING) << "Received restore_mode=" << state_response.restore_mode();
return true;
}
private:
// Stable state key.
std::string server_backed_state_key_;
};
// Handles DeviceInitialEnrollmentStateRequest /
// DeviceInitialEnrollmentStateResponse for Forced Initial Enrollment.
class StateDownloadMessageProcessorInitialEnrollment
: public AutoEnrollmentClient::StateDownloadMessageProcessor {
public:
StateDownloadMessageProcessorInitialEnrollment(
const std::string& device_serial_number,
const std::string& device_brand_code)
: device_serial_number_(device_serial_number),
device_brand_code_(device_brand_code) {}
DeviceManagementRequestJob::JobType GetJobType() const override {
return DeviceManagementRequestJob::TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL;
}
void FillRequest(em::DeviceManagementRequest* request) override {
auto* inner_request =
request->mutable_device_initial_enrollment_state_request();
inner_request->set_brand_code(device_brand_code_);
inner_request->set_serial_number(device_serial_number_);
}
bool ParseResponse(const em::DeviceManagementResponse& response,
std::string* restore_mode,
base::Optional<std::string>* management_domain,
base::Optional<std::string>* disabled_message) override {
if (!response.has_device_initial_enrollment_state_response()) {
LOG(ERROR) << "Server failed to provide initial enrollment response.";
return false;
}
const em::DeviceInitialEnrollmentStateResponse& state_response =
response.device_initial_enrollment_state_response();
if (state_response.has_initial_enrollment_mode()) {
*restore_mode = ConvertInitialEnrollmentMode(
state_response.initial_enrollment_mode());
} else {
// Unknown initial enrollment mode - treat as no enrollment.
*restore_mode = std::string();
}
if (state_response.has_management_domain())
*management_domain = state_response.management_domain();
else
management_domain->reset();
// Device disabling is not supported in initial forced enrollment.
disabled_message->reset();
// Logging as "WARNING" to make sure it's preserved in the logs.
LOG(WARNING) << "Received initial_enrollment_mode="
<< state_response.initial_enrollment_mode();
return true;
}
private:
// Serial number of the device.
std::string device_serial_number_;
// 4-character brand code of the device.
std::string device_brand_code_;
};
} // namespace
// static
std::unique_ptr<AutoEnrollmentClient> AutoEnrollmentClient::CreateForFRE(
const ProgressCallback& progress_callback,
DeviceManagementService* device_management_service,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> system_request_context,
const std::string& server_backed_state_key,
int power_initial,
int power_limit)
: progress_callback_(callback),
state_(AUTO_ENROLLMENT_STATE_IDLE),
has_server_state_(false),
device_state_available_(false),
device_id_(base::GenerateGUID()),
server_backed_state_key_(server_backed_state_key),
current_power_(power_initial),
power_limit_(power_limit),
modulus_updates_received_(0),
device_management_service_(service),
local_state_(local_state),
request_context_(system_request_context) {
DCHECK_LE(current_power_, power_limit_);
DCHECK(!progress_callback_.is_null());
CHECK(!server_backed_state_key_.empty());
server_backed_state_key_hash_ =
crypto::SHA256HashString(server_backed_state_key_);
int power_limit) {
return base::WrapUnique(new AutoEnrollmentClient(
progress_callback, device_management_service, local_state,
system_request_context,
std::make_unique<DeviceIdentifierProviderFRE>(server_backed_state_key),
std::make_unique<StateDownloadMessageProcessorFRE>(
server_backed_state_key),
power_initial, power_limit));
}
// static
std::unique_ptr<AutoEnrollmentClient>
AutoEnrollmentClient::CreateForInitialEnrollment(
const ProgressCallback& progress_callback,
DeviceManagementService* device_management_service,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> system_request_context,
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit) {
return base::WrapUnique(new AutoEnrollmentClient(
progress_callback, device_management_service, local_state,
system_request_context,
std::make_unique<DeviceIdentifierProviderInitialEnrollment>(
device_serial_number, device_brand_code),
std::make_unique<StateDownloadMessageProcessorInitialEnrollment>(
device_serial_number, device_brand_code),
power_initial, power_limit));
}
AutoEnrollmentClient::~AutoEnrollmentClient() {
......@@ -164,6 +413,34 @@ void AutoEnrollmentClient::OnNetworkChanged(
}
}
AutoEnrollmentClient::AutoEnrollmentClient(
const ProgressCallback& callback,
DeviceManagementService* service,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> system_request_context,
std::unique_ptr<DeviceIdentifierProvider> device_identifier_provider,
std::unique_ptr<StateDownloadMessageProcessor>
state_download_message_processor,
int power_initial,
int power_limit)
: progress_callback_(callback),
state_(AUTO_ENROLLMENT_STATE_IDLE),
has_server_state_(false),
device_state_available_(false),
device_id_(base::GenerateGUID()),
current_power_(power_initial),
power_limit_(power_limit),
modulus_updates_received_(0),
device_management_service_(service),
local_state_(local_state),
request_context_(system_request_context),
device_identifier_provider_(std::move(device_identifier_provider)),
state_download_message_processor_(
std::move(state_download_message_processor)) {
DCHECK_LE(current_power_, power_limit_);
DCHECK(!progress_callback_.is_null());
}
bool AutoEnrollmentClient::GetCachedDecision() {
const PrefService::Preference* has_server_state_pref =
local_state_->FindPreference(prefs::kShouldAutoEnroll);
......@@ -241,11 +518,16 @@ void AutoEnrollmentClient::NextStep() {
}
void AutoEnrollmentClient::SendBucketDownloadRequest() {
// Only power-of-2 moduli are supported for now. These are computed by taking
// the lower |current_power_| bits of the hash.
std::string id_hash = device_identifier_provider_->GetIdHash();
// Currently AutoEnrollmentClient supports working with hashes that are at
// least 8 bytes long. If this is reduced, the computation of the remainder
// must also be adapted to handle the case of a shorter hash gracefully.
DCHECK_GE(id_hash.size(), 8u);
uint64_t remainder = 0;
const size_t last_byte_index = id_hash.size() - 1;
for (int i = 0; 8 * i < current_power_; ++i) {
uint64_t byte = server_backed_state_key_hash_[31 - i] & 0xff;
uint64_t byte = id_hash[last_byte_index - i] & 0xff;
remainder = remainder | (byte << (8 * i));
}
remainder = remainder & ((UINT64_C(1) << current_power_) - 1);
......@@ -262,6 +544,8 @@ void AutoEnrollmentClient::SendBucketDownloadRequest() {
request_job_->GetRequest()->mutable_auto_enrollment_request();
request->set_remainder(remainder);
request->set_modulus(INT64_C(1) << current_power_);
request->set_enrollment_check_type(
device_identifier_provider_->GetEnrollmentCheckType());
request_job_->Start(
base::Bind(&AutoEnrollmentClient::HandleRequestCompletion,
base::Unretained(this),
......@@ -271,15 +555,10 @@ void AutoEnrollmentClient::SendBucketDownloadRequest() {
void AutoEnrollmentClient::SendDeviceStateRequest() {
ReportProgress(AUTO_ENROLLMENT_STATE_PENDING);
VLOG(1) << "State request for key: " << server_backed_state_key_;
request_job_.reset(
device_management_service_->CreateJob(
DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL,
request_context_.get()));
request_job_.reset(device_management_service_->CreateJob(
state_download_message_processor_->GetJobType(), request_context_.get()));
request_job_->SetClientID(device_id_);
em::DeviceStateRetrievalRequest* request =
request_job_->GetRequest()->mutable_device_state_retrieval_request();
request->set_server_backed_state_key(server_backed_state_key_);
state_download_message_processor_->FillRequest(request_job_->GetRequest());
request_job_->Start(
base::Bind(&AutoEnrollmentClient::HandleRequestCompletion,
base::Unretained(this),
......@@ -377,45 +656,41 @@ bool AutoEnrollmentClient::OnBucketDownloadRequestCompletion(
bool AutoEnrollmentClient::OnDeviceStateRequestCompletion(
DeviceManagementStatus status,
int net_error,
const enterprise_management::DeviceManagementResponse& response) {
bool progress = false;
if (!response.has_device_state_retrieval_response()) {
LOG(ERROR) << "Server failed to provide auto-enrollment response.";
} else {
const em::DeviceStateRetrievalResponse& state_response =
response.device_state_retrieval_response();
{
DictionaryPrefUpdate dict(local_state_, prefs::kServerBackedDeviceState);
UpdateDict(
dict.Get(), kDeviceStateManagementDomain,
state_response.has_management_domain(),
std::make_unique<base::Value>(state_response.management_domain()));
std::string restore_mode =
ConvertRestoreMode(state_response.restore_mode());
UpdateDict(dict.Get(), kDeviceStateRestoreMode, !restore_mode.empty(),
std::make_unique<base::Value>(restore_mode));
UpdateDict(dict.Get(), kDeviceStateDisabledMessage,
state_response.has_disabled_state(),
std::make_unique<base::Value>(
state_response.disabled_state().message()));
// Logging as "WARNING" to make sure it's preserved in the logs.
LOG(WARNING) << "Received restore_mode=" << state_response.restore_mode();
}
local_state_->CommitPendingWrite();
device_state_available_ = true;
progress = true;
}
const em::DeviceManagementResponse& response) {
std::string restore_mode;
base::Optional<std::string> management_domain;
base::Optional<std::string> disabled_message;
return progress;
bool progress = state_download_message_processor_->ParseResponse(
response, &restore_mode, &management_domain, &disabled_message);
if (!progress)
return false;
{
DictionaryPrefUpdate dict(local_state_, prefs::kServerBackedDeviceState);
UpdateDict(dict.Get(), kDeviceStateManagementDomain,
management_domain.has_value(),
std::make_unique<base::Value>(
management_domain.value_or(std::string())));
UpdateDict(dict.Get(), kDeviceStateRestoreMode, !restore_mode.empty(),
std::make_unique<base::Value>(restore_mode));
UpdateDict(dict.Get(), kDeviceStateDisabledMessage,
disabled_message.has_value(),
std::make_unique<base::Value>(
disabled_message.value_or(std::string())));
}
local_state_->CommitPendingWrite();
device_state_available_ = true;
return true;
}
bool AutoEnrollmentClient::IsIdHashInProtobuf(
const google::protobuf::RepeatedPtrField<std::string>& hashes) {
std::string id_hash = device_identifier_provider_->GetIdHash();
for (int i = 0; i < hashes.size(); ++i) {
if (hashes.Get(i) == server_backed_state_key_hash_)
if (hashes.Get(i) == id_hash)
return true;
}
return false;
......
......@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "net/base/network_change_notifier.h"
......@@ -31,8 +32,8 @@ class URLRequestContextGetter;
namespace policy {
class DeviceManagementRequestJob;
class DeviceManagementService;
class DeviceManagementRequestJob;
// Indicates the current state of the auto-enrollment check. (Numeric values
// are just to make reading of log files easier.)
......@@ -64,15 +65,24 @@ class AutoEnrollmentClient
// and the max is 2^62 (when the moduli are restricted to powers-of-2).
static const int kMaximumPower = 62;
// Subclasses of this class provide an identifier and specify the identifier
// set for the DeviceAutoEnrollmentRequest,
class DeviceIdentifierProvider;
// Subclasses of this class generate the request to download the device state
// (after determining that there is server-side device state) and parse the
// response.
class StateDownloadMessageProcessor;
// Used for signaling progress to a consumer.
typedef base::Callback<void(AutoEnrollmentState)> ProgressCallback;
typedef base::RepeatingCallback<void(AutoEnrollmentState)> ProgressCallback;
// |progress_callback| will be invoked whenever some significant event happens
// as part of the protocol, after Start() is invoked.
// The result of the protocol will be cached in |local_state|.
// |power_initial| and |power_limit| are exponents of power-of-2 values which
// will be the initial modulus and the maximum modulus used by this client.
AutoEnrollmentClient(
static std::unique_ptr<AutoEnrollmentClient> CreateForFRE(
const ProgressCallback& progress_callback,
DeviceManagementService* device_management_service,
PrefService* local_state,
......@@ -80,6 +90,22 @@ class AutoEnrollmentClient
const std::string& server_backed_state_key,
int power_initial,
int power_limit);
// |progress_callback| will be invoked whenever some significant event happens
// as part of the protocol, after Start() is invoked.
// The result of the protocol will be cached in |local_state|.
// |power_initial| and |power_limit| are exponents of power-of-2 values which
// will be the initial modulus and the maximum modulus used by this client.
static std::unique_ptr<AutoEnrollmentClient> CreateForInitialEnrollment(
const ProgressCallback& progress_callback,
DeviceManagementService* device_management_service,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> system_request_context,
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit);
~AutoEnrollmentClient() override;
// Registers preferences in local state.
......@@ -116,6 +142,17 @@ class AutoEnrollmentClient
int,
const enterprise_management::DeviceManagementResponse&);
AutoEnrollmentClient(
const ProgressCallback& progress_callback,
DeviceManagementService* device_management_service,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> system_request_context,
std::unique_ptr<DeviceIdentifierProvider> device_identifier_provider,
std::unique_ptr<StateDownloadMessageProcessor>
state_download_message_processor,
int power_initial,
int power_limit);
// Tries to load the result of a previous execution of the protocol from
// local state. Returns true if that decision has been made and is valid.
bool GetCachedDecision();
......@@ -157,7 +194,8 @@ class AutoEnrollmentClient
int net_error,
const enterprise_management::DeviceManagementResponse& response);
// Returns true if |server_backed_state_key_hash_| is contained in |hashes|.
// Returns true if the identifier hash provided by
// |device_identifier_provider_| is contained in |hashes|.
bool IsIdHashInProtobuf(
const google::protobuf::RepeatedPtrField<std::string>& hashes);
......@@ -181,10 +219,6 @@ class AutoEnrollmentClient
// Randomly generated device id for the auto-enrollment requests.
std::string device_id_;
// Stable state key and its SHA-256 digest.
std::string server_backed_state_key_;
std::string server_backed_state_key_hash_;
// Power-of-2 modulus to try next.
int current_power_;
......@@ -206,6 +240,14 @@ class AutoEnrollmentClient
// The request context to use to perform the auto enrollment request.
scoped_refptr<net::URLRequestContextGetter> request_context_;
// Specifies the identifier set and the hash of the device's current
// identifier.
std::unique_ptr<DeviceIdentifierProvider> device_identifier_provider_;
// Fills and parses state retrieval request / response.
std::unique_ptr<StateDownloadMessageProcessor>
state_download_message_processor_;
// Times used to determine the duration of the protocol, and the extra time
// needed to complete after the signin was complete.
// If |time_start_| is not null, the protocol is still running.
......
......@@ -41,12 +41,22 @@ const char kStateKeyHash[] =
"\xb3\x4a\x5e\xff\x73\x7e\x92\xd9\xf8\x6e\x72\x44\xd0\x97\xc3\xe6";
const char kDisabledMessage[] = "This device has been disabled.";
const char kSerialNumber[] = "SN123456";
const char kBrandCode[] = "AABC";
const char kInitialEnrollmentIdHash[] = "\x30\x18\xb7\x0f\x76\x09\xc5\xc7";
const int kInitialEnrollmentIdHashLength = 8;
using ::testing::InSequence;
using ::testing::Mock;
using ::testing::SaveArg;
using ::testing::_;
class AutoEnrollmentClientTest : public testing::Test {
enum class AutoEnrollmentProtocol { kFRE, kInitialEnrollment };
class AutoEnrollmentClientTest
: public testing::Test,
public ::testing::WithParamInterface<AutoEnrollmentProtocol> {
protected:
AutoEnrollmentClientTest()
: scoped_testing_local_state_(
......@@ -55,7 +65,7 @@ class AutoEnrollmentClientTest : public testing::Test {
state_(AUTO_ENROLLMENT_STATE_PENDING) {}
void SetUp() override {
CreateClient(kStateKey, 4, 8);
CreateClient(4, 8);
ASSERT_FALSE(local_state_->GetUserPref(prefs::kShouldAutoEnroll));
ASSERT_FALSE(local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit));
}
......@@ -65,19 +75,25 @@ class AutoEnrollmentClientTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
void CreateClient(const std::string& state_key,
int power_initial,
int power_limit) {
void CreateClient(int power_initial, int power_limit) {
state_ = AUTO_ENROLLMENT_STATE_PENDING;
service_.reset(new MockDeviceManagementService());
EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _))
.WillRepeatedly(SaveArg<5>(&last_request_));
client_.reset(new AutoEnrollmentClient(
base::Bind(&AutoEnrollmentClientTest::ProgressCallback,
base::Unretained(this)),
service_.get(), local_state_, new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get()),
state_key, power_initial, power_limit));
auto progress_callback = base::BindRepeating(
&AutoEnrollmentClientTest::ProgressCallback, base::Unretained(this));
auto* url_request_context_getter = new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get());
if (GetParam() == AutoEnrollmentProtocol::kFRE) {
client_ = AutoEnrollmentClient::CreateForFRE(
progress_callback, service_.get(), local_state_,
url_request_context_getter, kStateKey, power_initial, power_limit);
} else {
client_ = AutoEnrollmentClient::CreateForInitialEnrollment(
progress_callback, service_.get(), local_state_,
url_request_context_getter, kSerialNumber, kBrandCode, power_initial,
power_limit);
}
}
void ProgressCallback(AutoEnrollmentState state) {
......@@ -100,23 +116,75 @@ class AutoEnrollmentClientTest : public testing::Test {
if (with_hashes) {
for (int i = 0; i < 10; ++i) {
std::string state_key = base::StringPrintf("state_key %d", i);
std::string hash = crypto::SHA256HashString(state_key);
std::string hash_full = crypto::SHA256HashString(state_key);
std::string hash =
GetParam() == AutoEnrollmentProtocol::kFRE
? hash_full
: hash_full.substr(0, kInitialEnrollmentIdHashLength);
enrollment_response->mutable_hash()->Add()->assign(hash);
}
}
if (with_id_hash) {
enrollment_response->mutable_hash()->Add()->assign(kStateKeyHash,
crypto::kSHA256Length);
if (GetParam() == AutoEnrollmentProtocol::kFRE) {
enrollment_response->mutable_hash()->Add()->assign(
kStateKeyHash, crypto::kSHA256Length);
} else {
enrollment_response->mutable_hash()->Add()->assign(
kInitialEnrollmentIdHash, kInitialEnrollmentIdHashLength);
}
}
EXPECT_CALL(*service_,
CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _))
.WillOnce(service_->SucceedJob(response));
}
em::DeviceInitialEnrollmentStateResponse::InitialEnrollmentMode
MapRestoreModeToInitialEnrollmentMode(
em::DeviceStateRetrievalResponse::RestoreMode restore_mode) {
using DeviceStateRetrieval = em::DeviceStateRetrievalResponse;
using DeviceInitialEnrollmentState =
em::DeviceInitialEnrollmentStateResponse;
switch (restore_mode) {
case DeviceStateRetrieval::RESTORE_MODE_NONE:
return DeviceInitialEnrollmentState::INITIAL_ENROLLMENT_MODE_NONE;
case DeviceStateRetrieval::RESTORE_MODE_REENROLLMENT_REQUESTED:
return DeviceInitialEnrollmentState::INITIAL_ENROLLMENT_MODE_NONE;
case DeviceStateRetrieval::RESTORE_MODE_REENROLLMENT_ENFORCED:
return DeviceInitialEnrollmentState::
INITIAL_ENROLLMENT_MODE_ENROLLMENT_ENFORCED;
case DeviceStateRetrieval::RESTORE_MODE_DISABLED:
return DeviceInitialEnrollmentState::INITIAL_ENROLLMENT_MODE_NONE;
case DeviceStateRetrieval::RESTORE_MODE_REENROLLMENT_ZERO_TOUCH:
return DeviceInitialEnrollmentState::INITIAL_ENROLLMENT_MODE_NONE;
}
}
void ServerWillSendState(
const std::string& management_domain,
em::DeviceStateRetrievalResponse::RestoreMode restore_mode,
const std::string& device_disabled_message) {
if (GetParam() == AutoEnrollmentProtocol::kFRE) {
ServerWillSendFREState(management_domain, restore_mode,
device_disabled_message);
} else {
ServerWillSendInitialEnrollmentState(
management_domain,
MapRestoreModeToInitialEnrollmentMode(restore_mode));
}
}
DeviceManagementRequestJob::JobType GetStateRetrievalJobType() {
return GetParam() == AutoEnrollmentProtocol::kFRE
? DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL
: DeviceManagementRequestJob::
TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL;
}
void ServerWillSendFREState(
const std::string& management_domain,
em::DeviceStateRetrievalResponse::RestoreMode restore_mode,
const std::string& device_disabled_message) {
em::DeviceManagementResponse response;
em::DeviceStateRetrievalResponse* state_response =
response.mutable_device_state_retrieval_response();
......@@ -124,9 +192,20 @@ class AutoEnrollmentClientTest : public testing::Test {
state_response->set_management_domain(management_domain);
state_response->mutable_disabled_state()->set_message(
device_disabled_message);
EXPECT_CALL(
*service_,
CreateJob(DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL, _))
EXPECT_CALL(*service_, CreateJob(GetStateRetrievalJobType(), _))
.WillOnce(service_->SucceedJob(response));
}
void ServerWillSendInitialEnrollmentState(
const std::string& management_domain,
em::DeviceInitialEnrollmentStateResponse::InitialEnrollmentMode
initial_enrollment_mode) {
em::DeviceManagementResponse response;
em::DeviceInitialEnrollmentStateResponse* state_response =
response.mutable_device_initial_enrollment_state_response();
state_response->set_initial_enrollment_mode(initial_enrollment_mode);
state_response->set_management_domain(management_domain);
EXPECT_CALL(*service_, CreateJob(GetStateRetrievalJobType(), _))
.WillOnce(service_->SucceedJob(response));
}
......@@ -178,9 +257,14 @@ class AutoEnrollmentClientTest : public testing::Test {
}
std::string actual_disabled_message;
EXPECT_TRUE(state_dict->GetString(kDeviceStateDisabledMessage,
&actual_disabled_message));
EXPECT_EQ(expected_disabled_message, actual_disabled_message);
if (GetParam() == AutoEnrollmentProtocol::kFRE) {
EXPECT_TRUE(state_dict->GetString(kDeviceStateDisabledMessage,
&actual_disabled_message));
EXPECT_EQ(expected_disabled_message, actual_disabled_message);
} else {
EXPECT_FALSE(state_dict->GetString(kDeviceStateDisabledMessage,
&actual_disabled_message));
}
}
const em::DeviceAutoEnrollmentRequest& auto_enrollment_request() {
......@@ -199,7 +283,7 @@ class AutoEnrollmentClientTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientTest);
};
TEST_F(AutoEnrollmentClientTest, NetworkFailure) {
TEST_P(AutoEnrollmentClientTest, NetworkFailure) {
ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
......@@ -207,7 +291,7 @@ TEST_F(AutoEnrollmentClientTest, NetworkFailure) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, EmptyReply) {
TEST_P(AutoEnrollmentClientTest, EmptyReply) {
ServerWillReply(-1, false, false);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
......@@ -215,7 +299,7 @@ TEST_F(AutoEnrollmentClientTest, EmptyReply) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, ClientUploadsRightBits) {
TEST_P(AutoEnrollmentClientTest, ClientUploadsRightBits) {
ServerWillReply(-1, false, false);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
......@@ -223,12 +307,17 @@ TEST_F(AutoEnrollmentClientTest, ClientUploadsRightBits) {
EXPECT_TRUE(auto_enrollment_request().has_remainder());
EXPECT_TRUE(auto_enrollment_request().has_modulus());
EXPECT_EQ(16, auto_enrollment_request().modulus());
EXPECT_EQ(kStateKeyHash[31] & 0xf, auto_enrollment_request().remainder());
if (GetParam() == AutoEnrollmentProtocol::kFRE) {
EXPECT_EQ(kStateKeyHash[31] & 0xf, auto_enrollment_request().remainder());
} else {
EXPECT_EQ(kInitialEnrollmentIdHash[7] & 0xf,
auto_enrollment_request().remainder());
}
VerifyCachedResult(false, 8);
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, AskForMoreThenFail) {
TEST_P(AutoEnrollmentClientTest, AskForMoreThenFail) {
InSequence sequence;
ServerWillReply(32, false, false);
ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
......@@ -238,7 +327,7 @@ TEST_F(AutoEnrollmentClientTest, AskForMoreThenFail) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, AskForMoreThenEvenMore) {
TEST_P(AutoEnrollmentClientTest, AskForMoreThenEvenMore) {
InSequence sequence;
ServerWillReply(32, false, false);
ServerWillReply(64, false, false);
......@@ -248,7 +337,7 @@ TEST_F(AutoEnrollmentClientTest, AskForMoreThenEvenMore) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, AskForLess) {
TEST_P(AutoEnrollmentClientTest, AskForLess) {
InSequence sequence;
ServerWillReply(8, false, false);
ServerWillReply(-1, true, true);
......@@ -264,7 +353,7 @@ TEST_F(AutoEnrollmentClientTest, AskForLess) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, AskForSame) {
TEST_P(AutoEnrollmentClientTest, AskForSame) {
InSequence sequence;
ServerWillReply(16, false, false);
ServerWillReply(-1, true, true);
......@@ -280,7 +369,7 @@ TEST_F(AutoEnrollmentClientTest, AskForSame) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, AskForSameTwice) {
TEST_P(AutoEnrollmentClientTest, AskForSameTwice) {
InSequence sequence;
ServerWillReply(16, false, false);
ServerWillReply(16, false, false);
......@@ -290,7 +379,7 @@ TEST_F(AutoEnrollmentClientTest, AskForSameTwice) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, AskForTooMuch) {
TEST_P(AutoEnrollmentClientTest, AskForTooMuch) {
ServerWillReply(512, false, false);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
......@@ -298,7 +387,7 @@ TEST_F(AutoEnrollmentClientTest, AskForTooMuch) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, AskNonPowerOf2) {
TEST_P(AutoEnrollmentClientTest, AskNonPowerOf2) {
InSequence sequence;
ServerWillReply(100, false, false);
ServerWillReply(-1, false, false);
......@@ -307,12 +396,17 @@ TEST_F(AutoEnrollmentClientTest, AskNonPowerOf2) {
EXPECT_TRUE(auto_enrollment_request().has_remainder());
EXPECT_TRUE(auto_enrollment_request().has_modulus());
EXPECT_EQ(128, auto_enrollment_request().modulus());
EXPECT_EQ(kStateKeyHash[31] & 0x7f, auto_enrollment_request().remainder());
if (GetParam() == AutoEnrollmentProtocol::kFRE) {
EXPECT_EQ(kStateKeyHash[31] & 0x7f, auto_enrollment_request().remainder());
} else {
EXPECT_EQ(kInitialEnrollmentIdHash[7] & 0x7f,
auto_enrollment_request().remainder());
}
VerifyCachedResult(false, 8);
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, ConsumerDevice) {
TEST_P(AutoEnrollmentClientTest, ConsumerDevice) {
ServerWillReply(-1, true, false);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
......@@ -325,7 +419,7 @@ TEST_F(AutoEnrollmentClientTest, ConsumerDevice) {
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
}
TEST_F(AutoEnrollmentClientTest, ForcedReEnrollment) {
TEST_P(AutoEnrollmentClientTest, ForcedReEnrollment) {
ServerWillReply(-1, true, true);
ServerWillSendState(
"example.com",
......@@ -344,7 +438,11 @@ TEST_F(AutoEnrollmentClientTest, ForcedReEnrollment) {
EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
}
TEST_F(AutoEnrollmentClientTest, ForcedReEnrollmentZeroTouch) {
TEST_P(AutoEnrollmentClientTest, ForcedReEnrollmentZeroTouch) {
// Zero-Touch is currently not supported in the initial-enrollment exchange.
if (GetParam() == AutoEnrollmentProtocol::kInitialEnrollment)
return;
ServerWillReply(-1, true, true);
ServerWillSendState(
"example.com",
......@@ -363,7 +461,12 @@ TEST_F(AutoEnrollmentClientTest, ForcedReEnrollmentZeroTouch) {
EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ZERO_TOUCH, state_);
}
TEST_F(AutoEnrollmentClientTest, RequestedReEnrollment) {
TEST_P(AutoEnrollmentClientTest, RequestedReEnrollment) {
// Requesting re-enrollment is currently not supported in the
// initial-enrollment exchange.
if (GetParam() == AutoEnrollmentProtocol::kInitialEnrollment)
return;
ServerWillReply(-1, true, true);
ServerWillSendState(
"example.com",
......@@ -377,12 +480,15 @@ TEST_F(AutoEnrollmentClientTest, RequestedReEnrollment) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, DeviceDisabled) {
TEST_P(AutoEnrollmentClientTest, DeviceDisabled) {
// Disabling is currently not supported in the initial-enrollment exchange.
if (GetParam() == AutoEnrollmentProtocol::kInitialEnrollment)
return;
ServerWillReply(-1, true, true);
ServerWillSendState(
"example.com",
em::DeviceStateRetrievalResponse::RESTORE_MODE_DISABLED,
kDisabledMessage);
ServerWillSendState("example.com",
em::DeviceStateRetrievalResponse::RESTORE_MODE_DISABLED,
kDisabledMessage);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
VerifyCachedResult(true, 8);
......@@ -391,8 +497,8 @@ TEST_F(AutoEnrollmentClientTest, DeviceDisabled) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, NoBitsUploaded) {
CreateClient(kStateKey, 0, 0);
TEST_P(AutoEnrollmentClientTest, NoBitsUploaded) {
CreateClient(0, 0);
ServerWillReply(-1, false, false);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
......@@ -404,10 +510,12 @@ TEST_F(AutoEnrollmentClientTest, NoBitsUploaded) {
EXPECT_FALSE(HasServerBackedState());
}
TEST_F(AutoEnrollmentClientTest, ManyBitsUploaded) {
int64_t bottom62 = INT64_C(0x386e7244d097c3e6);
TEST_P(AutoEnrollmentClientTest, ManyBitsUploaded) {
int64_t bottom62 = GetParam() == AutoEnrollmentProtocol::kFRE
? INT64_C(0x386e7244d097c3e6)
: INT64_C(0x3018b70f7609c5c7);
for (int i = 0; i <= 62; ++i) {
CreateClient(kStateKey, i, i);
CreateClient(i, i);
ServerWillReply(-1, false, false);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
......@@ -421,8 +529,8 @@ TEST_F(AutoEnrollmentClientTest, ManyBitsUploaded) {
}
}
TEST_F(AutoEnrollmentClientTest, MoreThan32BitsUploaded) {
CreateClient(kStateKey, 10, 37);
TEST_P(AutoEnrollmentClientTest, MoreThan32BitsUploaded) {
CreateClient(10, 37);
InSequence sequence;
ServerWillReply(INT64_C(1) << 37, false, false);
ServerWillReply(-1, true, true);
......@@ -438,7 +546,7 @@ TEST_F(AutoEnrollmentClientTest, MoreThan32BitsUploaded) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, ReuseCachedDecision) {
TEST_P(AutoEnrollmentClientTest, ReuseCachedDecision) {
// No bucket download requests should be issued.
EXPECT_CALL(*service_,
CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT, _))
......@@ -463,12 +571,12 @@ TEST_F(AutoEnrollmentClientTest, ReuseCachedDecision) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) {
TEST_P(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) {
local_state_->SetUserPref(prefs::kShouldAutoEnroll,
std::make_unique<base::Value>(false));
local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit,
std::make_unique<base::Value>(8));
CreateClient(kStateKey, 5, 10);
CreateClient(5, 10);
ServerWillReply(-1, true, true);
ServerWillSendState(
"example.com",
......@@ -481,7 +589,7 @@ TEST_F(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) {
TEST_P(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) {
ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
client_->Start();
// Don't invoke the callback if there was a network failure.
......@@ -518,7 +626,7 @@ TEST_F(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) {
kDisabledMessage);
}
TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonWithPendingRequest) {
TEST_P(AutoEnrollmentClientTest, CancelAndDeleteSoonWithPendingRequest) {
MockDeviceManagementJob* job = NULL;
ServerWillReplyAsync(&job);
EXPECT_FALSE(job);
......@@ -539,7 +647,7 @@ TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonWithPendingRequest) {
EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
}
TEST_F(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) {
TEST_P(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) {
MockDeviceManagementJob* job = NULL;
ServerWillReplyAsync(&job);
EXPECT_FALSE(job);
......@@ -569,7 +677,7 @@ TEST_F(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) {
EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
}
TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) {
TEST_P(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) {
ServerWillReply(-1, true, true);
ServerWillSendState(
"example.com",
......@@ -588,7 +696,7 @@ TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) {
EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
}
TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) {
TEST_P(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) {
ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
client_->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
......@@ -600,7 +708,7 @@ TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) {
EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
}
TEST_F(AutoEnrollmentClientTest, NetworkFailureThenRequireUpdatedModulus) {
TEST_P(AutoEnrollmentClientTest, NetworkFailureThenRequireUpdatedModulus) {
// This test verifies that if the first request fails due to a network
// problem then the second request will correctly handle an updated
// modulus request from the server.
......@@ -637,5 +745,13 @@ TEST_F(AutoEnrollmentClientTest, NetworkFailureThenRequireUpdatedModulus) {
Mock::VerifyAndClearExpectations(service_.get());
}
INSTANTIATE_TEST_CASE_P(FRE,
AutoEnrollmentClientTest,
testing::Values(AutoEnrollmentProtocol::kFRE));
INSTANTIATE_TEST_CASE_P(
InitialEnrollment,
AutoEnrollmentClientTest,
testing::Values(AutoEnrollmentProtocol::kInitialEnrollment));
} // namespace
} // namespace policy
......@@ -57,6 +57,8 @@ const char kValueRequestCheckDeviceLicense[] = "check_device_license";
const char kValueRequestAppInstallReport[] = "app_install_report";
const char kValueRequestTokenEnrollment[] = "register_browser";
const char kValueRequestChromeDesktopReport[] = "chrome_desktop_report";
const char kValueRequestInitialEnrollmentStateRetrieval[] =
"device_initial_enrollment_state";
const char kChromeDevicePolicyType[] = "google/chromeos/device";
#if defined(OS_CHROMEOS)
......
......@@ -49,6 +49,7 @@ POLICY_EXPORT extern const char kValueRequestCheckDeviceLicense[];
POLICY_EXPORT extern const char kValueRequestAppInstallReport[];
POLICY_EXPORT extern const char kValueRequestTokenEnrollment[];
POLICY_EXPORT extern const char kValueRequestChromeDesktopReport[];
POLICY_EXPORT extern const char kValueRequestInitialEnrollmentStateRetrieval[];
// Policy type strings for the policy_type field in PolicyFetchRequest.
POLICY_EXPORT extern const char kChromeDevicePolicyType[];
......
......@@ -166,6 +166,8 @@ const char* JobTypeToRequestType(DeviceManagementRequestJob::JobType type) {
return dm_protocol::kValueRequestTokenEnrollment;
case DeviceManagementRequestJob::TYPE_CHROME_DESKTOP_REPORT:
return dm_protocol::kValueRequestChromeDesktopReport;
case DeviceManagementRequestJob::TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL:
return dm_protocol::kValueRequestInitialEnrollmentStateRetrieval;
}
NOTREACHED() << "Invalid job type " << type;
return "";
......
......@@ -66,6 +66,7 @@ class POLICY_EXPORT DeviceManagementRequestJob {
TYPE_UPLOAD_APP_INSTALL_REPORT = 17,
TYPE_TOKEN_ENROLLMENT = 18,
TYPE_CHROME_DESKTOP_REPORT = 19,
TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL = 20,
};
typedef base::Callback<
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment