// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/enterprise/data_protection/print_utils.h"

#include "base/containers/span.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "build/build_config.h"
#include "chrome/browser/enterprise/connectors/analysis/page_print_request_handler.h"
#include "chrome/browser/enterprise/connectors/common.h"
#include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.h"
#include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client_factory.h"
#include "chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.h"
#include "chrome/browser/policy/dm_token_utils.h"
#include "chrome/browser/printing/print_preview_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/enterprise/buildflags/buildflags.h"
#include "components/enterprise/connectors/core/cloud_content_scanning/common.h"
#include "components/enterprise/connectors/core/reporting_constants.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/web_contents_tester.h"
#include "printing/printing_features.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_LINUX)
#include "components/dbus/thread_linux/dbus_thread_linux.h"
#endif

#if BUILDFLAG(ENTERPRISE_LOCAL_CONTENT_ANALYSIS)
#include "chrome/browser/enterprise/connectors/test/fake_content_analysis_sdk_manager.h"  // nogncheck
#endif

namespace enterprise_data_protection {

namespace {

using ContentAnalysisResponse = enterprise_connectors::ContentAnalysisResponse;
using ContentAnalysisDelegate = enterprise_connectors::ContentAnalysisDelegate;
using RealtimeReportingClientFactory =
    enterprise_connectors::RealtimeReportingClientFactory;

ContentAnalysisDelegate* test_delegate_ = nullptr;

constexpr char kDmToken[] = "dm_token";

constexpr char kLocalPolicy[] = R"(
{
  "service_provider": "local_user_agent",
  "block_until_verdict": 1,
  "enable": [
    {
      "url_list": ["*"],
      "tags": ["dlp"]
    }
  ]
})";

constexpr char kCloudPolicy[] = R"(
{
  "service_provider": "google",
  "block_until_verdict": 1,
  "enable": [
    {
      "url_list": ["*"],
      "tags": ["dlp"]
    }
  ]
})";

constexpr char kScanId[] = "scan_id";

constexpr char kTestData[] = "lalilulelo";

constexpr char kPrinterName[] = "my_printer";

constexpr char kUserName[] = "test-user@chromium.org";

constexpr char16_t kUserJustification[] = u"User justification";

scoped_refptr<base::RefCountedMemory> CreateData() {
  return base::MakeRefCounted<base::RefCountedStaticMemory>(
      base::byte_span_from_cstring(kTestData));
}

ContentAnalysisResponse::Result CreateResult(
    ContentAnalysisResponse::Result::TriggeredRule::Action action) {
  ContentAnalysisResponse::Result result;
  result.set_tag("dlp");
  result.set_status(ContentAnalysisResponse::Result::SUCCESS);

  if (action !=
      ContentAnalysisResponse::Result::TriggeredRule::ACTION_UNSPECIFIED) {
    auto* rule = result.add_triggered_rules();
    rule->set_rule_name("print_rule_name");
    rule->set_action(action);
  }
  return result;
}

ContentAnalysisResponse CreateResponse(
    ContentAnalysisResponse::Result::TriggeredRule::Action action) {
  ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* result = response.add_results();
  *result = CreateResult(action);
  return response;
}

class PrintTestContentAnalysisDelegate : public ContentAnalysisDelegate {
 public:
  using ContentAnalysisDelegate::ContentAnalysisDelegate;

  static std::unique_ptr<ContentAnalysisDelegate> Create(
      content::WebContents* contents,
      ContentAnalysisDelegate::Data data,
      ContentAnalysisDelegate::CompletionCallback callback,
      enterprise_connectors::DeepScanAccessPoint access_point) {
    auto delegate = base::WrapUnique(new PrintTestContentAnalysisDelegate(
        contents, std::move(data), std::move(callback), access_point));
    test_delegate_ = delegate.get();
    return delegate;
  }
};

