chromium/chrome/browser/metrics/perf/windowed_incognito_observer_unittest.cc

// Copyright 2019 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/metrics/perf/windowed_incognito_observer.h"

#include "base/test/bind.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace metrics {

namespace {
// Allows access to some private methods for testing.
class TestWindowedIncognitoMonitor : public WindowedIncognitoMonitor {
 public:
  TestWindowedIncognitoMonitor() : WindowedIncognitoMonitor() {}

  TestWindowedIncognitoMonitor(const TestWindowedIncognitoMonitor&) = delete;
  TestWindowedIncognitoMonitor& operator=(const TestWindowedIncognitoMonitor&) =
      delete;

  int num_on_browser_added() { return num_on_browser_added_; }
  int num_on_browser_removed() { return num_on_browser_removed_; }

  using WindowedIncognitoMonitor::num_active_incognito_windows;
  using WindowedIncognitoMonitor::num_incognito_window_opened;

 private:
  // BrowserListObserver implementation.
  void OnBrowserAdded(Browser* browser) override {
    num_on_browser_added_++;
    WindowedIncognitoMonitor::OnBrowserAdded(browser);
  }

  void OnBrowserRemoved(Browser* browser) override {
    num_on_browser_removed_++;
    WindowedIncognitoMonitor::OnBrowserRemoved(browser);
  }

  int num_on_browser_added_ = 0;
  int num_on_browser_removed_ = 0;
};

}  // namespace

class WindowedIncognitoMonitorTest : public testing::Test {
 public:
  WindowedIncognitoMonitorTest() = default;

  WindowedIncognitoMonitorTest(const WindowedIncognitoMonitorTest&) = delete;
  WindowedIncognitoMonitorTest& operator=(const WindowedIncognitoMonitorTest&) =
      delete;

  void SetUp() override {
    // Instantiate a testing profile.
    TestingProfile::Builder profile_builder;
    profile_ = profile_builder.Build();
    incognito_monitor_ = std::make_unique<TestWindowedIncognitoMonitor>();
  }

  void TearDown() override {
    incognito_monitor_.reset();
    profile_.reset();
  }

  size_t OpenBrowserWindow(bool incognito) {
    auto browser_window = std::make_unique<TestBrowserWindow>();
    Profile* browser_profile =
        incognito ? profile_->GetPrimaryOTRProfile(/*create_if_needed=*/true)
                  : profile_.get();
    Browser::CreateParams params(browser_profile, true);
    params.type = Browser::TYPE_NORMAL;
    params.window = browser_window.get();
    auto browser = std::unique_ptr<Browser>(Browser::Create(params));

    size_t handle = next_browser_id++;
    open_browsers_[handle] =
        std::make_pair(std::move(browser_window), std::move(browser));
    return handle;
  }

  // Closes the browser window with the given handle.
  void CloseBrowserWindow(size_t handle) {
    auto it = open_browsers_.find(handle);
    ASSERT_FALSE(it == open_browsers_.end());
    open_browsers_.erase(it);
  }

 protected:
  content::BrowserTaskEnvironment task_environment_;

  // The associated testing browser profile.
  std::unique_ptr<TestingProfile> profile_;

  // Keep track of the open browsers and accompanying windows.
  std::unordered_map<
      size_t,
      std::pair<std::unique_ptr<TestBrowserWindow>, std::unique_ptr<Browser>>>
      open_browsers_;
  static size_t next_browser_id;

  std::unique_ptr<TestWindowedIncognitoMonitor> incognito_monitor_;
};

size_t WindowedIncognitoMonitorTest::next_browser_id = 1;

// Test that BrowserListObserver callbacks work as expected.
TEST_F(WindowedIncognitoMonitorTest, CheckSetup) {
  // Open a normal window.
  size_t window1 = OpenBrowserWindow(false);
  EXPECT_EQ(incognito_monitor_->num_on_browser_added(), 1);
  EXPECT_EQ(incognito_monitor_->num_on_browser_removed(), 0);

  // Close the normal window.
  CloseBrowserWindow(window1);
  EXPECT_EQ(incognito_monitor_->num_on_browser_added(), 1);
  EXPECT_EQ(incognito_monitor_->num_on_browser_removed(), 1);

  // Open an incognito window.
  size_t window2 = OpenBrowserWindow(true);
  EXPECT_EQ(incognito_monitor_->num_on_browser_added(), 2);
  EXPECT_EQ(incognito_monitor_->num_on_browser_removed(), 1);

  // Open a normal window.
  size_t window3 = OpenBrowserWindow(false);
  EXPECT_EQ(incognito_monitor_->num_on_browser_added(), 3);
  EXPECT_EQ(incognito_monitor_->num_on_browser_removed(), 1);

  // Close the normal window.
  CloseBrowserWindow(window3);
  EXPECT_EQ(incognito_monitor_->num_on_browser_added(), 3);
  EXPECT_EQ(incognito_monitor_->num_on_browser_removed(), 2);

  // Close the incognito window.
  CloseBrowserWindow(window2);
  EXPECT_EQ(incognito_monitor_->num_on_browser_added(), 3);
  EXPECT_EQ(incognito_monitor_->num_on_browser_removed(), 3);
}

