Commit a7d6c3ea authored by Chinglin Yu's avatar Chinglin Yu Committed by Commit Bot

Use WindowedIncognitoObserver off the UI thread.

WindowedIncognitoObserver provides the interface for querying the
current status of incognito windows, and watch for new incognito window
opening. The interface can be used off the UI thread.

WindowedIncognitoMonitor is used to create WindowedIncognitoObserver
instances off the UI thread. Internally, the implementation class,
WindowedIncognitoMonitor, is registered as a BrowserListObserver
to observe opening/closing of incognito windows on behalf of queries
from WindowedIncognitoObserver.

Bug: 904785
Test: Add unit_tests WindowedIncognitoMonitorTest.*

Change-Id: I936d679c1963e1ffc1a5bbc5c4470274200d100c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1692208
Commit-Queue: Chinglin Yu <chinglinyu@chromium.org>
Reviewed-by: default avatarGabriel Marin <gmx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683174}
parent 2a6e4af1
...@@ -245,20 +245,28 @@ std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpu( ...@@ -245,20 +245,28 @@ std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpu(
} // namespace internal } // namespace internal
PerfCollector::PerfCollector() PerfCollector::PerfCollector()
: MetricCollector(kPerfCollectorName), weak_factory_(this) { : MetricCollector(kPerfCollectorName),
windowed_incognito_monitor_(std::make_unique<WindowedIncognitoMonitor>()),
weak_factory_(this) {
// Parsing processor information may be expensive. Compute asynchronously // Parsing processor information may be expensive. Compute asynchronously
// in a separate thread. // in a separate thread.
DCHECK(base::SequencedTaskRunnerHandle::IsSet()); DCHECK(base::SequencedTaskRunnerHandle::IsSet());
auto task_runner = base::SequencedTaskRunnerHandle::Get(); ui_task_runner_ = base::SequencedTaskRunnerHandle::Get();
base::PostTaskWithTraits( base::PostTaskWithTraits(
FROM_HERE, FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT, {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&PerfCollector::ParseCPUFrequencies, task_runner, base::BindOnce(&PerfCollector::ParseCPUFrequencies, ui_task_runner_,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
PerfCollector::~PerfCollector() {} PerfCollector::~PerfCollector() {
// Destroy WindowedIncognitoMonitor on the UI thread.
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce([](std::unique_ptr<WindowedIncognitoMonitor> ref) {},
std::move(windowed_incognito_monitor_)));
}
void PerfCollector::Init() { void PerfCollector::Init() {
CHECK(command_selector_.SetOdds( CHECK(command_selector_.SetOdds(
...@@ -416,7 +424,9 @@ void PerfCollector::ParseOutputProtoIfValid( ...@@ -416,7 +424,9 @@ void PerfCollector::ParseOutputProtoIfValid(
const std::string& perf_stdout) { const std::string& perf_stdout) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (incognito_observer->incognito_launched()) { // Check whether an incognito window had been opened during profile
// collection. If there was an incognito window, discard the incoming data.
if (incognito_observer->IncognitoLaunched()) {
AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_LAUNCHED); AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_LAUNCHED);
return; return;
} }
...@@ -454,13 +464,6 @@ bool PerfCollector::ShouldCollect() const { ...@@ -454,13 +464,6 @@ bool PerfCollector::ShouldCollect() const {
return false; return false;
} }
// For privacy reasons, Chrome should only collect perf data if there is no
// incognito session active (or gets spawned during the collection).
if (BrowserList::IsIncognitoSessionActive()) {
AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_ACTIVE);
return false;
}
return true; return true;
} }
...@@ -482,8 +485,13 @@ bool CommandSamplesCPUCycles(const std::vector<std::string>& args) { ...@@ -482,8 +485,13 @@ bool CommandSamplesCPUCycles(const std::vector<std::string>& args) {
void PerfCollector::CollectProfile( void PerfCollector::CollectProfile(
std::unique_ptr<SampledProfile> sampled_profile) { std::unique_ptr<SampledProfile> sampled_profile) {
std::unique_ptr<WindowedIncognitoObserver> incognito_observer = auto incognito_observer = windowed_incognito_monitor_->CreateObserver();
std::make_unique<WindowedIncognitoObserver>(); // For privacy reasons, Chrome should only collect perf data if there is no
// incognito session active (or gets spawned during the collection).
if (incognito_observer->IncognitoActive()) {
AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_ACTIVE);
return;
}
std::vector<std::string> command = std::vector<std::string> command =
base::SplitString(command_selector_.Select(), kPerfCommandDelimiter, base::SplitString(command_selector_.Select(), kPerfCommandDelimiter,
......
...@@ -18,6 +18,7 @@ namespace metrics { ...@@ -18,6 +18,7 @@ namespace metrics {
struct CPUIdentity; struct CPUIdentity;
class PerfOutputCall; class PerfOutputCall;
class WindowedIncognitoMonitor;
class WindowedIncognitoObserver; class WindowedIncognitoObserver;
// Enables collection of perf events profile data. perf aka "perf events" is a // Enables collection of perf events profile data. perf aka "perf events" is a
...@@ -86,6 +87,8 @@ class PerfCollector : public MetricCollector { ...@@ -86,6 +87,8 @@ class PerfCollector : public MetricCollector {
// perf data processing code. // perf data processing code.
std::vector<uint32_t> max_frequencies_mhz_; std::vector<uint32_t> max_frequencies_mhz_;
std::unique_ptr<WindowedIncognitoMonitor> windowed_incognito_monitor_;
private: private:
// Change the values in |collection_params_| and the commands in // Change the values in |collection_params_| and the commands in
// |command_selector_| for any keys that are present in |params|. // |command_selector_| for any keys that are present in |params|.
...@@ -98,6 +101,9 @@ class PerfCollector : public MetricCollector { ...@@ -98,6 +101,9 @@ class PerfCollector : public MetricCollector {
// An active call to perf/quipper, if set. // An active call to perf/quipper, if set.
std::unique_ptr<PerfOutputCall> perf_output_call_; std::unique_ptr<PerfOutputCall> perf_output_call_;
// For destroying |windowed_incognito_monitor_| on the UI thread.
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
base::WeakPtrFactory<PerfCollector> weak_factory_; base::WeakPtrFactory<PerfCollector> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PerfCollector); DISALLOW_COPY_AND_ASSIGN(PerfCollector);
......
...@@ -116,13 +116,19 @@ class TestIncognitoObserver : public WindowedIncognitoObserver { ...@@ -116,13 +116,19 @@ class TestIncognitoObserver : public WindowedIncognitoObserver {
// Used for passing observers to ParseOutputProtoIfValid(). // Used for passing observers to ParseOutputProtoIfValid().
static std::unique_ptr<WindowedIncognitoObserver> CreateWithIncognitoLaunched( static std::unique_ptr<WindowedIncognitoObserver> CreateWithIncognitoLaunched(
bool incognito_launched) { bool incognito_launched) {
auto observer = base::WrapUnique(new TestIncognitoObserver()); return base::WrapUnique(new TestIncognitoObserver(incognito_launched));
observer->set_incognito_launched(incognito_launched);
return observer;
} }
~TestIncognitoObserver() override = default;
bool IncognitoLaunched() const override { return incognito_launched_; }
private: private:
TestIncognitoObserver() {} TestIncognitoObserver(bool incognito_launched)
: WindowedIncognitoObserver(nullptr, 0),
incognito_launched_(incognito_launched) {}
bool incognito_launched_;
DISALLOW_COPY_AND_ASSIGN(TestIncognitoObserver); DISALLOW_COPY_AND_ASSIGN(TestIncognitoObserver);
}; };
...@@ -188,9 +194,9 @@ TEST_F(PerfCollectorTest, CheckSetup) { ...@@ -188,9 +194,9 @@ TEST_F(PerfCollectorTest, CheckSetup) {
EXPECT_TRUE(stored_profiles.empty()); EXPECT_TRUE(stored_profiles.empty());
EXPECT_FALSE(TestIncognitoObserver::CreateWithIncognitoLaunched(false) EXPECT_FALSE(TestIncognitoObserver::CreateWithIncognitoLaunched(false)
->incognito_launched()); ->IncognitoLaunched());
EXPECT_TRUE(TestIncognitoObserver::CreateWithIncognitoLaunched(true) EXPECT_TRUE(TestIncognitoObserver::CreateWithIncognitoLaunched(true)
->incognito_launched()); ->IncognitoLaunched());
base::ThreadPoolInstance::Get()->FlushForTesting(); base::ThreadPoolInstance::Get()->FlushForTesting();
scoped_task_environment_->RunUntilIdle(); scoped_task_environment_->RunUntilIdle();
EXPECT_GT(perf_collector_->max_frequencies_mhz_.size(), 0u); EXPECT_GT(perf_collector_->max_frequencies_mhz_.size(), 0u);
......
...@@ -10,18 +10,78 @@ ...@@ -10,18 +10,78 @@
namespace metrics { namespace metrics {
WindowedIncognitoObserver::WindowedIncognitoObserver() std::unique_ptr<WindowedIncognitoObserver>
: incognito_launched_(false) { WindowedIncognitoMonitor::CreateObserver() {
base::AutoLock lock(lock_);
return std::make_unique<WindowedIncognitoObserver>(
this, num_incognito_window_opened_);
}
WindowedIncognitoObserver::WindowedIncognitoObserver(
WindowedIncognitoMonitor* monitor,
uint64_t num_incognito_window_opened)
: windowed_incognito_monitor_(monitor),
num_incognito_window_opened_(num_incognito_window_opened) {}
bool WindowedIncognitoObserver::IncognitoLaunched() const {
return windowed_incognito_monitor_->IncognitoLaunched(
num_incognito_window_opened_);
}
bool WindowedIncognitoObserver::IncognitoActive() const {
return windowed_incognito_monitor_->IncognitoActive();
}
WindowedIncognitoMonitor::WindowedIncognitoMonitor()
: num_active_incognito_windows_(0), num_incognito_window_opened_(0) {
BrowserList::AddObserver(this); BrowserList::AddObserver(this);
// No need to acquire |lock_| because no observer has been created yet.
// Iterate over the BrowserList to get the current value of
// |num_active_incognito_windows_|.
for (auto* window : *BrowserList::GetInstance())
if (window->profile()->IsOffTheRecord())
num_active_incognito_windows_++;
} }
WindowedIncognitoObserver::~WindowedIncognitoObserver() { WindowedIncognitoMonitor::~WindowedIncognitoMonitor() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
BrowserList::RemoveObserver(this); BrowserList::RemoveObserver(this);
} }
void WindowedIncognitoObserver::OnBrowserAdded(Browser* browser) { bool WindowedIncognitoMonitor::IncognitoActive() const {
if (browser->profile()->IsOffTheRecord()) base::AutoLock lock(lock_);
incognito_launched_ = true; return num_active_incognito_windows_ > 0;
}
bool WindowedIncognitoMonitor::IncognitoLaunched(
uint64_t prev_num_incognito_opened) const {
base::AutoLock lock(lock_);
// Whether there is any incognito window opened after the observer was
// created.
return prev_num_incognito_opened < num_incognito_window_opened_;
}
void WindowedIncognitoMonitor::OnBrowserAdded(Browser* browser) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock lock(lock_);
if (!browser->profile()->IsOffTheRecord())
return;
num_active_incognito_windows_++;
num_incognito_window_opened_++;
}
void WindowedIncognitoMonitor::OnBrowserRemoved(Browser* browser) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock lock(lock_);
if (!browser->profile()->IsOffTheRecord())
return;
DCHECK(num_active_incognito_windows_ > 0);
num_active_incognito_windows_--;
} }
} // namespace metrics } // namespace metrics
...@@ -6,40 +6,107 @@ ...@@ -6,40 +6,107 @@
#define CHROME_BROWSER_METRICS_PERF_WINDOWED_INCOGNITO_OBSERVER_H_ #define CHROME_BROWSER_METRICS_PERF_WINDOWED_INCOGNITO_OBSERVER_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/browser_list_observer.h"
class Browser; class Browser;
namespace metrics { namespace metrics {
// This class watches for any incognito window being opened from the time it is class WindowedIncognitoMonitor;
// instantiated to the time it is destroyed.
class WindowedIncognitoObserver : public BrowserListObserver { // WindowedIncognitoObserver provides an interface for getting the current
// status of incognito windows and monitoring any new incognito windows after
// the observer is created. It can be used from any sequence.
//
// Example:
//
// // Create an WindowedIncognitoMonitor on the UI thread:
// auto windowed_incognito_monitor =
// std:::make_unique<WindowedIncognitoMonitor>();
//
// // Use an observer from any sequence:
// auto observer = windowed_incognito_monitor->CreateObserver();
// bool active = observer->IncognitoActive();
// // |active| will be true if there is any active incognito window.
//
// // An incognito window is opened.
// bool launched = observer->IncognitoLaunched();
// EXPECT_TRUE(launched);
//
// // Destroy the monitor on the UI thread:
// windowed_incognito_monitor.reset();
class WindowedIncognitoObserver {
public: public:
WindowedIncognitoObserver(); explicit WindowedIncognitoObserver(WindowedIncognitoMonitor* monitor,
~WindowedIncognitoObserver() override; uint64_t incognito_open_count);
virtual ~WindowedIncognitoObserver() = default;
// This method can be checked to see whether any incognito window has been // Made virtual for override in test.
// opened since the time this object was created. virtual bool IncognitoLaunched() const;
bool incognito_launched() const { bool IncognitoActive() const;
return incognito_launched_;
} private:
WindowedIncognitoMonitor* windowed_incognito_monitor_;
// The number of incognito windows that has been opened when the observer is
// created.
uint64_t num_incognito_window_opened_;
DISALLOW_COPY_AND_ASSIGN(WindowedIncognitoObserver);
};
// WindowedIncognitoMonitor watches for any incognito window being opened or
// closed from the time it is instantiated to the time it is destroyed. The
// monitor is affine to the UI thread: instantiation, destruction and the
// BrowserListObserver callbacks are called on the UI thread. The other methods
// for creating and serving WindowedIncognitoObserver are thread-safe.
class WindowedIncognitoMonitor : public BrowserListObserver {
public:
WindowedIncognitoMonitor();
~WindowedIncognitoMonitor() override;
// Returns an instance of WindowedIncognitoObserver that represents the
// request for monitoring any incognito window launches from now on.
std::unique_ptr<WindowedIncognitoObserver> CreateObserver();
protected: protected:
// Making IncognitoActive() and IncognitoLaunched() only accessible from
// WindowedIncognitoObserver;
friend class WindowedIncognitoObserver;
// Returns whether there is any active incognito window.
bool IncognitoActive() const;
// Returns whether there was any incognito window opened since an observer was
// created. Returns true if |num_prev_incognito_opened|, which is passed by
// the calling observer, is less than |num_incognito_window_opened_| of the
// monitor.
bool IncognitoLaunched(uint64_t num_prev_incognito_opened) const;
// BrowserListObserver implementation.
void OnBrowserAdded(Browser* browser) override;
void OnBrowserRemoved(Browser* browser) override;
// For testing. // For testing.
void set_incognito_launched(bool value) { int num_active_incognito_windows() const {
incognito_launched_ = value; return num_active_incognito_windows_;
}
uint64_t num_incognito_window_opened() const {
return num_incognito_window_opened_;
} }
private: private:
// BrowserListObserver implementation. mutable base::Lock lock_;
void OnBrowserAdded(Browser* browser) override;
// Gets set if an incognito window was opened during the lifetime of the // The number of active incognito window(s).
// object. Closing the window does not clear the flag. int num_active_incognito_windows_;
bool incognito_launched_; // The number of incognito windows we have ever seen.
uint64_t num_incognito_window_opened_;
DISALLOW_COPY_AND_ASSIGN(WindowedIncognitoObserver); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(WindowedIncognitoMonitor);
}; };
} // namespace metrics } // namespace metrics
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
#include "base/macros.h"
#include "base/test/bind_test_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.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() {}
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;
DISALLOW_COPY_AND_ASSIGN(TestWindowedIncognitoMonitor);
};
} // namespace
class WindowedIncognitoMonitorTest : public testing::Test {
public:
WindowedIncognitoMonitorTest() = default;
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_->GetOffTheRecordProfile() : profile_.get();
Browser::CreateParams params(browser_profile, true);
params.type = Browser::TYPE_TABBED;
params.window = browser_window.get();
auto browser = std::make_unique<Browser>(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::TestBrowserThreadBundle test_browser_thread_bundle_;
// 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_;
DISALLOW_COPY_AND_ASSIGN(WindowedIncognitoMonitorTest);
};
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
...@@ -3991,6 +3991,7 @@ test("unit_tests") { ...@@ -3991,6 +3991,7 @@ test("unit_tests") {
"../browser/metrics/perf/perf_events_collector_unittest.cc", "../browser/metrics/perf/perf_events_collector_unittest.cc",
"../browser/metrics/perf/process_type_collector_unittest.cc", "../browser/metrics/perf/process_type_collector_unittest.cc",
"../browser/metrics/perf/profile_provider_chromeos_unittest.cc", "../browser/metrics/perf/profile_provider_chromeos_unittest.cc",
"../browser/metrics/perf/windowed_incognito_observer_unittest.cc",
"../browser/notifications/chrome_ash_message_center_client_unittest.cc", "../browser/notifications/chrome_ash_message_center_client_unittest.cc",
"../browser/signin/signin_error_notifier_ash_unittest.cc", "../browser/signin/signin_error_notifier_ash_unittest.cc",
"../browser/speech/tts_chromeos_unittest.cc", "../browser/speech/tts_chromeos_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment