chromium/chrome/browser/ash/policy/dlp/dlp_content_manager_ash_unittest.cc

// Copyright 2020 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/ash/policy/dlp/dlp_content_manager_ash.h"

#include <memory>
#include <optional>
#include <string_view>

#include "ash/public/cpp/privacy_screen_dlp_helper.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/task/thread_pool.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/policy/dlp/dialogs/dlp_warn_dialog.h"
#include "chrome/browser/chromeos/policy/dlp/dialogs/dlp_warn_notifier.h"
#include "chrome/browser/chromeos/policy/dlp/dialogs/mock_dlp_warn_notifier.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
#include "chrome/browser/chromeos/policy/dlp/test/dlp_content_manager_test_helper.h"
#include "chrome/browser/chromeos/policy/dlp/test/mock_dlp_rules_manager.h"
#include "chrome/browser/enterprise/data_controls/dlp_reporting_manager.h"
#include "chrome/browser/enterprise/data_controls/dlp_reporting_manager_test_helper.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/policy/messaging_layer/public/report_client_test_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/screenshot_area.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/enterprise/data_controls/core/browser/dlp_histogram_helper.h"
#include "components/enterprise/data_controls/core/browser/dlp_policy_event.pb.h"
#include "components/reporting/client/mock_report_queue.h"
#include "components/reporting/storage/test_storage_module.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::Mock;

namespace policy {

namespace {

constexpr char kEmailId[] = "[email protected]";
constexpr char kGaiaId[] = "12345";
constexpr char kSrcPattern[] = "example";
constexpr char kRuleName[] = "ruleName";
constexpr char kRuleId[] = "obfuscatedId";
const std::u16string kApplicationName = u"application";
const DlpRulesManager::RuleMetadata kRuleMetadata(kRuleName, kRuleId);

const DlpContentRestrictionSet kScreenshotRestricted(
    DlpContentRestriction::kScreenshot,
    DlpRulesManager::Level::kBlock);
const DlpContentRestrictionSet kPrivacyScreenEnforced(
    DlpContentRestriction::kPrivacyScreen,
    DlpRulesManager::Level::kBlock);
const DlpContentRestrictionSet kPrivacyScreenReported(
    DlpContentRestriction::kPrivacyScreen,
    DlpRulesManager::Level::kReport);
const DlpContentRestrictionSet kPrintingRestricted(
    DlpContentRestriction::kPrint,
    DlpRulesManager::Level::kBlock);
const DlpContentRestrictionSet kScreenShareRestricted(
    DlpContentRestriction::kScreenShare,
    DlpRulesManager::Level::kBlock);

const DlpContentRestrictionSet kPrintingWarned(DlpContentRestriction::kPrint,
                                               DlpRulesManager::Level::kWarn);
const DlpContentRestrictionSet kScreenshotWarned(
    DlpContentRestriction::kScreenshot,
    DlpRulesManager::Level::kWarn);
const DlpContentRestrictionSet kScreenShareWarned(
    DlpContentRestriction::kScreenShare,
    DlpRulesManager::Level::kWarn);

const DlpContentRestrictionSet kScreenshotReported(
    DlpContentRestriction::kScreenshot,
    DlpRulesManager::Level::kReport);

const DlpContentRestrictionSet kEmptyRestrictionSet;
const DlpContentRestrictionSet kNonEmptyRestrictionSet = kScreenshotRestricted;

class MockPrivacyScreenHelper : public ash::PrivacyScreenDlpHelper {
 public:
  MOCK_METHOD(bool, IsSupported, (), (const, override));
  MOCK_METHOD(void, SetEnforced, (bool enforced), (override));
};

}  // namespace

using MockWarningCallback =
    testing::StrictMock<base::MockCallback<WarningCallback>>;

class DlpContentManagerAshTest : public testing::Test {
 public:
  DlpContentManagerAshTest(const DlpContentManagerAshTest&) = delete;
  DlpContentManagerAshTest& operator=(const DlpContentManagerAshTest&) = delete;

  std::unique_ptr<KeyedService> SetDlpRulesManager(
      content::BrowserContext* context) {
    auto dlp_rules_manager = std::make_unique<MockDlpRulesManager>(
        Profile::FromBrowserContext(context));
    mock_rules_manager_ = dlp_rules_manager.get();
    return dlp_rules_manager;
  }

  MockDlpWarnNotifier* CreateAndSetDlpWarnNotifier(bool should_proceed) {
    std::unique_ptr<MockDlpWarnNotifier> wrapper =
        std::make_unique<MockDlpWarnNotifier>(should_proceed);
    MockDlpWarnNotifier* mock_dlp_warn_notifier = wrapper.get();
    helper_.SetWarnNotifierForTesting(std::move(wrapper));
    return mock_dlp_warn_notifier;
  }

  // Checks that there is an expected number of blocked/not blocked and
  // warned/not warned data points. Number of not blocked and not warned data
  // points is the difference between |total_count| and |blocked_count| and
  // |warned_count| respectfully.
  void VerifyHistogramCounts(int blocked_count,
                             int warned_count,
                             int total_count,
                             std::string blocked_suffix,
                             std::string warned_suffix) {
    histogram_tester_.ExpectBucketCount(
        data_controls::GetDlpHistogramPrefix() + blocked_suffix, true,
        blocked_count);
    histogram_tester_.ExpectBucketCount(
        data_controls::GetDlpHistogramPrefix() + blocked_suffix, false,
        total_count - blocked_count);
    histogram_tester_.ExpectBucketCount(
        data_controls::GetDlpHistogramPrefix() + warned_suffix, true,
        warned_count);
    histogram_tester_.ExpectBucketCount(
        data_controls::GetDlpHistogramPrefix() + warned_suffix, false,
        total_count - warned_count);
  }

 protected:
  DlpContentManagerAshTest()
      : profile_manager_(TestingBrowserProcess::GetGlobal()),
        user_manager_(new ash::FakeChromeUserManager()),
        scoped_user_manager_(base::WrapUnique(user_manager_.get())) {}
  ~DlpContentManagerAshTest() override = default;

  std::unique_ptr<content::WebContents> CreateWebContents() {
    auto web_contents =
        content::WebContentsTester::CreateTestWebContents(profile_, nullptr);
    // `DlpContentTabHelper` is responsible for clearing a destroyed
    // `WebContents` from `DlpContentManager`'s list of `WebContents`;
    // instantiate it here to make sure that cleanup happens even in unit
    // tests.
    DlpContentTabHelper::MaybeCreateForWebContents(web_contents.get());
    CHECK(DlpContentTabHelper::FromWebContents(web_contents.get()));
    return web_contents;
  }

  void SetUp() override {
    testing::Test::SetUp();

    ASSERT_TRUE(profile_manager_.SetUp());
    LoginFakeUser();
    SetReportQueueForReportingManager();
    SetupDlpRulesManager();

    EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
        .WillRepeatedly(::testing::Return(true));
  }

  void TearDown() override {
    testing::Test::TearDown();

    helper_.ResetWarnNotifierForTesting();
  }

  void SetReportQueueForReportingManager() {
    auto report_queue = std::unique_ptr<::reporting::MockReportQueue,
                                        base::OnTaskRunnerDeleter>(
        new ::reporting::MockReportQueue(),
        base::OnTaskRunnerDeleter(
            base::ThreadPool::CreateSequencedTaskRunner({})));
    EXPECT_CALL(*report_queue.get(), AddRecord)
        .WillRepeatedly(
            [this](std::string_view record, ::reporting::Priority priority,
                   ::reporting::ReportQueue::EnqueueCallback callback) {
              DlpPolicyEvent event;
              event.ParseFromString(std::string(record));
              // Don't use this code in a multithreaded env as it can course
              // concurrency issues with the events in the vector.
              events_.push_back(event);
            });
    helper_.GetReportingManager()->SetReportQueueForTest(
        std::move(report_queue));
  }

  void SetupDlpRulesManager() {
    DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
        profile(),
        base::BindRepeating(&DlpContentManagerAshTest::SetDlpRulesManager,
                            base::Unretained(this)));
    ASSERT_TRUE(DlpRulesManagerFactory::GetForPrimaryProfile());
  }

  DlpContentManagerAsh* GetManager() {
    return static_cast<DlpContentManagerAsh*>(helper_.GetContentManager());
  }

  TestingProfile* profile() { return profile_; }

  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  std::unique_ptr<::reporting::ReportingClient::TestEnvironment>
      test_reporting_ = ::reporting::ReportingClient::TestEnvironment::
          CreateWithStorageModule(
              base::MakeRefCounted<::reporting::test::TestStorageModule>());
  DlpContentManagerTestHelper helper_;
  base::HistogramTester histogram_tester_;
  std::vector<DlpPolicyEvent> events_;
  raw_ptr<MockDlpRulesManager, DanglingUntriaged> mock_rules_manager_ = nullptr;
  MockPrivacyScreenHelper mock_privacy_screen_helper_;

 private:
  void LoginFakeUser() {
    AccountId account_id = AccountId::FromUserEmailGaiaId(kEmailId, kGaiaId);

    profile_ = profile_manager_.CreateTestingProfile(account_id.GetUserEmail());
    profile_->SetIsNewProfile(true);

    user_manager_->AddUserWithAffiliationAndTypeAndProfile(
        account_id, false /*is_affiliated*/, user_manager::UserType::kRegular,
        profile_);
    user_manager_->LoginUser(account_id, true /*set_profile_created_flag*/);

    EXPECT_EQ(ProfileManager::GetActiveUserProfile(), profile_);
  }

  content::RenderViewHostTestEnabler rvh_test_enabler_;
  TestingProfileManager profile_manager_;
  raw_ptr<TestingProfile> profile_;
  raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_;
  user_manager::ScopedUserManager scoped_user_manager_;
};

TEST_F(DlpContentManagerAshTest, NoConfidentialDataShown) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);
}

TEST_F(DlpContentManagerAshTest, ConfidentialDataShown) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  helper_.ChangeConfidentiality(web_contents.get(), kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kNonEmptyRestrictionSet);

  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);
}

TEST_F(DlpContentManagerAshTest, ConfidentialDataVisibilityChanged) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  helper_.ChangeConfidentiality(web_contents.get(), kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kNonEmptyRestrictionSet);

  web_contents->WasHidden();
  helper_.ChangeVisibility(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  web_contents->WasShown();
  helper_.ChangeVisibility(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kNonEmptyRestrictionSet);

  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);
}

TEST_F(DlpContentManagerAshTest,
       TwoWebContentsVisibilityAndConfidentialityChanged) {
  std::unique_ptr<content::WebContents> web_contents1 = CreateWebContents();
  std::unique_ptr<content::WebContents> web_contents2 = CreateWebContents();
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  // WebContents 1 becomes confidential.
  helper_.ChangeConfidentiality(web_contents1.get(), kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kNonEmptyRestrictionSet);

  web_contents2->WasHidden();
  helper_.ChangeVisibility(web_contents2.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kNonEmptyRestrictionSet);

  // WebContents 1 becomes non-confidential.
  helper_.ChangeConfidentiality(web_contents1.get(), kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  // WebContents 2 becomes confidential.
  helper_.ChangeConfidentiality(web_contents2.get(), kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  web_contents2->WasShown();
  helper_.ChangeVisibility(web_contents2.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kNonEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kNonEmptyRestrictionSet);

  helper_.DestroyWebContents(web_contents1.get());
  helper_.DestroyWebContents(web_contents2.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);
}

TEST_F(DlpContentManagerAshTest, PrivacyScreenEnforcement) {
  const std::string src_pattern("example.com");
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern(_, _, _, _))
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(src_pattern)));
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(testing::_)).Times(0);
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  testing::Mock::VerifyAndClearExpectations(&mock_privacy_screen_helper_);
  EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
      .WillRepeatedly(::testing::Return(true));
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(true)).Times(1);
  helper_.ChangeConfidentiality(web_contents.get(), kPrivacyScreenEnforced);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      true, 1);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      false, 0);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          src_pattern, DlpRulesManager::Restriction::kPrivacyScreen, kRuleName,
          kRuleId, DlpRulesManager::Level::kBlock)));

  testing::Mock::VerifyAndClearExpectations(&mock_privacy_screen_helper_);
  EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
      .WillRepeatedly(::testing::Return(true));
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(false)).Times(1);
  web_contents->WasHidden();
  helper_.ChangeVisibility(web_contents.get());
  task_environment_.FastForwardBy(helper_.GetPrivacyScreenOffDelay());
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      true, 1);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      false, 1);
  EXPECT_EQ(events_.size(), 1u);

  testing::Mock::VerifyAndClearExpectations(&mock_privacy_screen_helper_);
  EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
      .WillRepeatedly(::testing::Return(true));
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(true)).Times(1);
  web_contents->WasShown();
  helper_.ChangeVisibility(web_contents.get());
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      true, 2);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      false, 1);
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          src_pattern, DlpRulesManager::Restriction::kPrivacyScreen, kRuleName,
          kRuleId, DlpRulesManager::Level::kBlock)));

  testing::Mock::VerifyAndClearExpectations(&mock_privacy_screen_helper_);
  EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
      .WillRepeatedly(::testing::Return(true));
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(false)).Times(1);
  helper_.DestroyWebContents(web_contents.get());
  task_environment_.FastForwardBy(helper_.GetPrivacyScreenOffDelay());
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      true, 2);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      false, 2);
  EXPECT_EQ(events_.size(), 2u);
}

