chromium/chrome/browser/chromeos/policy/dlp/dlp_content_manager_browsertest.cc

// Copyright 2021 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/chromeos/policy/dlp/dlp_content_manager.h"

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/test_future.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/printing/print_test_utils.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/printing/print_view_manager_common.h"
#include "chrome/browser/printing/test_print_preview_dialog_cloned_observer.h"
#include "chrome/browser/printing/test_print_view_manager_for_request_preview.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.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/report_queue_impl.h"
#include "components/reporting/storage/test_storage_module.h"
#include "components/reporting/util/test_support_callbacks.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;

namespace policy {

namespace {

const DlpContentRestrictionSet kEmptyRestrictionSet;
const DlpContentRestrictionSet kScreenshotRestricted(
    DlpContentRestriction::kScreenshot,
    DlpRulesManager::Level::kBlock);
const DlpContentRestrictionSet kScreenshotWarned(
    DlpContentRestriction::kScreenshot,
    DlpRulesManager::Level::kWarn);
const DlpContentRestrictionSet kScreenshotReported(
    DlpContentRestriction::kScreenshot,
    DlpRulesManager::Level::kReport);
const DlpContentRestrictionSet kPrintAllowed(DlpContentRestriction::kPrint,
                                             DlpRulesManager::Level::kAllow);
const DlpContentRestrictionSet kPrintRestricted(DlpContentRestriction::kPrint,
                                                DlpRulesManager::Level::kBlock);
const DlpContentRestrictionSet kPrintReported(DlpContentRestriction::kPrint,
                                              DlpRulesManager::Level::kReport);
const DlpContentRestrictionSet kPrintWarned(DlpContentRestriction::kPrint,
                                            DlpRulesManager::Level::kWarn);
const DlpContentRestrictionSet kScreenShareWarned(
    DlpContentRestriction::kScreenShare,
    DlpRulesManager::Level::kWarn);

constexpr char kPrintBlockedNotificationId[] = "print_dlp_blocked";

constexpr char kExampleUrl[] = "https://example.com";
constexpr char kLabel[] = "label";
const std::u16string kApplicationTitle = u"example.com";

constexpr char kRuleName[] = "rule #1";
constexpr char kRuleId[] = "testid1";
const DlpRulesManager::RuleMetadata kRuleMetadata(kRuleName, kRuleId);
}  // namespace

class DlpContentManagerBrowserTest : public InProcessBrowserTest {
 public:
  DlpContentManagerBrowserTest() = default;
  ~DlpContentManagerBrowserTest() override = default;

  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;
  }

  void SetUpOnMainThread() override {
    // Instantiate |DlpContentManagerTestHelper| after main thread has been
    // set up cause |DlpReportingManager| needs a sequenced task runner handle
    // to set up the report queue.
    helper_ = std::make_unique<DlpContentManagerTestHelper>();
  }

  void TearDownOnMainThread() override { helper_.reset(); }

  // Sets up mock rules manager.
  void SetupDlpRulesManager() {
    DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
        browser()->profile(),
        base::BindRepeating(&DlpContentManagerBrowserTest::SetDlpRulesManager,
                            base::Unretained(this)));
    ASSERT_TRUE(DlpRulesManagerFactory::GetForPrimaryProfile());

    EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern)
        .WillRepeatedly(testing::DoAll(testing::SetArgPointee<3>(kRuleMetadata),
                                       testing::Return("example.com")));
    EXPECT_CALL(*mock_rules_manager_, IsRestricted)
        .WillRepeatedly(testing::Return(DlpRulesManager::Level::kAllow));
  }

  void SetupReporting() {
    SetupDlpRulesManager();
    // Set up mock report queue.
    data_controls::SetReportQueueForReportingManager(
        helper_->GetReportingManager(), events_,
        base::SequencedTaskRunner::GetCurrentDefault());
  }

  void CheckEvents(DlpRulesManager::Restriction restriction,
                   DlpRulesManager::Level level,
                   size_t count) {
    EXPECT_EQ(events_.size(), count);
    for (size_t i = 0; i < count; ++i) {
      EXPECT_THAT(events_[i], data_controls::IsDlpPolicyEvent(
                                  data_controls::CreateDlpPolicyEvent(
                                      GURL(kExampleUrl).spec(), restriction,
                                      kRuleName, kRuleId, level)));
    }
  }

 protected:
  std::unique_ptr<::reporting::ReportingClient::TestEnvironment>
      test_reporting_;
  std::unique_ptr<DlpContentManagerTestHelper> helper_;
  base::HistogramTester histogram_tester_;
  raw_ptr<MockDlpRulesManager, DanglingUntriaged> mock_rules_manager_;
  std::vector<DlpPolicyEvent> events_;
};

