| // Copyright 2018 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 <tuple> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/callback_helpers.h" |
| #include "base/files/file_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "base/task/post_task.h" |
| #include "base/task/thread_pool.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "build/branding_buildflags.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chrome_browser_main.h" |
| #include "chrome/browser/chrome_browser_main_extra_parts.h" |
| #include "chrome/browser/net/system_network_context_manager.h" |
| #include "chrome/browser/policy/chrome_browser_policy_connector.h" |
| #include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_result_codes.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/test/base/chrome_test_utils.h" |
| #include "components/enterprise/browser/controller/browser_dm_token_storage.h" |
| #include "components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h" |
| #include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h" |
| #include "components/enterprise/browser/enterprise_switches.h" |
| #include "components/policy/core/common/cloud/chrome_browser_cloud_management_metrics.h" |
| #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
| #include "components/policy/core/common/cloud/cloud_policy_util.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/machine_level_user_cloud_policy_manager.h" |
| #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h" |
| #include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h" |
| #include "components/policy/core/common/cloud/mock_device_management_service.h" |
| #include "components/policy/core/common/policy_switches.h" |
| #include "components/policy/policy_constants.h" |
| #include "components/policy/test_support/client_storage.h" |
| #include "components/policy/test_support/embedded_policy_test_server.h" |
| #include "components/policy/test_support/policy_storage.h" |
| #include "content/public/browser/network_service_instance.h" |
| #include "content/public/test/browser_test.h" |
| #include "google_apis/gaia/gaia_urls.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 "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #if defined(OS_ANDROID) |
| #include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_android.h" |
| #else |
| #include "chrome/browser/device_identity/device_oauth2_token_service.h" |
| #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h" |
| #include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_desktop.h" |
| #include "chrome/browser/ui/browser_finder.h" |
| #endif // defined(OS_ANDROID) |
| |
| #if defined(OS_MAC) |
| #include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_mac_util.h" |
| #endif // defined(OS_MAC) |
| |
| using testing::_; |
| using testing::DoAll; |
| using testing::Invoke; |
| using testing::InvokeWithoutArgs; |
| |
| namespace em = enterprise_management; |
| |
| namespace policy { |
| namespace { |
| |
| constexpr char kEnrollmentToken[] = "enrollment_token"; |
| constexpr char kMachineName[] = "foo"; |
| constexpr char kClientID[] = "fake_client_id"; |
| constexpr char kDMToken[] = "fake_dm_token"; |
| const char kInvalidDMToken[] = "invalid_dm_token"; |
| constexpr char kEnrollmentResultMetrics[] = |
| "Enterprise.MachineLevelUserCloudPolicyEnrollment.Result"; |
| const char kUnenrollmentSuccessMetrics[] = |
| "Enterprise.MachineLevelUserCloudPolicyEnrollment.UnenrollSuccess"; |
| |
| #if defined(OS_ANDROID) |
| typedef ChromeBrowserCloudManagementBrowserTestDelegateAndroid |
| ChromeBrowserCloudManagementBrowserTestDelegateType; |
| #else |
| typedef ChromeBrowserCloudManagementBrowserTestDelegateDesktop |
| ChromeBrowserCloudManagementBrowserTestDelegateType; |
| #endif // defined(OS_ANDROID) |
| |
| void UpdatePolicyStorage(PolicyStorage* policy_storage) { |
| em::CloudPolicySettings settings; |
| em::BooleanPolicyProto* saving_browser_history_disabled = |
| settings.mutable_savingbrowserhistorydisabled(); |
| saving_browser_history_disabled->mutable_policy_options()->set_mode( |
| em::PolicyOptions::MANDATORY); |
| saving_browser_history_disabled->set_value(true); |
| |
| policy_storage->SetPolicyPayload( |
| dm_protocol::kChromeMachineLevelUserCloudPolicyType, |
| settings.SerializeAsString()); |
| policy_storage->SetPolicyPayload( |
| dm_protocol::kChromeMachineLevelUserCloudPolicyAndroidType, |
| settings.SerializeAsString()); |
| policy_storage->set_robot_api_auth_code("fake_auth_code"); |
| policy_storage->set_service_account_identity("foo@bar.com"); |
| } |
| |
| ClientStorage::ClientInfo CreateTestClientInfo() { |
| ClientStorage::ClientInfo client_info; |
| client_info.device_id = kClientID; |
| client_info.device_token = kDMToken; |
| client_info.allowed_policy_types.insert( |
| {dm_protocol::kChromeMachineLevelUserCloudPolicyType, |
| dm_protocol::kChromeMachineLevelUserCloudPolicyAndroidType, |
| dm_protocol::kChromeMachineLevelExtensionCloudPolicyType}); |
| return client_info; |
| } |
| |
| class ChromeBrowserCloudManagementControllerObserver |
| : public ChromeBrowserCloudManagementController::Observer { |
| public: |
| ChromeBrowserCloudManagementControllerObserver( |
| ChromeBrowserCloudManagementBrowserTestDelegate* delegate) |
| : delegate_(delegate) {} |
| ~ChromeBrowserCloudManagementControllerObserver() override = default; |
| |
| void OnPolicyRegisterFinished(bool succeeded) override { |
| delegate_->MaybeCheckDialogClosingAfterPolicyRegistration( |
| !succeeded && should_display_error_message_); |
| EXPECT_EQ(should_succeed_, succeeded); |
| is_finished_ = true; |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->RemoveObserver(this); |
| EXPECT_EQ( |
| delegate_->ExpectManagerImmediatelyInitialized(succeeded), |
| g_browser_process->browser_policy_connector() |
| ->machine_level_user_cloud_policy_manager() |
| ->IsInitializationComplete(PolicyDomain::POLICY_DOMAIN_CHROME)); |
| } |
| |
| void SetShouldSucceed(bool should_succeed) { |
| should_succeed_ = should_succeed; |
| } |
| |
| void SetShouldDisplayErrorMessage(bool should_display) { |
| should_display_error_message_ = should_display; |
| } |
| |
| bool IsFinished() { return is_finished_; } |
| |
| private: |
| raw_ptr<ChromeBrowserCloudManagementBrowserTestDelegate> delegate_; |
| |
| bool is_finished_ = false; |
| bool should_succeed_ = false; |
| bool should_display_error_message_ = false; |
| }; |
| |
| class ChromeBrowserExtraSetUp : public ChromeBrowserMainExtraParts { |
| public: |
| explicit ChromeBrowserExtraSetUp( |
| ChromeBrowserCloudManagementControllerObserver* observer) |
| : observer_(observer) {} |
| ChromeBrowserExtraSetUp(const ChromeBrowserExtraSetUp&) = delete; |
| ChromeBrowserExtraSetUp& operator=(const ChromeBrowserExtraSetUp&) = delete; |
| void PreCreateMainMessageLoop() override { |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->AddObserver(observer_); |
| } |
| |
| private: |
| raw_ptr<ChromeBrowserCloudManagementControllerObserver> observer_; |
| }; |
| |
| // Two observers that quit run_loop when policy is fetched and stored or in case |
| // the core is disconnected in case of error. |
| class PolicyFetchStoreObserver : public CloudPolicyStore::Observer { |
| public: |
| PolicyFetchStoreObserver(CloudPolicyStore* store, |
| base::OnceClosure quit_closure) |
| : store_(store), quit_closure_(std::move(quit_closure)) { |
| store_->AddObserver(this); |
| } |
| PolicyFetchStoreObserver(const PolicyFetchStoreObserver&) = delete; |
| PolicyFetchStoreObserver& operator=(const PolicyFetchStoreObserver&) = delete; |
| ~PolicyFetchStoreObserver() override { store_->RemoveObserver(this); } |
| |
| void OnStoreLoaded(CloudPolicyStore* store) override { |
| std::move(quit_closure_).Run(); |
| } |
| void OnStoreError(CloudPolicyStore* store) override { |
| std::move(quit_closure_).Run(); |
| } |
| |
| private: |
| raw_ptr<CloudPolicyStore> store_; |
| base::OnceClosure quit_closure_; |
| }; |
| |
| class PolicyFetchCoreObserver : public CloudPolicyCore::Observer { |
| public: |
| PolicyFetchCoreObserver(CloudPolicyCore* core, base::OnceClosure quit_closure) |
| : core_(core), quit_closure_(std::move(quit_closure)) { |
| core_->AddObserver(this); |
| } |
| ~PolicyFetchCoreObserver() override { core_->RemoveObserver(this); } |
| |
| void OnCoreConnected(CloudPolicyCore* core) override {} |
| |
| void OnRefreshSchedulerStarted(CloudPolicyCore* core) override {} |
| |
| void OnCoreDisconnecting(CloudPolicyCore* core) override { |
| // This is called when policy fetching fails and is used in |
| // ChromeBrowserCloudManagementController to unenroll the browser. The |
| // status must be DM_STATUS_SERVICE_DEVICE_NOT_FOUND for this to happen. |
| EXPECT_EQ(core->client()->status(), DM_STATUS_SERVICE_DEVICE_NOT_FOUND); |
| std::move(quit_closure_).Run(); |
| } |
| |
| void OnRemoteCommandsServiceStarted(CloudPolicyCore* core) override {} |
| |
| private: |
| raw_ptr<CloudPolicyCore> core_; |
| base::OnceClosure quit_closure_; |
| }; |
| |
| } // namespace |
| |
| class ChromeBrowserCloudManagementServiceIntegrationTest |
| : public PlatformBrowserTest, |
| public testing::WithParamInterface<std::string ( // NOLINT |
| ChromeBrowserCloudManagementServiceIntegrationTest::*)(void)> { |
| public: |
| MOCK_METHOD4(OnJobDone, |
| void(DeviceManagementService::Job*, |
| DeviceManagementStatus, |
| int, |
| const std::string&)); |
| |
| std::string InitTestServer() { |
| StartTestServer(); |
| return test_server_->GetServiceURL().spec(); |
| } |
| |
| protected: |
| void PerformRegistration(const std::string& enrollment_token, |
| const std::string& machine_name, |
| bool expect_success) { |
| base::RunLoop run_loop; |
| if (expect_success) { |
| EXPECT_CALL(*this, OnJobDone(_, testing::Eq(DM_STATUS_SUCCESS), _, _)) |
| .WillOnce(DoAll( |
| Invoke(this, &ChromeBrowserCloudManagementServiceIntegrationTest:: |
| RecordToken), |
| InvokeWithoutArgs(&run_loop, &base::RunLoop::QuitWhenIdle))); |
| } else { |
| EXPECT_CALL(*this, OnJobDone(_, testing::Ne(DM_STATUS_SUCCESS), _, _)) |
| .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::QuitWhenIdle)); |
| } |
| |
| std::unique_ptr<FakeJobConfiguration> config = |
| std::make_unique<FakeJobConfiguration>( |
| service_.get(), |
| DeviceManagementService::JobConfiguration::TYPE_TOKEN_ENROLLMENT, |
| kClientID, |
| /*critical=*/false, |
| !enrollment_token.empty() |
| ? DMAuth::FromEnrollmentToken(enrollment_token) |
| : DMAuth::NoAuth(), |
| /*oauth_token=*/absl::nullopt, |
| g_browser_process->system_network_context_manager() |
| ->GetSharedURLLoaderFactory(), |
| base::BindOnce( |
| &ChromeBrowserCloudManagementServiceIntegrationTest::OnJobDone, |
| base::Unretained(this)), |
| base::DoNothing(), base::DoNothing()); |
| |
| em::DeviceManagementRequest request; |
| em::RegisterBrowserRequest* register_browser_request = |
| request.mutable_register_browser_request(); |
| register_browser_request->set_os_platform(GetOSPlatform()); |
| if (!machine_name.empty()) |
| register_browser_request->set_machine_name(machine_name); |
| std::string payload; |
| ASSERT_TRUE(request.SerializeToString(&payload)); |
| config->SetRequestPayload(payload); |
| |
| std::unique_ptr<DeviceManagementService::Job> job = |
| service_->CreateJob(std::move(config)); |
| |
| run_loop.Run(); |
| } |
| |
| void UploadChromeDesktopReport( |
| const em::ChromeDesktopReportRequest* chrome_desktop_report) { |
| base::RunLoop run_loop; |
| |
| EXPECT_CALL(*this, OnJobDone(_, testing::Eq(DM_STATUS_SUCCESS), _, _)) |
| .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::QuitWhenIdle)); |
| |
| std::unique_ptr<FakeJobConfiguration> config = std::make_unique< |
| FakeJobConfiguration>( |
| service_.get(), |
| DeviceManagementService::JobConfiguration::TYPE_CHROME_DESKTOP_REPORT, |
| kClientID, |
| /*critical=*/false, DMAuth::FromEnrollmentToken(kDMToken), |
| /*oauth_token=*/std::string(), |
| g_browser_process->system_network_context_manager() |
| ->GetSharedURLLoaderFactory(), |
| base::BindOnce( |
| &ChromeBrowserCloudManagementServiceIntegrationTest::OnJobDone, |
| base::Unretained(this)), |
| /* retry_callback */ base::DoNothing(), |
| /* should_retry_callback */ base::DoNothing()); |
| |
| std::unique_ptr<DeviceManagementService::Job> job = |
| service_->CreateJob(std::move(config)); |
| |
| 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); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void TearDownOnMainThread() override { |
| service_.reset(); |
| test_server_.reset(); |
| } |
| |
| void StartTestServer() { |
| test_server_ = std::make_unique<EmbeddedPolicyTestServer>(); |
| 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(); |
| } |
| |
| ChromeBrowserCloudManagementBrowserTestDelegateType delegate_; |
| |
| std::string token_; |
| std::unique_ptr<DeviceManagementService> service_; |
| network::TestURLLoaderFactory test_url_loader_factory_; |
| std::unique_ptr<EmbeddedPolicyTestServer> test_server_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementServiceIntegrationTest, |
| Registration) { |
| ASSERT_TRUE(token_.empty()); |
| PerformRegistration(kEnrollmentToken, kMachineName, /*expect_success=*/true); |
| EXPECT_FALSE(token_.empty()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementServiceIntegrationTest, |
| RegistrationNoEnrollmentToken) { |
| ASSERT_TRUE(token_.empty()); |
| PerformRegistration(std::string(), kMachineName, /*expect_success=*/false); |
| EXPECT_TRUE(token_.empty()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementServiceIntegrationTest, |
| RegistrationNoMachineName) { |
| ASSERT_TRUE(token_.empty()); |
| bool expect_success = delegate_.AcceptEmptyMachineNameOnBrowserRegistration(); |
| PerformRegistration(kEnrollmentToken, std::string(), expect_success); |
| EXPECT_NE(token_.empty(), expect_success); |
| } |
| |
| #if defined(OS_ANDROID) |
| // TODO(http://crbug.com/1091438): Enable this test on Android once reporting is |
| // implemented. |
| #define MAYBE_ChromeDesktopReport DISABLED_ChromeDesktopReport |
| #else |
| #define MAYBE_ChromeDesktopReport ChromeDesktopReport |
| #endif // defined(OS_ANDROID) |
| IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementServiceIntegrationTest, |
| MAYBE_ChromeDesktopReport) { |
| em::ChromeDesktopReportRequest chrome_desktop_report; |
| UploadChromeDesktopReport(&chrome_desktop_report); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| ChromeBrowserCloudManagementServiceIntegrationTestInstance, |
| ChromeBrowserCloudManagementServiceIntegrationTest, |
| testing::Values( |
| &ChromeBrowserCloudManagementServiceIntegrationTest::InitTestServer)); |
| |
| class CloudPolicyStoreObserverStub : public CloudPolicyStore::Observer { |
| public: |
| CloudPolicyStoreObserverStub() = default; |
| CloudPolicyStoreObserverStub(const CloudPolicyStoreObserverStub&) = delete; |
| CloudPolicyStoreObserverStub& operator=(const CloudPolicyStoreObserverStub&) = |
| delete; |
| |
| bool was_called() const { return on_loaded_ || on_error_; } |
| |
| private: |
| // CloudPolicyStore::Observer |
| void OnStoreLoaded(CloudPolicyStore* store) override { on_loaded_ = true; } |
| void OnStoreError(CloudPolicyStore* store) override { on_error_ = true; } |
| |
| bool on_loaded_ = false; |
| bool on_error_ = false; |
| }; |
| |
| class MachineLevelUserCloudPolicyManagerTest : public PlatformBrowserTest { |
| protected: |
| int CreateAndInitManager(const std::string& dm_token) { |
| base::ScopedAllowBlockingForTesting scope_for_testing; |
| std::string client_id("client_id"); |
| base::FilePath user_data_dir; |
| CombinedSchemaRegistry schema_registry; |
| CloudPolicyStoreObserverStub observer; |
| |
| base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); |
| DMToken browser_dm_token = |
| dm_token.empty() ? DMToken::CreateEmptyTokenForTesting() |
| : DMToken::CreateValidTokenForTesting(dm_token); |
| std::unique_ptr<MachineLevelUserCloudPolicyStore> policy_store = |
| MachineLevelUserCloudPolicyStore::Create( |
| browser_dm_token, client_id, base::FilePath(), user_data_dir, |
| base::ThreadPool::CreateSequencedTaskRunner( |
| {base::MayBlock(), base::TaskPriority::BEST_EFFORT})); |
| policy_store->AddObserver(&observer); |
| |
| base::FilePath policy_dir = user_data_dir.Append( |
| ChromeBrowserCloudManagementController::kPolicyDir); |
| |
| std::unique_ptr<MachineLevelUserCloudPolicyManager> manager = |
| std::make_unique<MachineLevelUserCloudPolicyManager>( |
| std::move(policy_store), nullptr, policy_dir, |
| base::ThreadTaskRunnerHandle::Get(), |
| base::BindRepeating(&content::GetNetworkConnectionTracker)); |
| manager->Init(&schema_registry); |
| |
| manager->store()->RemoveObserver(&observer); |
| manager->Shutdown(); |
| return observer.was_called(); |
| } |
| |
| ChromeBrowserCloudManagementBrowserTestDelegateType delegate_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyManagerTest, NoDmToken) { |
| EXPECT_EQ(CreateAndInitManager(std::string()), |
| delegate_.ExpectOnStoreEventFired()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyManagerTest, WithDmToken) { |
| EXPECT_TRUE(CreateAndInitManager("dummy_dm_token")); |
| } |
| |
| class ChromeBrowserCloudManagementEnrollmentTest |
| : public PlatformBrowserTest, |
| public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> { |
| public: |
| ChromeBrowserCloudManagementEnrollmentTest() : observer_(&delegate_) { |
| BrowserDMTokenStorage::SetForTesting(&storage_); |
| storage_.SetEnrollmentToken(enrollment_token()); |
| storage_.SetClientId("client_id"); |
| storage_.EnableStorage(storage_enabled()); |
| storage_.SetEnrollmentErrorOption(should_display_error_message()); |
| |
| observer_.SetShouldSucceed(is_enrollment_token_valid()); |
| observer_.SetShouldDisplayErrorMessage(should_display_error_message()); |
| |
| if (!is_enrollment_token_valid() && should_display_error_message()) { |
| set_expected_exit_code( |
| chrome::RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED); |
| } |
| } |
| |
| ChromeBrowserCloudManagementEnrollmentTest( |
| const ChromeBrowserCloudManagementEnrollmentTest&) = delete; |
| ChromeBrowserCloudManagementEnrollmentTest& operator=( |
| const ChromeBrowserCloudManagementEnrollmentTest&) = delete; |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| ASSERT_TRUE(test_server_.Start()); |
| |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, |
| test_server_.GetServiceURL().spec()); |
| ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); |
| |
| histogram_tester_.ExpectTotalCount(kEnrollmentResultMetrics, 0); |
| } |
| |
| #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| void SetUpDefaultCommandLine(base::CommandLine* command_line) override { |
| PlatformBrowserTest::SetUpDefaultCommandLine(command_line); |
| command_line->AppendSwitch(::switches::kEnableChromeBrowserCloudManagement); |
| } |
| #endif |
| |
| void TearDownInProcessBrowserTestFixture() override { |
| // Test body is skipped if enrollment failed as Chrome quit early. |
| // Verify the enrollment result in the tear down instead. |
| if (!is_enrollment_token_valid()) { |
| VerifyEnrollmentResult(); |
| } |
| } |
| |
| void CreatedBrowserMainParts(content::BrowserMainParts* parts) override { |
| static_cast<ChromeBrowserMainParts*>(parts)->AddParts( |
| std::make_unique<ChromeBrowserExtraSetUp>(&observer_)); |
| } |
| |
| void VerifyEnrollmentResult() { |
| DMToken dm_token = BrowserDMTokenStorage::Get()->RetrieveDMToken(); |
| if (is_enrollment_token_valid()) { |
| EXPECT_TRUE(dm_token.is_valid()); |
| EXPECT_EQ(kFakeDeviceToken, dm_token.value()); |
| } else { |
| EXPECT_TRUE(dm_token.is_empty()); |
| } |
| |
| // Verify the enrollment result. |
| ChromeBrowserCloudManagementEnrollmentResult expected_result; |
| if (is_enrollment_token_valid() && storage_enabled()) { |
| expected_result = ChromeBrowserCloudManagementEnrollmentResult::kSuccess; |
| } else if (is_enrollment_token_valid() && !storage_enabled()) { |
| expected_result = |
| ChromeBrowserCloudManagementEnrollmentResult::kFailedToStore; |
| } else { |
| expected_result = |
| ChromeBrowserCloudManagementEnrollmentResult::kFailedToFetch; |
| } |
| |
| // Verify the metrics. |
| histogram_tester_.ExpectBucketCount(kEnrollmentResultMetrics, |
| expected_result, 1); |
| histogram_tester_.ExpectTotalCount(kEnrollmentResultMetrics, 1); |
| } |
| |
| protected: |
| bool is_enrollment_token_valid() const { return std::get<0>(GetParam()); } |
| bool storage_enabled() const { return std::get<1>(GetParam()); } |
| bool should_display_error_message() const { return std::get<2>(GetParam()); } |
| std::string enrollment_token() const { |
| return is_enrollment_token_valid() ? kEnrollmentToken |
| : kInvalidEnrollmentToken; |
| } |
| |
| ChromeBrowserCloudManagementBrowserTestDelegateType delegate_; |
| |
| base::HistogramTester histogram_tester_; |
| |
| private: |
| EmbeddedPolicyTestServer test_server_; |
| FakeBrowserDMTokenStorage storage_; |
| ChromeBrowserCloudManagementControllerObserver observer_; |
| }; |
| |
| // Consistently timing out on Windows. http://crbug.com/1025220 |
| #if defined(OS_WIN) |
| #define MAYBE_Test DISABLED_Test |
| #else |
| #define MAYBE_Test Test |
| #endif |
| IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementEnrollmentTest, MAYBE_Test) { |
| #undef MAYBE_Test |
| // Test body is run only if enrollment is succeeded or failed without error |
| // message. |
| EXPECT_TRUE(is_enrollment_token_valid() || !should_display_error_message()); |
| |
| delegate_.MaybeWaitForEnrollmentConfirmation(enrollment_token()); |
| |
| delegate_.MaybeCheckTotalBrowserCount(1u); |
| |
| VerifyEnrollmentResult(); |
| #if defined(OS_MAC) |
| // Verify the last mericis of launch is recorded in |
| // applicationDidFinishNotification. |
| EXPECT_EQ(1u, histogram_tester_ |
| .GetAllSamples("Startup.OSX.DockIconWillFinishBouncing") |
| .size()); |
| #endif |
| } |
| |
| #if defined(OS_ANDROID) |
| // No need to run this test with |should_display_error_message| equals true on |
| // Android. |
| INSTANTIATE_TEST_SUITE_P( |
| ChromeBrowserCloudManagementEnrollmentTest, |
| ChromeBrowserCloudManagementEnrollmentTest, |
| ::testing::Combine( |
| ::testing::Bool(), |
| ::testing::Bool(), |
| /*should_display_error_message=*/::testing::Values(false))); |
| #else |
| INSTANTIATE_TEST_SUITE_P(ChromeBrowserCloudManagementEnrollmentTest, |
| ChromeBrowserCloudManagementEnrollmentTest, |
| ::testing::Combine(::testing::Bool(), |
| ::testing::Bool(), |
| ::testing::Bool())); |
| #endif // defined(OS_ANDROID) |
| |
| class MachineLevelUserCloudPolicyPolicyFetchObserver |
| : public ChromeBrowserCloudManagementControllerObserver { |
| public: |
| MachineLevelUserCloudPolicyPolicyFetchObserver( |
| ChromeBrowserCloudManagementBrowserTestDelegate* delegate) |
| : ChromeBrowserCloudManagementControllerObserver(delegate) {} |
| ~MachineLevelUserCloudPolicyPolicyFetchObserver() override = default; |
| |
| void QuitOnUnenroll(base::RepeatingClosure quit_closure) { |
| quit_closure_ = std::move(quit_closure); |
| } |
| |
| void OnBrowserUnenrolled(bool succeeded) override { |
| if (!quit_closure_.is_null()) { |
| EXPECT_FALSE(succeeded); |
| std::move(quit_closure_).Run(); |
| } |
| } |
| |
| private: |
| base::RepeatingClosure quit_closure_; |
| }; |
| |
| class MachineLevelUserCloudPolicyPolicyFetchTest |
| : public PlatformBrowserTest, |
| public ::testing::WithParamInterface<std::tuple<std::string, bool>> { |
| public: |
| MachineLevelUserCloudPolicyPolicyFetchTest() : observer_(&delegate_) { |
| BrowserDMTokenStorage::SetForTesting(&storage_); |
| storage_.SetEnrollmentToken(kEnrollmentToken); |
| storage_.SetClientId(kClientID); |
| storage_.EnableStorage(storage_enabled()); |
| if (!dm_token().empty()) |
| storage_.SetDMToken(dm_token()); |
| } |
| MachineLevelUserCloudPolicyPolicyFetchTest( |
| const MachineLevelUserCloudPolicyPolicyFetchTest&) = delete; |
| MachineLevelUserCloudPolicyPolicyFetchTest& operator=( |
| const MachineLevelUserCloudPolicyPolicyFetchTest&) = delete; |
| |
| void SetUpOnMainThread() override { |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->AddObserver(&observer_); |
| } |
| |
| void TearDownOnMainThread() override { |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->RemoveObserver(&observer_); |
| } |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| SetUpTestServer(); |
| ASSERT_TRUE(test_server_->Start()); |
| |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, |
| test_server_->GetServiceURL().spec()); |
| ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); |
| } |
| |
| #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| void SetUpDefaultCommandLine(base::CommandLine* command_line) override { |
| PlatformBrowserTest::SetUpDefaultCommandLine(command_line); |
| command_line->AppendSwitch(::switches::kEnableChromeBrowserCloudManagement); |
| } |
| #endif |
| |
| void SetUpTestServer() { |
| test_server_ = std::make_unique<EmbeddedPolicyTestServer>(); |
| UpdatePolicyStorage(test_server_->policy_storage()); |
| test_server_->client_storage()->RegisterClient(CreateTestClientInfo()); |
| } |
| |
| DMToken retrieve_dm_token() { return storage_.RetrieveDMToken(); } |
| |
| const std::string dm_token() const { return std::get<0>(GetParam()); } |
| bool storage_enabled() const { return std::get<1>(GetParam()); } |
| |
| protected: |
| ChromeBrowserCloudManagementBrowserTestDelegateType delegate_; |
| |
| MachineLevelUserCloudPolicyPolicyFetchObserver observer_; |
| |
| base::HistogramTester histogram_tester_; |
| |
| private: |
| std::unique_ptr<EmbeddedPolicyTestServer> test_server_; |
| FakeBrowserDMTokenStorage storage_; |
| base::ScopedTempDir temp_dir_; |
| }; |
| |
| #if defined(OS_ANDROID) |
| // Flaky on android-pie-x86-rel. https://crbug.com/1235367 |
| IN_PROC_BROWSER_TEST_P(MachineLevelUserCloudPolicyPolicyFetchTest, |
| DISABLED_Test) { |
| #else |
| IN_PROC_BROWSER_TEST_P(MachineLevelUserCloudPolicyPolicyFetchTest, Test) { |
| #endif // defined(OS_ANDROID) |
| MachineLevelUserCloudPolicyManager* manager = |
| g_browser_process->browser_policy_connector() |
| ->machine_level_user_cloud_policy_manager(); |
| ASSERT_TRUE(manager); |
| // If the policy hasn't been updated, wait for it. |
| if (manager->core()->client()->last_policy_timestamp().is_null()) { |
| base::RunLoop run_loop; |
| // Listen to store event which is fired after policy validation if token is |
| // valid. Otherwise listen to the core since it gets disconnected by |
| // unenrollment. |
| std::unique_ptr<PolicyFetchCoreObserver> core_observer; |
| std::unique_ptr<PolicyFetchStoreObserver> store_observer; |
| if (dm_token() == kInvalidDMToken) { |
| if (storage_enabled()) { |
| // |run_loop|'s QuitClosure will be called after the core is |
| // disconnected following unenrollment. |
| core_observer = std::make_unique<PolicyFetchCoreObserver>( |
| manager->core(), run_loop.QuitClosure()); |
| } else { |
| // |run_loop|'s QuitClosure will be called after the browser attempts to |
| // unenroll from CBCM. This is necessary to quit the loop in the case |
| // the storage fails since the core is not disconnected. |
| observer_.QuitOnUnenroll(run_loop.QuitClosure()); |
| } |
| } else { |
| store_observer = std::make_unique<PolicyFetchStoreObserver>( |
| manager->store(), run_loop.QuitClosure()); |
| } |
| g_browser_process->browser_policy_connector() |
| ->device_management_service() |
| ->ScheduleInitialization(0); |
| run_loop.Run(); |
| } |
| EXPECT_TRUE( |
| manager->IsInitializationComplete(PolicyDomain::POLICY_DOMAIN_CHROME)); |
| |
| const PolicyMap& policy_map = manager->store()->policy_map(); |
| if (dm_token() != kInvalidDMToken) { |
| EXPECT_EQ(1u, policy_map.size()); |
| EXPECT_EQ(base::Value(true), |
| *(policy_map.Get(key::kSavingBrowserHistoryDisabled)->value())); |
| |
| // The token in storage should be valid. |
| DMToken token = retrieve_dm_token(); |
| EXPECT_TRUE(token.is_valid()); |
| |
| // The test server will register with kFakeDeviceToken if |
| // Chrome is started without a DM token. |
| if (dm_token().empty()) |
| EXPECT_EQ(token.value(), kFakeDeviceToken); |
| else |
| EXPECT_EQ(token.value(), kDMToken); |
| |
| histogram_tester_.ExpectTotalCount(kUnenrollmentSuccessMetrics, 0); |
| } else { |
| EXPECT_EQ(0u, policy_map.size()); |
| |
| // The token in storage should be invalid. |
| DMToken token = retrieve_dm_token(); |
| EXPECT_TRUE(token.is_invalid()); |
| |
| histogram_tester_.ExpectUniqueSample(kUnenrollmentSuccessMetrics, |
| storage_enabled(), 1); |
| } |
| } |
| |
| // The tests here cover three DM token cases combined with the storage |
| // succeeding or failing: |
| // 1) Start Chrome with a valid DM token but no policy cache. Chrome will |
| // load the policy from the DM server. |
| // 2) Start Chrome with an invalid DM token. Chrome will hit the DM server and |
| // get an error. There should be no more cloud policy applied. |
| // 3) Start Chrome without DM token. Chrome will register itself and fetch |
| // policy after it. |
| INSTANTIATE_TEST_SUITE_P( |
| MachineLevelUserCloudPolicyPolicyFetchTest, |
| MachineLevelUserCloudPolicyPolicyFetchTest, |
| ::testing::Combine(::testing::Values(kDMToken, kInvalidDMToken, ""), |
| ::testing::Bool())); |
| |
| #if !defined(OS_ANDROID) |
| class MachineLevelUserCloudPolicyRobotAuthTest : public PlatformBrowserTest { |
| public: |
| MachineLevelUserCloudPolicyRobotAuthTest() : observer_(&delegate_) { |
| BrowserDMTokenStorage::SetForTesting(&storage_); |
| storage_.SetEnrollmentToken(kEnrollmentToken); |
| storage_.SetClientId(kClientID); |
| storage_.EnableStorage(true); |
| storage_.SetDMToken(kDMToken); |
| } |
| |
| void SetUpOnMainThread() override { |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->AddObserver(&observer_); |
| test_url_loader_factory_.AddResponse( |
| GaiaUrls::GetInstance()->oauth2_token_url().spec(), |
| R"P({ |
| "access_token":"at", |
| "refresh_token":"rt", |
| "expires_in":9999 |
| })P"); |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->SetGaiaURLLoaderFactory( |
| test_url_loader_factory_.GetSafeWeakWrapper()); |
| } |
| |
| void TearDownOnMainThread() override { |
| g_browser_process->browser_policy_connector() |
| ->chrome_browser_cloud_management_controller() |
| ->RemoveObserver(&observer_); |
| } |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| SetUpTestServer(); |
| ASSERT_TRUE(test_server_->Start()); |
| |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, |
| test_server_->GetServiceURL().spec()); |
| ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); |
| } |
| |
| #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| void SetUpDefaultCommandLine(base::CommandLine* command_line) override { |
| PlatformBrowserTest::SetUpDefaultCommandLine(command_line); |
| command_line->AppendSwitch(::switches::kEnableChromeBrowserCloudManagement); |
| } |
| #endif |
| |
| void SetUpTestServer() { |
| test_server_ = std::make_unique<EmbeddedPolicyTestServer>(); |
| UpdatePolicyStorage(test_server_->policy_storage()); |
| test_server_->client_storage()->RegisterClient(CreateTestClientInfo()); |
| } |
| |
| DMToken retrieve_dm_token() { return storage_.RetrieveDMToken(); } |
| |
| private: |
| ChromeBrowserCloudManagementBrowserTestDelegateType delegate_; |
| std::unique_ptr<EmbeddedPolicyTestServer> test_server_; |
| FakeBrowserDMTokenStorage storage_; |
| base::ScopedTempDir temp_dir_; |
| network::TestURLLoaderFactory test_url_loader_factory_; |
| ChromeBrowserCloudManagementControllerObserver observer_; |
| }; // namespace policy |
| |
| // Flaky on linux & win: https://crbug.com/1105167 |
| #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \ |
| defined(OS_MAC) |
| #define MAYBE_Test DISABLED_Test |
| #else |
| #define MAYBE_Test Test |
| #endif |
| IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyRobotAuthTest, MAYBE_Test) { |
| MachineLevelUserCloudPolicyManager* manager = |
| g_browser_process->browser_policy_connector() |
| ->machine_level_user_cloud_policy_manager(); |
| ASSERT_TRUE(manager); |
| // If the policy hasn't been updated, wait for it. |
| if (manager->core()->client()->last_policy_timestamp().is_null()) { |
| base::RunLoop run_loop; |
| // Listen to store event which is fired after policy validation if token is |
| // valid. |
| auto store_observer = std::make_unique<PolicyFetchStoreObserver>( |
| manager->store(), run_loop.QuitClosure()); |
| |
| g_browser_process->browser_policy_connector() |
| ->device_management_service() |
| ->ScheduleInitialization(0); |
| run_loop.Run(); |
| } |
| EXPECT_TRUE( |
| manager->IsInitializationComplete(PolicyDomain::POLICY_DOMAIN_CHROME)); |
| |
| const PolicyMap& policy_map = manager->store()->policy_map(); |
| |
| EXPECT_EQ(1u, policy_map.size()); |
| EXPECT_EQ(base::Value(true), |
| *(policy_map.Get(key::kSavingBrowserHistoryDisabled)->value())); |
| |
| // The token in storage should be valid. |
| DMToken token = retrieve_dm_token(); |
| EXPECT_TRUE(token.is_valid()); |
| |
| // The test server will register with kFakeDeviceToken if |
| // Chrome is started without a DM token. |
| EXPECT_EQ(token.value(), kDMToken); |
| |
| base::RunLoop run_loop; |
| DeviceOAuth2TokenServiceFactory::Get()->SetRefreshTokenAvailableCallback( |
| run_loop.QuitClosure()); |
| run_loop.Run(); |
| EXPECT_TRUE( |
| DeviceOAuth2TokenServiceFactory::Get()->RefreshTokenIsAvailable()); |
| } |
| #endif // !defined(OS_ANDROID) |
| |
| } // namespace policy |