TEST_F(DlpContentManagerAshTest, PrivacyScreenReported) {
  const std::string src_pattern("example.com");
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern(_, _, _, _))
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(src_pattern)));

  // Privacy screen should never be enforced.
  EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
      .WillRepeatedly(::testing::Return(true));
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(testing::_)).Times(0);
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  helper_.ChangeConfidentiality(web_contents.get(), kPrivacyScreenReported);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          src_pattern, DlpRulesManager::Restriction::kPrivacyScreen, kRuleName,
          kRuleId, DlpRulesManager::Level::kReport)));

  web_contents->WasHidden();
  helper_.ChangeVisibility(web_contents.get());
  task_environment_.FastForwardBy(helper_.GetPrivacyScreenOffDelay());
  EXPECT_EQ(events_.size(), 1u);

  web_contents->WasShown();
  helper_.ChangeVisibility(web_contents.get());
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          src_pattern, DlpRulesManager::Restriction::kPrivacyScreen, kRuleName,
          kRuleId, DlpRulesManager::Level::kReport)));

  helper_.DestroyWebContents(web_contents.get());
  task_environment_.FastForwardBy(helper_.GetPrivacyScreenOffDelay());
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      true, 0);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrivacyScreenEnforcedUMA,
      false, 0);
  EXPECT_EQ(events_.size(), 2u);
}

TEST_F(DlpContentManagerAshTest,
       PrivacyScreenNotEnforcedAndReportedOnUnsupportedDevice) {
  const std::string src_pattern("example.com");
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern(_, _, _, _))
      .WillRepeatedly(::testing::Return(src_pattern));

  EXPECT_CALL(mock_privacy_screen_helper_, IsSupported())
      .WillRepeatedly(::testing::Return(false));

  // Privacy screen should never be enforced or reported.
  EXPECT_CALL(mock_privacy_screen_helper_, SetEnforced(testing::_)).Times(0);
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  helper_.ChangeConfidentiality(web_contents.get(), kPrivacyScreenEnforced);
  EXPECT_EQ(events_.size(), 0u);

  web_contents->WasHidden();
  helper_.ChangeVisibility(web_contents.get());
  task_environment_.FastForwardBy(helper_.GetPrivacyScreenOffDelay());
  EXPECT_EQ(events_.size(), 0u);

  web_contents->WasShown();
  helper_.ChangeVisibility(web_contents.get());
  EXPECT_EQ(events_.size(), 0u);

  helper_.DestroyWebContents(web_contents.get());
}