IN_PROC_BROWSER_TEST_F(DlpContentManagerBrowserTest, PrintingNotRestricted) {
  // Set up mock report queue and mock rules manager.
  SetupReporting();
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  NotificationDisplayServiceTester display_service_tester(browser()->profile());

  base::MockCallback<WarningCallback> cb;
  EXPECT_CALL(cb, Run(true)).Times(1);

  helper_->GetContentManager()->CheckPrintingRestriction(
      web_contents, web_contents->GetPrimaryMainFrame()->GetGlobalId(),
      cb.Get());

  // Start printing and check that there is no notification when printing is not
  // restricted.
  printing::test::StartPrint(web_contents);
  EXPECT_FALSE(
      display_service_tester.GetNotification(kPrintBlockedNotificationId));
  CheckEvents(DlpRulesManager::Restriction::kPrinting,
              DlpRulesManager::Level::kBlock, 0u);
}

IN_PROC_BROWSER_TEST_F(DlpContentManagerBrowserTest, ScreenshotsRestricted) {
  SetupReporting();
  DlpContentManager* manager = helper_->GetContentManager();
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  EXPECT_FALSE(manager->IsScreenshotApiRestricted(web_contents));
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      true, 0);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      false, 1);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kBlock, 0u);

  helper_->ChangeConfidentiality(web_contents, kScreenshotRestricted);
  EXPECT_TRUE(manager->IsScreenshotApiRestricted(web_contents));
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      true, 1);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      false, 1);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kBlock, 1u);

  web_contents->WasHidden();
  helper_->ChangeVisibility(web_contents);
  EXPECT_TRUE(manager->IsScreenshotApiRestricted(web_contents));
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      true, 2);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      false, 1);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kBlock, 2u);

  web_contents->WasShown();
  helper_->ChangeVisibility(web_contents);
  EXPECT_TRUE(manager->IsScreenshotApiRestricted(web_contents));
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      true, 3);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      false, 1);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kBlock, 3u);

  helper_->DestroyWebContents(web_contents);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      true, 3);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      false, 1);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kBlock, 3u);
}

IN_PROC_BROWSER_TEST_F(DlpContentManagerBrowserTest, ScreenshotsWarned) {
  SetupReporting();
  DlpContentManager* manager = helper_->GetContentManager();
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  EXPECT_FALSE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kWarn, 0u);

  helper_->ChangeConfidentiality(web_contents, kScreenshotWarned);
  EXPECT_TRUE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kWarn, 1u);

  web_contents->WasHidden();
  helper_->ChangeVisibility(web_contents);
  EXPECT_TRUE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kWarn, 2u);

  web_contents->WasShown();
  helper_->ChangeVisibility(web_contents);
  EXPECT_TRUE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kWarn, 3u);

  helper_->DestroyWebContents(web_contents);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kWarn, 3u);
}

IN_PROC_BROWSER_TEST_F(DlpContentManagerBrowserTest, ScreenshotsReported) {
  SetupReporting();
  DlpContentManager* manager = helper_->GetContentManager();
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  EXPECT_FALSE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kReport, 0u);

  helper_->ChangeConfidentiality(web_contents, kScreenshotReported);
  EXPECT_FALSE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kReport, 1u);

  web_contents->WasHidden();
  helper_->ChangeVisibility(web_contents);
  EXPECT_FALSE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kReport, 2u);

  web_contents->WasShown();
  helper_->ChangeVisibility(web_contents);
  EXPECT_FALSE(manager->IsScreenshotApiRestricted(web_contents));
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kReport, 3u);

  helper_->DestroyWebContents(web_contents);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      true, 0);
  histogram_tester_.ExpectBucketCount(
      data_controls::GetDlpHistogramPrefix() +
          data_controls::dlp::kScreenshotBlockedUMA,
      false, 4);
  CheckEvents(DlpRulesManager::Restriction::kScreenshot,
              DlpRulesManager::Level::kReport, 3u);
}