class TestPagePrintRequestHandler
    : public enterprise_connectors::PagePrintRequestHandler {
 public:
  static std::unique_ptr<PagePrintRequestHandler> Create(
      ContentAnalysisResponse::Result::TriggeredRule::Action action,
      enterprise_connectors::ContentAnalysisInfo* content_analysis_info,
      enterprise_connectors::BinaryUploadService* upload_service,
      Profile* profile,
      GURL url,
      const std::string& printer_name,
      const std::string& page_content_type,
      base::ReadOnlySharedMemoryRegion page_region,
      CompletionCallback callback) {
    auto handler = base::WrapUnique(new TestPagePrintRequestHandler(
        content_analysis_info, upload_service, profile, url, printer_name,
        page_content_type, std::move(page_region), std::move(callback)));
    handler->action_ = action;
    return handler;
  }

 protected:
  using PagePrintRequestHandler::PagePrintRequestHandler;

  void UploadForDeepScanning(
      std::unique_ptr<enterprise_connectors::PagePrintAnalysisRequest> request)
      override {
    ASSERT_EQ(request->printer_name(), kPrinterName);
    OnContentAnalysisResponse(
        enterprise_connectors::ScanRequestUploadResult::kSuccess,
        CreateResponse(action_));
  }

 private:
  ContentAnalysisResponse::Result::TriggeredRule::Action action_;
};

class PrintContentAnalysisUtilsTest
    : public PrintPreviewTest,
      public testing::WithParamInterface<const char*> {
 public:
  PrintContentAnalysisUtilsTest()
      : profile_manager_(TestingBrowserProcess::GetGlobal()) {
    ContentAnalysisDelegate::DisableUIForTesting();
  }

  const char* policy_value() const { return GetParam(); }

  void SetUp() override {
    ASSERT_TRUE(profile_manager_.SetUp());
    PrintPreviewTest::SetUp();
    content::WebContentsTester::For(web_contents())->SetTitle(u"New Tab");

    SetDMTokenForTesting(policy::DMToken::CreateValidToken(kDmToken));

    client_ = std::make_unique<policy::MockCloudPolicyClient>();

    RealtimeReportingClientFactory::GetInstance()->SetTestingFactory(
        profile(),
        base::BindRepeating(
            &enterprise_connectors::test::BuildRealtimeReportingClient));

    RealtimeReportingClientFactory::GetForProfile(profile())
        ->SetBrowserCloudPolicyClientForTesting(client_.get());
    identity_test_environment_.MakePrimaryAccountAvailable(
        kUserName, signin::ConsentLevel::kSignin);
    RealtimeReportingClientFactory::GetForProfile(profile())
        ->SetIdentityManagerForTesting(
            identity_test_environment_.identity_manager());

    enterprise_connectors::test::SetAnalysisConnector(
        profile()->GetPrefs(), enterprise_connectors::PRINT, policy_value());
    enterprise_connectors::test::SetOnSecurityEventReporting(
        profile()->GetPrefs(), true);
  }

  void TearDown() override {
    RealtimeReportingClientFactory::GetForProfile(profile())
        ->SetBrowserCloudPolicyClientForTesting(nullptr);
    SetDMTokenForTesting(policy::DMToken::CreateEmptyToken());
    enterprise_connectors::PagePrintRequestHandler::ResetFactoryForTesting();
#if BUILDFLAG(IS_LINUX)
    dbus_thread_linux::ShutdownOnDBusThreadAndBlock();
#endif
    PrintPreviewTest::TearDown();
    profile_manager_.DeleteAllTestingProfiles();
  }

  content::WebContents* contents() { return web_contents(); }

 protected:
  TestingProfileManager profile_manager_;
  base::test::ScopedFeatureList scoped_feature_list_;
  std::unique_ptr<policy::MockCloudPolicyClient> client_;
  signin::IdentityTestEnvironment identity_test_environment_;

#if BUILDFLAG(ENTERPRISE_LOCAL_CONTENT_ANALYSIS)
  // This installs a fake SDK manager that creates fake SDK clients when
  // its GetClient() method is called. This is needed so that calls to
  // ContentAnalysisSdkManager::Get()->GetClient() do not fail.
  enterprise_connectors::FakeContentAnalysisSdkManager sdk_manager_;
#endif
};

}  // namespace

TEST_P(PrintContentAnalysisUtilsTest, GetPrintAnalysisData_BeforeSystemDialog) {
  auto data = GetPrintAnalysisData(contents(),
                                   PrintScanningContext::kBeforeSystemDialog);

  ASSERT_TRUE(data);
  ASSERT_EQ(data->settings.block_until_verdict,
            enterprise_connectors::BlockUntilVerdict::kBlock);
  ASSERT_EQ(data->reason,
            enterprise_connectors::ContentAnalysisRequest::SYSTEM_DIALOG_PRINT);

  ASSERT_EQ(policy_value() == kLocalPolicy,
            data->settings.cloud_or_local_settings.is_local_analysis());
  ASSERT_EQ(policy_value() == kCloudPolicy,
            data->settings.cloud_or_local_settings.is_cloud_analysis());
}

TEST_P(PrintContentAnalysisUtilsTest,
       GetPrintAnalysisData_SystemPrintAfterPreview) {
  auto data = GetPrintAnalysisData(
      contents(), PrintScanningContext::kSystemPrintAfterPreview);

  // This enum value should never return a populated `data` since scanning
  // should either take place before the system dialog with the
  // `kBeforeSystemDialog` context, or right after it with the
  // `kSystemPrintBeforePrintDocument` context.
  ASSERT_FALSE(data);
}

TEST_P(PrintContentAnalysisUtilsTest,
       GetPrintAnalysisData_NormalPrintAfterPreview) {
  auto data = GetPrintAnalysisData(
      contents(), PrintScanningContext::kNormalPrintAfterPreview);

  ASSERT_TRUE(data);
  ASSERT_EQ(data->settings.block_until_verdict,
            enterprise_connectors::BlockUntilVerdict::kBlock);
  ASSERT_EQ(data->reason,
            enterprise_connectors::ContentAnalysisRequest::PRINT_PREVIEW_PRINT);

  ASSERT_EQ(policy_value() == kLocalPolicy,
            data->settings.cloud_or_local_settings.is_local_analysis());
  ASSERT_EQ(policy_value() == kCloudPolicy,
            data->settings.cloud_or_local_settings.is_cloud_analysis());
}

TEST_P(PrintContentAnalysisUtilsTest,
       GetPrintAnalysisData_NormalPrintBeforePrintDocument) {
  auto data = GetPrintAnalysisData(
      contents(), PrintScanningContext::kNormalPrintBeforePrintDocument);

  // This enum value should never return a populated `data` since scanning
  // should either take place before the preview dialog with the
  // `kBeforePreview` context, or right after it with the
  // `kNormalPrintAfterPreview` context.
  ASSERT_FALSE(data);
}

TEST_P(PrintContentAnalysisUtilsTest,
       GetPrintAnalysisData_SystemPrintBeforePrintDocument) {
  auto data = GetPrintAnalysisData(
      contents(), PrintScanningContext::kSystemPrintBeforePrintDocument);

  ASSERT_TRUE(data);
  ASSERT_EQ(data->settings.block_until_verdict,
            enterprise_connectors::BlockUntilVerdict::kBlock);
  ASSERT_EQ(data->reason,
            enterprise_connectors::ContentAnalysisRequest::SYSTEM_DIALOG_PRINT);

  ASSERT_EQ(policy_value() == kLocalPolicy,
            data->settings.cloud_or_local_settings.is_local_analysis());
  ASSERT_EQ(policy_value() == kCloudPolicy,
            data->settings.cloud_or_local_settings.is_cloud_analysis());
}

#if BUILDFLAG(IS_MAC)
TEST_P(PrintContentAnalysisUtilsTest,
       GetPrintAnalysisData_MacOpenPdfInPreview) {
  auto data =
      GetPrintAnalysisData(contents(), PrintScanningContext::kOpenPdfInPreview);

  ASSERT_TRUE(data);
  ASSERT_EQ(data->settings.block_until_verdict,
            enterprise_connectors::BlockUntilVerdict::kBlock);
  ASSERT_EQ(data->reason,
            enterprise_connectors::ContentAnalysisRequest::PRINT_PREVIEW_PRINT);

  ASSERT_EQ(policy_value() == kLocalPolicy,
            data->settings.cloud_or_local_settings.is_local_analysis());
  ASSERT_EQ(policy_value() == kCloudPolicy,
            data->settings.cloud_or_local_settings.is_cloud_analysis());
}
#endif  // BUILDFLAG(IS_MAC)