// Test that incognito window state is recorded correctly.
TEST_F(WindowedIncognitoMonitorTest, NumIncognitoWindow) {
  // Open a normal window. This doesn't affect incognito state.
  size_t window1 = OpenBrowserWindow(false);
  EXPECT_EQ(incognito_monitor_->num_active_incognito_windows(), 0);
  EXPECT_EQ(incognito_monitor_->num_incognito_window_opened(), 0U);

  // Close the normal window.
  CloseBrowserWindow(window1);
  EXPECT_EQ(incognito_monitor_->num_active_incognito_windows(), 0);
  EXPECT_EQ(incognito_monitor_->num_incognito_window_opened(), 0U);

  // Open an incognito window.
  size_t window2 = OpenBrowserWindow(true);
  EXPECT_EQ(incognito_monitor_->num_active_incognito_windows(), 1);
  EXPECT_EQ(incognito_monitor_->num_incognito_window_opened(), 1U);

  // Open another incognito window.
  size_t window3 = OpenBrowserWindow(true);
  EXPECT_EQ(incognito_monitor_->num_active_incognito_windows(), 2);
  EXPECT_EQ(incognito_monitor_->num_incognito_window_opened(), 2U);

  // Close an incognito window.
  CloseBrowserWindow(window3);
  EXPECT_EQ(incognito_monitor_->num_active_incognito_windows(), 1);
  EXPECT_EQ(incognito_monitor_->num_incognito_window_opened(), 2U);

  // Close the final incognito window.
  CloseBrowserWindow(window2);
  EXPECT_EQ(incognito_monitor_->num_active_incognito_windows(), 0);
  EXPECT_EQ(incognito_monitor_->num_incognito_window_opened(), 2U);
}

// Test that WindowedIncognitoObserver returns the correct incognito state.
TEST_F(WindowedIncognitoMonitorTest, IncognitoObserver) {
  auto observer1 = incognito_monitor_->CreateObserver();
  EXPECT_FALSE(observer1->IncognitoActive());
  EXPECT_FALSE(observer1->IncognitoLaunched());

  // Open an incognito window.
  size_t window1 = OpenBrowserWindow(true);
  EXPECT_TRUE(observer1->IncognitoActive());
  EXPECT_TRUE(observer1->IncognitoLaunched());

  // |observer2| is created after incognito window is opened.
  auto observer2 = incognito_monitor_->CreateObserver();
  EXPECT_TRUE(observer2->IncognitoActive());
  EXPECT_FALSE(observer2->IncognitoLaunched());

  // Open another incognito window.
  size_t window2 = OpenBrowserWindow(true);
  EXPECT_TRUE(observer1->IncognitoActive());
  EXPECT_TRUE(observer1->IncognitoLaunched());
  EXPECT_TRUE(observer2->IncognitoActive());
  EXPECT_TRUE(observer2->IncognitoLaunched());

  // Close all incognito windows.
  CloseBrowserWindow(window1);
  CloseBrowserWindow(window2);

  EXPECT_FALSE(observer1->IncognitoActive());
  EXPECT_TRUE(observer1->IncognitoLaunched());
  EXPECT_FALSE(observer2->IncognitoActive());
  EXPECT_TRUE(observer2->IncognitoLaunched());

  // An observer created now should not see incognito active of launched.
  auto observer3 = incognito_monitor_->CreateObserver();
  EXPECT_FALSE(observer3->IncognitoActive());
  EXPECT_FALSE(observer3->IncognitoLaunched());

  size_t window3 = OpenBrowserWindow(true);
  EXPECT_TRUE(observer3->IncognitoActive());
  EXPECT_TRUE(observer3->IncognitoLaunched());

  CloseBrowserWindow(window3);
  EXPECT_FALSE(observer3->IncognitoActive());
  EXPECT_TRUE(observer3->IncognitoLaunched());
}

}  // namespace metrics