class DlpContentManagerReportingBrowserTest
    : public DlpContentManagerBrowserTest {
 public:
  void SetUpOnMainThread() override {
    DlpContentManagerBrowserTest::SetUpOnMainThread();
    content::WebContents* first_tab =
        browser()->tab_strip_model()->GetActiveWebContents();
    ASSERT_TRUE(first_tab);

    // Open a new tab so |cloned_tab_observer_| can see it and create a
    // TestPrintViewManagerForRequestPreview for it before the real
    // PrintViewManager gets created.
    // Since TestPrintViewManagerForRequestPreview is created with
    // PrintViewManager::UserDataKey(), the real PrintViewManager is not created
    // and TestPrintViewManagerForRequestPreview gets mojo messages for the
    // purposes of this test.
    cloned_tab_observer_ =
        std::make_unique<printing::TestPrintPreviewDialogClonedObserver>(
            first_tab);
    chrome::DuplicateTab(browser());
  }

  void TearDownOnMainThread() override {
    DlpContentManagerBrowserTest::TearDownOnMainThread();
    cloned_tab_observer_.reset();
    test_reporting_.reset();
    storage_module_.reset();
  }

  // Sets up real report queue together with TestStorageModule
  void SetupReportQueue() {
    const ::reporting::Destination destination_ =
        ::reporting::Destination::UPLOAD_EVENTS;

    storage_module_ =
        base::MakeRefCounted<::reporting::test::TestStorageModule>();

    test_reporting_ =
        ::reporting::ReportingClient::TestEnvironment::CreateWithStorageModule(
            test_storage_module());

    policy_check_callback_ =
        base::BindRepeating(&testing::MockFunction<::reporting::Status()>::Call,
                            base::Unretained(&mocked_policy_check_));

    ON_CALL(mocked_policy_check_, Call())
        .WillByDefault(testing::Return(::reporting::Status::StatusOK()));

    auto config_result = ::reporting::ReportQueueConfiguration::Create(
                             {.event_type = ::reporting::EventType::kDevice,
                              .destination = destination_})
                             .SetPolicyCheckCallback(policy_check_callback_)
                             .Build();

    ASSERT_TRUE(config_result.has_value());

    // Create a report queue with the test storage module, and attach it
    // to an actual speculative report queue so we can override the one used in
    // |DlpReportingManager| by default.
    ::reporting::test::TestEvent<
        ::reporting::StatusOr<std::unique_ptr<::reporting::ReportQueue>>>
        report_queue_event;
    ::reporting::ReportQueueImpl::Create(std::move(config_result.value()),
                                         storage_module_,
                                         report_queue_event.cb());
    auto report_queue_result = report_queue_event.result();

    ASSERT_TRUE(report_queue_result.has_value());

    auto speculative_report_queue =
        ::reporting::SpeculativeReportQueueImpl::Create(
            {.destination = destination_});
    auto attach_queue_cb =
        speculative_report_queue->PrepareToAttachActualQueue();

    helper_->GetReportingManager()->SetReportQueueForTest(
        std::move(speculative_report_queue));
    std::move(attach_queue_cb).Run(std::move(report_queue_result.value()));

    // Wait until the speculative report queue is initialized with the stubbed
    // report queue posted to its internal task runner
    base::ThreadPoolInstance::Get()->FlushForTesting();
  }

  ::reporting::test::TestStorageModule* test_storage_module() const {
    ::reporting::test::TestStorageModule* test_storage_module =
        google::protobuf::down_cast<::reporting::test::TestStorageModule*>(
            storage_module_.get());
    DCHECK(test_storage_module);
    return test_storage_module;
  }

  void CheckRecord(DlpPolicyEvent expectedEvent, ::reporting::Record record) {
    DlpPolicyEvent event;
    EXPECT_TRUE(event.ParseFromString(record.data()));
    EXPECT_EQ(event.source().url(), GURL(kExampleUrl).spec());
    EXPECT_EQ(event.triggered_rule_name(), kRuleName);
    EXPECT_EQ(event.triggered_rule_id(), kRuleId);
    EXPECT_THAT(event, data_controls::IsDlpPolicyEvent(expectedEvent));
  }

  // Sets an action to execute when an event arrives to the report queue storage
  // module.
  void SetAddRecordCheck(DlpPolicyEvent expectedEvent, int times) {
    // TODO(1290312): Change to [=, this] when chrome code base is updated to
    // C++20.
    EXPECT_CALL(*test_storage_module(), AddRecord)
        .Times(times)
        .WillRepeatedly(testing::WithArgs<1, 2>(testing::Invoke(
            [=, this](::reporting::Record record,
                      base::OnceCallback<void(::reporting::Status)> callback) {
              content::GetUIThreadTaskRunner({})->PostTask(
                  FROM_HERE,
                  base::BindOnce(
                      &DlpContentManagerReportingBrowserTest::CheckRecord,
                      base::Unretained(this), std::move(expectedEvent),
                      std::move(record)));
              std::move(callback).Run(::reporting::Status::StatusOK());
            })));
  }

  // Start printing and wait for the end of
  // printing::PrintViewManager::RequestPrintPreview(). StartPrint() is an
  // asynchronous function, which initializes mojo communication with a renderer
  // process. We need to wait for the DLP restriction check in
  // RequestPrintPreview(), which happens after the renderer process
  // communicates back to the browser process.
  void StartPrint(
      printing::TestPrintViewManagerForRequestPreview* print_manager,
      content::WebContents* web_contents) {
    base::test::TestFuture<void> future;
    print_manager->set_quit_closure(future.GetCallback());
    printing::test::StartPrint(web_contents);
    EXPECT_TRUE(future.Wait());
  }

 protected:
  // Helper class to enable asserting that printing was accepted or rejected.
  class MockPrintManager
      : public printing::TestPrintViewManagerForRequestPreview {
   public:
    MOCK_METHOD(void, PrintPreviewAllowedForTesting, (), (override));
    MOCK_METHOD(void, PrintPreviewRejectedForTesting, (), (override));

    static void CreateForWebContents(content::WebContents* web_contents) {
      web_contents->SetUserData(
          PrintViewManager::UserDataKey(),
          std::make_unique<MockPrintManager>(web_contents));
    }

    static MockPrintManager* FromWebContents(
        content::WebContents* web_contents) {
      return static_cast<MockPrintManager*>(
          printing::TestPrintViewManagerForRequestPreview::FromWebContents(
              web_contents));
    }

    explicit MockPrintManager(content::WebContents* web_contents)
        : printing::TestPrintViewManagerForRequestPreview(web_contents) {}
    ~MockPrintManager() override = default;
  };

  MockPrintManager* GetPrintManager(content::WebContents* web_contents) {
    MockPrintManager::CreateForWebContents(web_contents);
    return MockPrintManager::FromWebContents(web_contents);
  }

  scoped_refptr<::reporting::StorageModuleInterface> storage_module_;
  testing::NiceMock<testing::MockFunction<::reporting::Status()>>
      mocked_policy_check_;
  ::reporting::ReportQueueConfiguration::PolicyCheckCallback
      policy_check_callback_;
  std::unique_ptr<printing::TestPrintPreviewDialogClonedObserver>
      cloned_tab_observer_;
};

