blob: b8e5bb043e602702002b2acc6a0c48ad71473065 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <memory>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/device_management_service.h"
#include "components/policy/core/common/cloud/dm_auth.h"
#include "components/policy/core/common/cloud/mock_device_management_service.h"
#include "components/policy/test_support/local_policy_test_server.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
using testing::DoAll;
using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::_;
namespace em = enterprise_management;
namespace policy {
namespace {
const char kClientID[] = "testid";
const char kDMToken[] = "fake_token";
// Parses the DeviceManagementRequest in |request_data| and writes a serialized
// DeviceManagementResponse to |response_data|.
void ConstructResponse(const std::string& request_data,
std::string* response_data) {
em::DeviceManagementRequest request;
ASSERT_TRUE(request.ParseFromString(request_data));
em::DeviceManagementResponse response;
if (request.has_register_request()) {
response.mutable_register_response()->set_device_management_token(kDMToken);
} else if (request.has_service_api_access_request()) {
response.mutable_service_api_access_response()->set_auth_code(
"fake_auth_code");
} else if (request.has_unregister_request()) {
response.mutable_unregister_response();
} else if (request.has_policy_request()) {
response.mutable_policy_response()->add_responses();
} else if (request.has_auto_enrollment_request()) {
response.mutable_auto_enrollment_response();
} else if (request.has_app_install_report_request()) {
response.mutable_app_install_report_response();
} else {
FAIL() << "Failed to parse request.";
}
ASSERT_TRUE(response.SerializeToString(response_data));
}
void OnRequest(network::TestURLLoaderFactory* test_factory,
const network::ResourceRequest& request) {
std::string upload_data(network::GetUploadData(request));
if (upload_data.empty())
return;
std::string response_data;
ConstructResponse(upload_data, &response_data);
test_factory->AddResponse(request.url.spec(), response_data);
}
} // namespace
class DeviceManagementServiceIntegrationTest
: public InProcessBrowserTest,
public testing::WithParamInterface<
std::string (DeviceManagementServiceIntegrationTest::*)(void)> {
public:
MOCK_METHOD4(OnJobDone,
void(DeviceManagementService::Job*,
DeviceManagementStatus,
int,
const std::string&));
std::string InitCannedResponse() {
test_url_loader_factory_ =
std::make_unique<network::TestURLLoaderFactory>();
test_shared_loader_factory_ =
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
test_url_loader_factory_.get());
test_url_loader_factory_->SetInterceptor(
base::BindRepeating(&OnRequest, test_url_loader_factory_.get()));
return "http://localhost";
}
std::string InitTestServer() {
StartTestServer();
return test_server_->GetServiceURL().spec();
}
void RecordAuthCode(DeviceManagementService::Job* job,
DeviceManagementStatus code,
int net_error,
const std::string& response_body) {
em::DeviceManagementResponse response;
ASSERT_TRUE(response.ParseFromString(response_body));
robot_auth_code_ = response.service_api_access_response().auth_code();
}
protected:
scoped_refptr<network::SharedURLLoaderFactory> GetFactory() {
return test_shared_loader_factory_
? test_shared_loader_factory_
: g_browser_process->system_network_context_manager()
->GetSharedURLLoaderFactory();
}
std::unique_ptr<DeviceManagementService::Job> StartJob(
DeviceManagementService::JobConfiguration::JobType type,
bool critical,
DMAuth auth_data,
absl::optional<std::string> oauth_token,
const em::DeviceManagementRequest request) {
std::string payload;
request.SerializeToString(&payload);
std::unique_ptr<FakeJobConfiguration> config =
std::make_unique<FakeJobConfiguration>(
service_.get(), type, kClientID, critical, std::move(auth_data),
oauth_token, GetFactory(),
base::BindOnce(&DeviceManagementServiceIntegrationTest::OnJobDone,
base::Unretained(this)),
base::DoNothing(), base::DoNothing());
config->SetRequestPayload(payload);
return service_->CreateJob(std::move(config));
}
void PerformRegistration() {
base::RunLoop run_loop;
EXPECT_CALL(*this, OnJobDone(_, DM_STATUS_SUCCESS, _, _))
.WillOnce(DoAll(
Invoke(this, &DeviceManagementServiceIntegrationTest::RecordToken),
InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)));
em::DeviceManagementRequest request;
request.mutable_register_request();
std::unique_ptr<DeviceManagementService::Job> job =
StartJob(DeviceManagementService::JobConfiguration::TYPE_REGISTRATION,
false, DMAuth::NoAuth(), "oauth_token", request);
run_loop.Run();
}
void SetUpOnMainThread() override {
std::string service_url((this->*(GetParam()))());
service_ = std::make_unique<DeviceManagementService>(
std::unique_ptr<DeviceManagementService::Configuration>(
new MockDeviceManagementServiceConfiguration(service_url)));
service_->ScheduleInitialization(0);
}
void TearDownOnMainThread() override {
service_.reset();
test_server_.reset();
}
void StartTestServer() {
test_server_ = std::make_unique<LocalPolicyTestServer>(
"chrome/test/data/policy/"
"policy_device_management_service_browsertest.json");
ASSERT_TRUE(test_server_->Start());
}
void RecordToken(DeviceManagementService::Job* job,
DeviceManagementStatus code,
int net_error,
const std::string& response_body) {
em::DeviceManagementResponse response;
ASSERT_TRUE(response.ParseFromString(response_body));
token_ = response.register_response().device_management_token();
}
std::string token_;
std::string robot_auth_code_;
std::unique_ptr<DeviceManagementService> service_;
std::unique_ptr<LocalPolicyTestServer> test_server_;
std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
};
#if BUILDFLAG(IS_CHROMEOS)
// Very flaky on ChromeOS: https://crbug.com/1262952
#define MAYBE_Registration DISABLED_Registration
#else
#define MAYBE_Registration Registration
#endif
IN_PROC_BROWSER_TEST_P(DeviceManagementServiceIntegrationTest,
MAYBE_Registration) {
PerformRegistration();
EXPECT_FALSE(token_.empty());
}
IN_PROC_BROWSER_TEST_P(DeviceManagementServiceIntegrationTest,
ApiAuthCodeFetch) {
PerformRegistration();
base::RunLoop run_loop;
EXPECT_CALL(*this, OnJobDone(_, DM_STATUS_SUCCESS, _, _))
.WillOnce(DoAll(
Invoke(this, &DeviceManagementServiceIntegrationTest::RecordAuthCode),
InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)));
em::DeviceManagementRequest request;
em::DeviceServiceApiAccessRequest* device_request =
request.mutable_service_api_access_request();
device_request->add_auth_scopes("authScope4Test");
device_request->set_oauth2_client_id("oauth2ClientId4Test");
std::unique_ptr<DeviceManagementService::Job> job = StartJob(
DeviceManagementService::JobConfiguration::TYPE_API_AUTH_CODE_FETCH,
false, DMAuth::FromDMToken(token_), "", request);
run_loop.Run();
ASSERT_EQ("fake_auth_code", robot_auth_code_);
}
// TODO(crbug.com/1254962): flaky on Mac builders
#if BUILDFLAG(IS_MAC)
#define MAYBE_PolicyFetch DISABLED_PolicyFetch
#else
#define MAYBE_PolicyFetch PolicyFetch
#endif
IN_PROC_BROWSER_TEST_P(DeviceManagementServiceIntegrationTest,
MAYBE_PolicyFetch) {
PerformRegistration();
base::RunLoop run_loop;
EXPECT_CALL(*this, OnJobDone(_, DM_STATUS_SUCCESS, _, _))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
em::DeviceManagementRequest request;
request.mutable_policy_request()->add_requests()->set_policy_type(
dm_protocol::kChromeUserPolicyType);
std::unique_ptr<DeviceManagementService::Job> job =
StartJob(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH,
false, DMAuth::FromDMToken(token_), "", request);
run_loop.Run();
}
#if BUILDFLAG(IS_MAC)
// Flaky on Mac: https://crbug.com/1254962
#define MAYBE_Unregistration DISABLED_Unregistration
#else
#define MAYBE_Unregistration Unregistration
#endif
IN_PROC_BROWSER_TEST_P(DeviceManagementServiceIntegrationTest,
MAYBE_Unregistration) {
PerformRegistration();
base::RunLoop run_loop;
EXPECT_CALL(*this, OnJobDone(_, DM_STATUS_SUCCESS, _, _))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
em::DeviceManagementRequest request;
request.mutable_unregister_request();
std::unique_ptr<DeviceManagementService::Job> job =
StartJob(DeviceManagementService::JobConfiguration::TYPE_UNREGISTRATION,
false, DMAuth::FromDMToken(token_), "", request);
run_loop.Run();
}
#if BUILDFLAG(IS_MAC)
// Flaky on Mac: https://crbug.com/1254962
#define MAYBE_AutoEnrollment DISABLED_AutoEnrollment
#else
#define MAYBE_AutoEnrollment AutoEnrollment
#endif
IN_PROC_BROWSER_TEST_P(DeviceManagementServiceIntegrationTest,
MAYBE_AutoEnrollment) {
base::RunLoop run_loop;
EXPECT_CALL(*this, OnJobDone(_, DM_STATUS_SUCCESS, _, _))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
em::DeviceManagementRequest request;
request.mutable_auto_enrollment_request()->set_remainder(0);
request.mutable_auto_enrollment_request()->set_modulus(1);
std::unique_ptr<DeviceManagementService::Job> job =
StartJob(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
false, DMAuth::NoAuth(), "", request);
run_loop.Run();
}
INSTANTIATE_TEST_SUITE_P(
DeviceManagementServiceIntegrationTestInstance,
DeviceManagementServiceIntegrationTest,
testing::Values(&DeviceManagementServiceIntegrationTest::InitCannedResponse,
&DeviceManagementServiceIntegrationTest::InitTestServer));
} // namespace policy