TEST_F(DlpContentManagerAshTest, VideoCaptureReportDuringRecording) {
  const GURL kSrcUrl = GURL("https://example.com/");
  const GURL kGoogleUrl = GURL("https://google.com/");
  // Return |kSrcPattern| for reporting for both |kSrcUrl| and |kGoogleUrl|.
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(2)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  // Setup two web contents with different urls.
  std::unique_ptr<content::WebContents> web_contents1 = CreateWebContents();
  content::WebContentsTester::For(web_contents1.get())
      ->NavigateAndCommit(kSrcUrl);
  std::unique_ptr<content::WebContents> web_contents2 = CreateWebContents();
  content::WebContentsTester::For(web_contents2.get())
      ->NavigateAndCommit(kGoogleUrl);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);

  // WebContents 1 becomes confidential. No reporting expected.
  helper_.ChangeConfidentiality(web_contents1.get(), kScreenshotReported);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kScreenshotReported);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kScreenshotReported);
  EXPECT_TRUE(events_.empty());

  // Simulate starting video capture. Expect report event from WebContents 1.
  const ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
  GetManager()->OnVideoCaptureStarted(area);
  ASSERT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          web_contents1->GetLastCommittedURL().spec(),
          DlpRulesManager::Restriction::kScreenshot, kRuleName, kRuleId,
          DlpRulesManager::Level::kReport)));

  // WebContents 2 becomes confidential. Expect report event from WebContents 2.
  helper_.ChangeConfidentiality(web_contents1.get(), kEmptyRestrictionSet);
  helper_.ChangeConfidentiality(web_contents2.get(), kScreenshotReported);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kScreenshotReported);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kScreenshotReported);
  ASSERT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          web_contents2->GetLastCommittedURL().spec(),
          DlpRulesManager::Restriction::kScreenshot, kRuleName, kRuleId,
          DlpRulesManager::Level::kReport)));

  // Remove confidentiality for both web contents.
  helper_.ChangeConfidentiality(web_contents2.get(), kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kEmptyRestrictionSet);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kEmptyRestrictionSet);
  EXPECT_EQ(events_.size(), 2u);

  // Both web contents become confidential. Expect no reporting event because
  // both urls were already reported during the current capture.
  helper_.ChangeConfidentiality(web_contents1.get(), kScreenshotReported);
  helper_.ChangeConfidentiality(web_contents2.get(), kScreenshotReported);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents1.get()),
            kScreenshotReported);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents2.get()),
            kScreenshotReported);
  EXPECT_EQ(GetManager()->GetOnScreenPresentRestrictions(),
            kScreenshotReported);
  EXPECT_EQ(events_.size(), 2u);

  GetManager()->CheckStoppedVideoCapture(base::DoNothing());
  EXPECT_EQ(events_.size(), 2u);

  // Remove confidentiality to avoid race condition in test case
  // deinitialization.
  helper_.ChangeConfidentiality(web_contents1.get(), kEmptyRestrictionSet);
  helper_.ChangeConfidentiality(web_contents2.get(), kEmptyRestrictionSet);
}

TEST_F(DlpContentManagerAshTest, PrintingRestricted) {
  // Needs to be set because CheckPrintingRestriction() will show the blocked
  // notification.
  NotificationDisplayServiceTester display_service_tester(profile());
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(true)).Times(1);   // No restrictions.
  EXPECT_CALL(cb, Run(false)).Times(1);  // Block restriction.
  EXPECT_CALL(cb, Run(true)).Times(1);   // WebContents destroyed.

  // No restrictions are enforced for web_contents: allow.
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  content::GlobalRenderFrameHostId rfh_id =
      web_contents->GetPrimaryMainFrame()->GetGlobalId();
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/0,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);

  // Block restriction is enforced for web_contents: block.
  helper_.ChangeConfidentiality(web_contents.get(), kPrintingRestricted);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kPrintingRestricted);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);

  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kPrinting, kRuleName,
          kRuleId, DlpRulesManager::Level::kBlock)));

  // Web contents are destroyed: allow.
  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/3,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
}

TEST_F(DlpContentManagerAshTest, PrintingWarnedProceeded) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/true);
  // The warning should be shown only once.
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(1);
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(3)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  EXPECT_CALL(cb, Run(true)).Times(3);

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  content::GlobalRenderFrameHostId rfh_id =
      web_contents->GetPrimaryMainFrame()->GetGlobalId();

  // Warn restriction is enforced: allow and remember that the user proceeded.
  helper_.ChangeConfidentiality(web_contents.get(), kPrintingWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kPrintingWarned);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());

  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kPrinting, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(CreateDlpPolicyWarningProceededEvent(
          kSrcPattern, DlpRulesManager::Restriction::kPrinting, kRuleName,
          kRuleId)));
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrintingWarnProceededUMA,
      true, 1);

  // Check again: allow based on cached user's response - no dialog is shown.
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());

  EXPECT_EQ(events_.size(), 3u);
  EXPECT_THAT(
      events_[2],
      data_controls::IsDlpPolicyEvent(CreateDlpPolicyWarningProceededEvent(
          kSrcPattern, DlpRulesManager::Restriction::kPrinting, kRuleName,
          kRuleId)));
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrintingWarnProceededUMA,
      true, 1);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrintingWarnSilentProceededUMA,
      true, 1);

  // Web contents are destroyed: allow, no dialog is shown.
  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());

  EXPECT_EQ(events_.size(), 3u);
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/3,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
}