IN_PROC_BROWSER_TEST_F(DlpContentManagerReportingBrowserTest,
                       PrintingRestricted) {
  // Set up mock rules manager.
  SetupDlpRulesManager();
  // Set up real report queue.
  SetupReportQueue();
  // Sets an action to execute when an event arrives to a storage module.
  SetAddRecordCheck(
      CreateDlpPolicyEvent(GURL(kExampleUrl).spec(),
                           DlpRulesManager::Restriction::kPrinting, kRuleName,
                           kRuleId, DlpRulesManager::Level::kBlock),
      /*times=*/2);

  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  NotificationDisplayServiceTester display_service_tester(browser()->profile());

  // Set up the mocks for directly calling CheckPrintingRestriction().
  base::MockCallback<WarningCallback> cb;
  testing::InSequence s;
  EXPECT_CALL(cb, Run(true)).Times(1);
  EXPECT_CALL(cb, Run(false)).Times(1);

  content::GlobalRenderFrameHostId rfh_id =
      web_contents->GetPrimaryMainFrame()->GetGlobalId();
  // Printing should first be allowed.
  helper_->GetContentManager()->CheckPrintingRestriction(web_contents, rfh_id,
                                                         cb.Get());

  // Set up printing restriction.
  helper_->ChangeConfidentiality(web_contents, kPrintRestricted);
  helper_->GetContentManager()->CheckPrintingRestriction(web_contents, rfh_id,
                                                         cb.Get());

  // Setup the mock for the printing manager to invoke
  // CheckPrintingRestriction() indirectly.
  MockPrintManager* print_manager = GetPrintManager(web_contents);
  EXPECT_CALL(*print_manager, PrintPreviewAllowedForTesting).Times(0);
  EXPECT_CALL(*print_manager, PrintPreviewRejectedForTesting).Times(1);
  StartPrint(print_manager, web_contents);

  // Check for notification about printing restriction.
  EXPECT_TRUE(
      display_service_tester.GetNotification(kPrintBlockedNotificationId));
}