TEST_P(PrintContentAnalysisUtilsTest, PrintIfAllowedByPolicyAllowed) {
  ContentAnalysisDelegate::SetFactoryForTesting(
      base::BindRepeating(&PrintTestContentAnalysisDelegate::Create));
  enterprise_connectors::PagePrintRequestHandler::SetFactoryForTesting(
      base::BindRepeating(
          &TestPagePrintRequestHandler::Create,
          ContentAnalysisResponse::Result::TriggeredRule::ACTION_UNSPECIFIED));

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  validator.ExpectNoReport();

  auto data = CreateData();
  base::RunLoop run_loop;
  auto on_verdict = base::BindLambdaForTesting([&run_loop](bool allowed) {
    ASSERT_TRUE(allowed);
    run_loop.Quit();
  });

  PrintIfAllowedByPolicy(data, contents(), kPrinterName,
                         PrintScanningContext::kNormalPrintAfterPreview,
                         std::move(on_verdict),
                         /*hide_preview=*/base::DoNothing());
  run_loop.Run();
}

TEST_P(PrintContentAnalysisUtilsTest, PrintIfAllowedByPolicyReportOnly) {
  ContentAnalysisDelegate::SetFactoryForTesting(
      base::BindRepeating(&PrintTestContentAnalysisDelegate::Create));
  enterprise_connectors::PagePrintRequestHandler::SetFactoryForTesting(
      base::BindRepeating(
          &TestPagePrintRequestHandler::Create,
          ContentAnalysisResponse::Result::TriggeredRule::REPORT_ONLY));

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  chrome::cros::reporting::proto::DlpSensitiveDataEvent expected_event;
  expected_event.set_url("");
  expected_event.set_tab_url("");
  expected_event.set_source("");
  expected_event.set_destination(kPrinterName);
  expected_event.set_content_type("");
  expected_event.set_file_name("New Tab");
  expected_event.set_scan_id(kScanId);

  expected_event.set_trigger(
      chrome::cros::reporting::proto::DataTransferEventTrigger::PAGE_PRINT);
  expected_event.set_event_result(
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED);

  chrome::cros::reporting::proto::TriggeredRuleInfo triggered_rule;
  triggered_rule.set_rule_name("print_rule_name");
  triggered_rule.set_action(
      chrome::cros::reporting::proto::TriggeredRuleInfo::REPORT_ONLY);

  *expected_event.add_triggered_rule_info() = triggered_rule;
  expected_event.set_profile_identifier(profile()->GetPath().AsUTF8Unsafe());
  expected_event.set_profile_user_name(kUserName);

  validator.ExpectSensitiveDataEvent(std::move(expected_event));

  auto data = CreateData();
  base::RunLoop run_loop;
  auto on_verdict = base::BindLambdaForTesting([&run_loop](bool allowed) {
    ASSERT_TRUE(allowed);
    run_loop.Quit();
  });

  PrintIfAllowedByPolicy(data, contents(), kPrinterName,
                         PrintScanningContext::kNormalPrintAfterPreview,
                         std::move(on_verdict),
                         /*hide_preview=*/base::DoNothing());
  run_loop.Run();
  validator_run_loop.Run();
}