TEST_F(DlpContentManagerAshTest, PrintingWarnedCancelled) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/false);
  // If the user cancels, the warning can be shown again for the same contents.
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(2);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(2)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(false)).Times(2);  // Action canceled after the warning.
  EXPECT_CALL(cb, Run(true)).Times(1);   // WebContents destroyed.

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  content::GlobalRenderFrameHostId rfh_id =
      web_contents->GetPrimaryMainFrame()->GetGlobalId();

  // Warn restriction is enforced: reject since the user canceled.
  helper_.ChangeConfidentiality(web_contents.get(), kPrintingWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kPrintingWarned);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kPrinting, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrintingWarnProceededUMA,
      false, 1);

  // Check again: since the user previously cancelled, dialog is shown again.
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kPrinting, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kPrintingWarnProceededUMA,
      false, 2);

  // Web contents are destroyed: allow, no dialog is shown.
  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckPrintingRestriction(web_contents.get(), rfh_id, cb.Get());
  EXPECT_EQ(events_.size(), 2u);
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/3,
      /*blocked_suffix=*/data_controls::dlp::kPrintingBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kPrintingWarnedUMA);
}

TEST_F(DlpContentManagerAshTest, CaptureModeInitRestricted) {
  // Needs to be set because CheckCaptureModeInitRestriction() will show the
  // blocked notification.
  NotificationDisplayServiceTester display_service_tester(profile());
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(true)).Times(1);   // No restrictions enforced.
  EXPECT_CALL(cb, Run(false)).Times(1);  // Block restriction.
  EXPECT_CALL(cb, Run(true)).Times(1);   // WebContents destroyed.

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/0,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);

  helper_.ChangeConfidentiality(web_contents.get(), kScreenshotRestricted);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenshotRestricted);
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kBlock)));

  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/3,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);
}

TEST_F(DlpContentManagerAshTest, CaptureModeInitWarnedContinued) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/true);
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(1);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(true)).Times(2);

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  helper_.ChangeConfidentiality(web_contents.get(), kScreenshotWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenshotWarned);
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());

  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      true, 1);

  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));

  // Check again: allow based on cached user's response - no dialog is shown.
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      true, 1);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnSilentProceededUMA,
      true, 1);
  EXPECT_EQ(events_.size(), 1u);
}

TEST_F(DlpContentManagerAshTest, CaptureModeInitWarnedCancelled) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/false);
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(2);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(2)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(false)).Times(2);

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  // Warn restriction is enforced: reject since the user canceled.
  helper_.ChangeConfidentiality(web_contents.get(), kScreenshotWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenshotWarned);
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      false, 1);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));

  // Check again: since the user previously cancelled, dialog is shown again.
  GetManager()->CheckCaptureModeInitRestriction(cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kCaptureModeInitBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kCaptureModeInitWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      false, 2);
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));
}

TEST_F(DlpContentManagerAshTest, ScreenshotRestricted) {
  // Needs to be set because CheckScreenshotRestriction() will show the blocked
  // notification.
  NotificationDisplayServiceTester display_service_tester(profile());
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(true)).Times(1);   // No restrictions enforced.
  EXPECT_CALL(cb, Run(false)).Times(1);  // Block restriction.
  EXPECT_CALL(cb, Run(true)).Times(1);   // WebContents destroyed.

  ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/0,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);

  helper_.ChangeConfidentiality(web_contents.get(), kScreenshotRestricted);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenshotRestricted);
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);

  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kBlock)));

  // Web contents are destroyed: allow.
  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/3,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);
}

TEST_F(DlpContentManagerAshTest, ScreenshotWarnedContinued) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/true);
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(1);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  EXPECT_CALL(cb, Run(true)).Times(2);

  ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  // Warn restriction is enforced: allow and remember that the user proceeded.
  helper_.ChangeConfidentiality(web_contents.get(), kScreenshotWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenshotWarned);
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));

  // Check again: allow based on cached user's response - no dialog is shown.
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      true, 1);
  EXPECT_EQ(events_.size(), 1u);
}

TEST_F(DlpContentManagerAshTest, ScreenshotWarnedCancelled) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/false);
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(2);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(2)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  EXPECT_CALL(cb, Run(false)).Times(2);

  ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  // Warn restriction is enforced: reject since the user canceled.
  helper_.ChangeConfidentiality(web_contents.get(), kScreenshotWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenshotWarned);
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      false, 1);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));

  // Check again: since the user previously cancelled, dialog is shown again.
  GetManager()->CheckScreenshotRestriction(area, cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kScreenshotBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenshotWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotWarnProceededUMA,
      false, 2);
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenshot, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));
}