IN_PROC_BROWSER_TEST_F(DlpContentManagerReportingBrowserTest,
                       PrintingReported) {
  SetupDlpRulesManager();
  SetupReportQueue();
  SetAddRecordCheck(
      CreateDlpPolicyEvent(GURL(kExampleUrl).spec(),
                           DlpRulesManager::Restriction::kPrinting, kRuleName,
                           kRuleId, DlpRulesManager::Level::kReport),
      /*times=*/2);

  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  NotificationDisplayServiceTester display_service_tester(browser()->profile());

  // Set up printing restriction.
  helper_->ChangeConfidentiality(web_contents, kPrintReported);
  // Printing should be reported, but still allowed whether we call
  // CheckPrintingRestriction() directly or indirectly.
  base::MockCallback<WarningCallback> cb;
  EXPECT_CALL(cb, Run(true)).Times(1);
  helper_->GetContentManager()->CheckPrintingRestriction(
      web_contents, web_contents->GetPrimaryMainFrame()->GetGlobalId(),
      cb.Get());

  MockPrintManager* print_manager = GetPrintManager(web_contents);
  EXPECT_CALL(*print_manager, PrintPreviewAllowedForTesting).Times(1);
  EXPECT_CALL(*print_manager, PrintPreviewRejectedForTesting).Times(0);
  StartPrint(print_manager, web_contents);

  EXPECT_FALSE(
      display_service_tester.GetNotification(kPrintBlockedNotificationId));
}