TEST_P(PrintContentAnalysisUtilsTest, PrintIfAllowedByPolicyWarnThenCancel) {
  ContentAnalysisDelegate::SetFactoryForTesting(
      base::BindRepeating(&PrintTestContentAnalysisDelegate::Create));
  enterprise_connectors::PagePrintRequestHandler::SetFactoryForTesting(
      base::BindRepeating(
          &TestPagePrintRequestHandler::Create,
          ContentAnalysisResponse::Result::TriggeredRule::WARN));

  // The cancel callback is called after the verdict is received.
  enterprise_connectors::ContentAnalysisDelegate::
      SetOnAckAllRequestsCallbackForTesting(base::BindOnce(
          [](const std::map<std::string,
                            enterprise_connectors::
                                ContentAnalysisAcknowledgement::FinalAction>&
                 map) {
            ASSERT_TRUE(test_delegate_);
            test_delegate_->Cancel(/* warning= */ true);
          }));

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  chrome::cros::reporting::proto::DlpSensitiveDataEvent expected_event;
  expected_event.set_url("");
  expected_event.set_tab_url("");
  expected_event.set_source("");
  expected_event.set_destination(kPrinterName);
  expected_event.set_content_type("");
  expected_event.set_file_name("New Tab");
  expected_event.set_scan_id(kScanId);

  expected_event.set_trigger(
      chrome::cros::reporting::proto::DataTransferEventTrigger::PAGE_PRINT);
  expected_event.set_event_result(
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED);

  chrome::cros::reporting::proto::TriggeredRuleInfo triggered_rule;
  triggered_rule.set_rule_name("print_rule_name");
  triggered_rule.set_action(
      chrome::cros::reporting::proto::TriggeredRuleInfo::WARN);

  *expected_event.add_triggered_rule_info() = triggered_rule;
  expected_event.set_profile_identifier(profile()->GetPath().AsUTF8Unsafe());
  expected_event.set_profile_user_name(kUserName);

  validator.ExpectSensitiveDataEvent(std::move(expected_event));

  auto data = CreateData();
  base::RunLoop run_loop;
  auto on_verdict = base::BindLambdaForTesting([&run_loop](bool allowed) {
    ASSERT_FALSE(allowed);
    run_loop.Quit();
  });
  PrintIfAllowedByPolicy(data, contents(), kPrinterName,
                         PrintScanningContext::kNormalPrintAfterPreview,
                         std::move(on_verdict),
                         /*hide_preview=*/base::DoNothing());
  run_loop.Run();
  validator_run_loop.Run();
}

// TODO(http://crbug.com/434099738): Flaky on multiple platforms.
TEST_P(PrintContentAnalysisUtilsTest,
       DISABLED_PrintIfAllowedByPolicyWarnedThenBypass) {
  ContentAnalysisDelegate::SetFactoryForTesting(
      base::BindRepeating(&PrintTestContentAnalysisDelegate::Create));
  enterprise_connectors::PagePrintRequestHandler::SetFactoryForTesting(
      base::BindRepeating(
          &TestPagePrintRequestHandler::Create,
          ContentAnalysisResponse::Result::TriggeredRule::WARN));

  // The bypass callback is called after the verdict is received.
  enterprise_connectors::ContentAnalysisDelegate::
      SetOnAckAllRequestsCallbackForTesting(base::BindOnce(
          [](const std::map<std::string,
                            enterprise_connectors::
                                ContentAnalysisAcknowledgement::FinalAction>&
                 map) {
            ASSERT_TRUE(test_delegate_);
            test_delegate_->SetPageWarningForTesting();
            test_delegate_->BypassWarnings(kUserJustification);
          }));

  base::RunLoop validator_warn_run_loop;
  enterprise_connectors::test::EventReportValidator validator(client_.get());
  validator.SetDoneClosure(validator_warn_run_loop.QuitClosure());
  chrome::cros::reporting::proto::DlpSensitiveDataEvent event_bypass;
  event_bypass.set_destination(kPrinterName);
  event_bypass.set_file_name("New Tab");
  event_bypass.set_trigger(chrome::cros::reporting::proto::PAGE_PRINT);
  event_bypass.set_event_result(
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BYPASSED);
  event_bypass.set_profile_user_name(kUserName);
  event_bypass.set_profile_identifier(profile()->GetPath().AsUTF8Unsafe());
  event_bypass.set_scan_id(kScanId);
  event_bypass.set_user_justification(base::UTF16ToUTF8(kUserJustification));

  chrome::cros::reporting::proto::DlpSensitiveDataEvent event_warn;
  event_warn.set_destination(kPrinterName);
  event_warn.set_file_name("New Tab");
  event_warn.set_trigger(chrome::cros::reporting::proto::PAGE_PRINT);
  event_warn.set_event_result(
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED);
  event_warn.set_profile_user_name(kUserName);
  event_warn.set_profile_identifier(profile()->GetPath().AsUTF8Unsafe());
  event_warn.set_scan_id(kScanId);

  validator.ExpectSensitiveDataEventWarnThenBypass(std::move(event_warn),
                                                   std::move(event_bypass));

  auto data = CreateData();
  base::RunLoop run_loop;
  auto on_verdict = base::BindLambdaForTesting([&run_loop](bool allowed) {
    ASSERT_TRUE(allowed);
    run_loop.Quit();
  });

  PrintIfAllowedByPolicy(data, contents(), kPrinterName,
                         PrintScanningContext::kNormalPrintAfterPreview,
                         std::move(on_verdict),
                         /*hide_preview=*/base::DoNothing());
  run_loop.Run();
  validator_warn_run_loop.Run();
}