TEST_F(DlpContentManagerAshTest, ScreenShareRestricted) {
  // Needs to be set because CheckScreenShareRestriction() will show the blocked
  // notification.
  NotificationDisplayServiceTester display_service_tester(profile());
  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(true)).Times(1);   // No restrictions enforced.
  EXPECT_CALL(cb, Run(false)).Times(1);  // Block restriction.
  EXPECT_CALL(cb, Run(true)).Times(1);   // WebContents destroyed.

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  const content::DesktopMediaID media_id(
      content::DesktopMediaID::TYPE_WEB_CONTENTS,
      content::DesktopMediaID::kNullId,
      content::WebContentsMediaCaptureId(
          web_contents->GetPrimaryMainFrame()->GetProcess()->GetID(),
          web_contents->GetPrimaryMainFrame()->GetRoutingID()));
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/0,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);

  helper_.ChangeConfidentiality(web_contents.get(), kScreenShareRestricted);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenShareRestricted);
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);

  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenShare, kRuleName,
          kRuleId, DlpRulesManager::Level::kBlock)));

  // Web contents are destroyed: allow.
  helper_.DestroyWebContents(web_contents.get());
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kEmptyRestrictionSet);
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/1, /*warned_count=*/0,
      /*total_count=*/3,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);
}

TEST_F(DlpContentManagerAshTest, ScreenShareWarnedContinued) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/true);
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(1);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(1)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  EXPECT_CALL(cb, Run(true)).Times(2);

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  const content::DesktopMediaID media_id(
      content::DesktopMediaID::TYPE_WEB_CONTENTS,
      content::DesktopMediaID::kNullId,
      content::WebContentsMediaCaptureId(
          web_contents->GetPrimaryMainFrame()->GetProcess()->GetID(),
          web_contents->GetPrimaryMainFrame()->GetRoutingID()));

  // Warn restriction is enforced: allow and remember that the user proceeded.
  helper_.ChangeConfidentiality(web_contents.get(), kScreenShareWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenShareWarned);
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenShare, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));

  // Check again: allow based on cached user's response - no dialog is shown.
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenShareWarnProceededUMA,
      true, 1);
  EXPECT_EQ(events_.size(), 1u);
}

TEST_F(DlpContentManagerAshTest, ScreenShareWarnedCancelled) {
  MockDlpWarnNotifier* mock_dlp_warn_notifier =
      CreateAndSetDlpWarnNotifier(/*should_proceed=*/false);
  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(2);

  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
      .Times(2)
      .WillRepeatedly(testing::DoAll(::testing::SetArgPointee<3>(kRuleMetadata),
                                     ::testing::Return(kSrcPattern)));

  MockWarningCallback cb;
  EXPECT_CALL(cb, Run(false)).Times(2);

  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  const content::DesktopMediaID media_id(
      content::DesktopMediaID::TYPE_WEB_CONTENTS,
      content::DesktopMediaID::kNullId,
      content::WebContentsMediaCaptureId(
          web_contents->GetPrimaryMainFrame()->GetProcess()->GetID(),
          web_contents->GetPrimaryMainFrame()->GetRoutingID()));

  // Warn restriction is enforced: reject since the user canceled.
  helper_.ChangeConfidentiality(web_contents.get(), kScreenShareWarned);
  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
            kScreenShareWarned);
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/1,
      /*total_count=*/1,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenShareWarnProceededUMA,
      false, 1);
  EXPECT_EQ(events_.size(), 1u);
  EXPECT_THAT(
      events_[0],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenShare, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));

  // Check again: since the user previously cancelled, dialog is shown again.
  GetManager()->CheckScreenShareRestriction(media_id, kApplicationName,
                                            cb.Get());
  VerifyHistogramCounts(
      /*blocked_count=*/0, /*warned_count=*/2,
      /*total_count=*/2,
      /*blocked_suffix=*/data_controls::dlp::kScreenShareBlockedUMA,
      /*warned_suffix=*/data_controls::dlp::kScreenShareWarnedUMA);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenShareWarnProceededUMA,
      false, 2);
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(data_controls::CreateDlpPolicyEvent(
          kSrcPattern, DlpRulesManager::Restriction::kScreenShare, kRuleName,
          kRuleId, DlpRulesManager::Level::kWarn)));
}

TEST_F(DlpContentManagerAshTest, OnWindowRestrictionChanged) {}

}  // namespace policy