IN_PROC_BROWSER_TEST_F(DlpContentManagerReportingBrowserTest, PrintingWarned) {
  SetupDlpRulesManager();
  SetupReportQueue();
  NotificationDisplayServiceTester display_service_tester(browser()->profile());

  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();

  // Set up printing restriction.
  helper_->ChangeConfidentiality(web_contents, kPrintWarned);

  SetAddRecordCheck(
      CreateDlpPolicyEvent(GURL(kExampleUrl).spec(),
                           DlpRulesManager::Restriction::kPrinting, kRuleName,
                           kRuleId, DlpRulesManager::Level::kWarn),
      /*times=*/1);

  MockPrintManager* print_manager = GetPrintManager(web_contents);
  testing::InSequence s;
  EXPECT_CALL(*print_manager, PrintPreviewRejectedForTesting()).Times(1);

  StartPrint(print_manager, web_contents);
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 1);
  // Hit Esc to "Cancel".
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false,
                                              false, false, false));
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 0);
  // There should be no notification about printing restriction.
  EXPECT_FALSE(
      display_service_tester.GetNotification(kPrintBlockedNotificationId));
  EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(test_storage_module()));

  SetAddRecordCheck(
      CreateDlpPolicyEvent(GURL(kExampleUrl).spec(),
                           DlpRulesManager::Restriction::kPrinting, kRuleName,
                           kRuleId, DlpRulesManager::Level::kWarn),
      /*times=*/1);

  // Attempt to print again.
  StartPrint(print_manager, web_contents);
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 1);
  EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(test_storage_module()));

  SetAddRecordCheck(
      CreateDlpPolicyWarningProceededEvent(
          GURL(kExampleUrl).spec(), DlpRulesManager::Restriction::kPrinting,
          kRuleName, kRuleId),
      /*times=*/1);
  EXPECT_CALL(*print_manager, PrintPreviewAllowedForTesting()).Times(1);

  // Hit Enter to "Print anyway".
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_RETURN, false,
                                              false, false, false));
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 0);
}

IN_PROC_BROWSER_TEST_F(DlpContentManagerReportingBrowserTest,
                       TabShareWarnedDuringAllowed) {
  SetupReporting();
  NotificationDisplayServiceTester display_service_tester(browser()->profile());

  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kExampleUrl)));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetActiveWebContents();
  const content::DesktopMediaID media_id(
      content::DesktopMediaID::TYPE_WEB_CONTENTS,
      content::DesktopMediaID::kNullId,
      content::WebContentsMediaCaptureId(
          web_contents->GetPrimaryMainFrame()->GetProcess()->GetID(),
          web_contents->GetPrimaryMainFrame()->GetRoutingID()));

  DlpContentManager* manager = helper_->GetContentManager();
  base::MockCallback<content::MediaStreamUI::StateChangeCallback>
      state_change_cb;
  base::MockCallback<base::RepeatingClosure> stop_cb;
  base::MockCallback<content::MediaStreamUI::SourceCallback> source_cb;
  // Explicitly specify that the stop callback should never be invoked.
  EXPECT_CALL(stop_cb, Run()).Times(0);
  testing::InSequence s;
  EXPECT_CALL(state_change_cb,
              Run(testing::_, blink::mojom::MediaStreamStateChange::PAUSE))
      .Times(1);
  EXPECT_CALL(source_cb, Run).Times(1);
  // Although the share should be paused and resumed, DLP will only call
  // state_change_cb_ once to pause it. When it's supposed to be resumed, it
  // will call source_cb only first and resume only the new stream once
  // notified.
  EXPECT_CALL(state_change_cb,
              Run(testing::_, blink::mojom::MediaStreamStateChange::PLAY))
      .Times(0);

  manager->OnScreenShareStarted(kLabel, {media_id}, kApplicationTitle,
                                stop_cb.Get(), state_change_cb.Get(),
                                source_cb.Get());

  helper_->ChangeConfidentiality(web_contents, kScreenShareWarned);
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 1);
  CheckEvents(DlpRulesManager::Restriction::kScreenShare,
              DlpRulesManager::Level::kWarn, 1u);

  // Hit Enter to "Share anyway".
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
      browser(), ui::VKEY_RETURN, /*control=*/false,
      /*shift=*/false, /*alt=*/false, /*command=*/false));
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 0);
  EXPECT_EQ(events_.size(), 2u);
  EXPECT_THAT(
      events_[1],
      data_controls::IsDlpPolicyEvent(
          data_controls::CreateDlpPolicyWarningProceededEvent(
              GURL(kExampleUrl).spec(),
              DlpRulesManager::Restriction::kScreenShare, kRuleName, kRuleId)));

  // The contents should already be cached as allowed by the user, so this
  // should not trigger a new warning.
  helper_->ChangeConfidentiality(web_contents, kScreenShareWarned);
  EXPECT_EQ(helper_->ActiveWarningDialogsCount(), 0);
  EXPECT_EQ(events_.size(), 2u);
}

}  // namespace policy