TEST_P(PrintContentAnalysisUtilsTest, PrintIfAllowedByPolicyBlocked) {
  ContentAnalysisDelegate::SetFactoryForTesting(
      base::BindRepeating(&PrintTestContentAnalysisDelegate::Create));
  enterprise_connectors::PagePrintRequestHandler::SetFactoryForTesting(
      base::BindRepeating(
          &TestPagePrintRequestHandler::Create,
          ContentAnalysisResponse::Result::TriggeredRule::BLOCK));

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());
  chrome::cros::reporting::proto::DlpSensitiveDataEvent expected_event;
  expected_event.set_url("");
  expected_event.set_tab_url("");
  expected_event.set_source("");
  expected_event.set_destination(kPrinterName);
  expected_event.set_content_type("");
  expected_event.set_file_name("New Tab");
  expected_event.set_scan_id(kScanId);

  expected_event.set_trigger(
      chrome::cros::reporting::proto::DataTransferEventTrigger::PAGE_PRINT);
  expected_event.set_event_result(
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED);

  chrome::cros::reporting::proto::TriggeredRuleInfo triggered_rule;
  triggered_rule.set_rule_name("print_rule_name");
  triggered_rule.set_action(
      chrome::cros::reporting::proto::TriggeredRuleInfo::BLOCK);

  *expected_event.add_triggered_rule_info() = triggered_rule;
  expected_event.set_profile_identifier(profile()->GetPath().AsUTF8Unsafe());
  expected_event.set_profile_user_name(kUserName);

  validator.ExpectSensitiveDataEvent(std::move(expected_event));

  auto data = CreateData();
  base::RunLoop run_loop;
  auto on_verdict = base::BindLambdaForTesting([&run_loop](bool allowed) {
    ASSERT_FALSE(allowed);
    run_loop.Quit();
  });

  PrintIfAllowedByPolicy(data, contents(), kPrinterName,
                         PrintScanningContext::kNormalPrintAfterPreview,
                         std::move(on_verdict),
                         /*hide_preview=*/base::DoNothing());
  validator_run_loop.Run();
  run_loop.Run();
}

TEST_P(PrintContentAnalysisUtilsTest, PrintIfAllowedByPolicyNullInitiator) {
  enterprise_connectors::test::EventReportValidator validator(client_.get());
  validator.ExpectNoReport();

  auto data = CreateData();
  base::test::TestFuture<bool> future;
  PrintIfAllowedByPolicy(data, /*initiator=*/nullptr, kPrinterName,
                         PrintScanningContext::kNormalPrintAfterPreview,
                         future.GetCallback(),
                         /*hide_preview=*/base::DoNothing());
  EXPECT_FALSE(future.Get());
}

INSTANTIATE_TEST_SUITE_P(
    All,
    PrintContentAnalysisUtilsTest,
    /*policy_value=*/testing::Values(kLocalPolicy, kCloudPolicy));

}  // namespace enterprise_data_protection
