blob: b12a993e48790f7bfe687a9e26839d4e6609af98 [file] [log] [blame]
// Copyright 2018 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/ui/views/relaunch_notification/relaunch_notification_controller.h"
#include <memory>
#include "base/macros.h"
#include "base/values.h"
#include "chrome/browser/upgrade_detector.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// A delegate interface for handling the actions taken by the controller.
class ControllerDelegate {
public:
virtual ~ControllerDelegate() = default;
virtual void ShowRelaunchRecommendedBubble() = 0;
virtual void CloseRelaunchRecommendedBubble() = 0;
virtual void ShowRelaunchRequiredDialog() = 0;
virtual void CloseRelaunchRequiredDialog() = 0;
protected:
ControllerDelegate() = default;
};
// A fake controller that asks a delegate to do work.
class FakeRelaunchNotificationController
: public RelaunchNotificationController {
public:
FakeRelaunchNotificationController(UpgradeDetector* upgrade_detector,
ControllerDelegate* delegate)
: RelaunchNotificationController(upgrade_detector), delegate_(delegate) {}
private:
void ShowRelaunchRecommendedBubble() override {
delegate_->ShowRelaunchRecommendedBubble();
}
void CloseRelaunchRecommendedBubble() override {
delegate_->CloseRelaunchRecommendedBubble();
}
void ShowRelaunchRequiredDialog() override {
delegate_->ShowRelaunchRequiredDialog();
}
void CloseRelaunchRequiredDialog() override {
delegate_->CloseRelaunchRequiredDialog();
}
ControllerDelegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(FakeRelaunchNotificationController);
};
// A mock delegate for testing.
class MockControllerDelegate : public ControllerDelegate {
public:
MOCK_METHOD0(ShowRelaunchRecommendedBubble, void());
MOCK_METHOD0(CloseRelaunchRecommendedBubble, void());
MOCK_METHOD0(ShowRelaunchRequiredDialog, void());
MOCK_METHOD0(CloseRelaunchRequiredDialog, void());
};
// A fake UpgradeDetector.
class FakeUpgradeDetector : public UpgradeDetector {
public:
FakeUpgradeDetector() = default;
// Sets the annoyance level to |level| and broadcasts the change to all
// observers.
void BroadcastLevelChange(UpgradeNotificationAnnoyanceLevel level) {
set_upgrade_notification_stage(level);
NotifyUpgrade();
}
private:
DISALLOW_COPY_AND_ASSIGN(FakeUpgradeDetector);
};
} // namespace
// A test harness that provides facilities for manipulating the relaunch
// notification policy setting and for broadcasting upgrade notifications.
class RelaunchNotificationControllerTest : public ::testing::Test {
protected:
RelaunchNotificationControllerTest()
: scoped_local_state_(TestingBrowserProcess::GetGlobal()) {}
UpgradeDetector* upgrade_detector() { return &upgrade_detector_; }
FakeUpgradeDetector& fake_upgrade_detector() { return upgrade_detector_; }
// Sets the browser.relaunch_notification preference in Local State to
// |value|.
void SetNotificationPref(int value) {
scoped_local_state_.Get()->SetManagedPref(
prefs::kRelaunchNotification, std::make_unique<base::Value>(value));
}
private:
ScopedTestingLocalState scoped_local_state_;
FakeUpgradeDetector upgrade_detector_;
DISALLOW_COPY_AND_ASSIGN(RelaunchNotificationControllerTest);
};
TEST_F(RelaunchNotificationControllerTest, CreateDestroy) {
::testing::StrictMock<MockControllerDelegate> mock_controller_delegate;
FakeRelaunchNotificationController controller(upgrade_detector(),
&mock_controller_delegate);
}
// Without the browser.relaunch_notification preference set, the controller
// should not be observing the UpgradeDetector, and should therefore never
// attempt to show any notifications.
TEST_F(RelaunchNotificationControllerTest, PolicyUnset) {
::testing::StrictMock<MockControllerDelegate> mock_controller_delegate;
FakeRelaunchNotificationController controller(upgrade_detector(),
&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_LOW);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
}
// With the browser.relaunch_notification preference set to 1, the controller
// should be observing the UpgradeDetector and should show "Requested"
// notifications on each level change.
TEST_F(RelaunchNotificationControllerTest, RecommendedByPolicy) {
SetNotificationPref(1);
::testing::StrictMock<MockControllerDelegate> mock_controller_delegate;
FakeRelaunchNotificationController controller(upgrade_detector(),
&mock_controller_delegate);
// Nothing shown if the level is broadcast at NONE.
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
// Show for each level change, but not for repeat notifications.
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRecommendedBubble());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_LOW);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_LOW);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRecommendedBubble());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRecommendedBubble());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRecommendedBubble());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRecommendedBubble());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
// And closed if the level drops back to none.
EXPECT_CALL(mock_controller_delegate, CloseRelaunchRecommendedBubble());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
}
// With the browser.relaunch_notification preference set to 2, the controller
// should be observing the UpgradeDetector and should show "Required"
// notifications on each level change.
TEST_F(RelaunchNotificationControllerTest, RequiredByPolicy) {
SetNotificationPref(2);
::testing::StrictMock<MockControllerDelegate> mock_controller_delegate;
FakeRelaunchNotificationController controller(upgrade_detector(),
&mock_controller_delegate);
// Nothing shown if the level is broadcast at NONE.
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
// Show for each level change, but not for repeat notifications.
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRequiredDialog());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_LOW);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_LOW);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRequiredDialog());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRequiredDialog());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRequiredDialog());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRequiredDialog());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
// And closed if the level drops back to none.
EXPECT_CALL(mock_controller_delegate, CloseRelaunchRequiredDialog());
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
}
// Flipping the policy should have no effect when at level NONE
TEST_F(RelaunchNotificationControllerTest, PolicyChangesNoUpgrade) {
::testing::StrictMock<MockControllerDelegate> mock_controller_delegate;
FakeRelaunchNotificationController controller(upgrade_detector(),
&mock_controller_delegate);
SetNotificationPref(1);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
SetNotificationPref(2);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
SetNotificationPref(3); // Bogus value!
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
SetNotificationPref(0);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
}
// Policy changes at an elevated level should show the appropriate notification.
TEST_F(RelaunchNotificationControllerTest, PolicyChangesWithUpgrade) {
::testing::StrictMock<MockControllerDelegate> mock_controller_delegate;
FakeRelaunchNotificationController controller(upgrade_detector(),
&mock_controller_delegate);
fake_upgrade_detector().BroadcastLevelChange(
UpgradeDetector::UPGRADE_ANNOYANCE_LOW);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRecommendedBubble());
SetNotificationPref(1);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, CloseRelaunchRecommendedBubble());
EXPECT_CALL(mock_controller_delegate, ShowRelaunchRequiredDialog());
SetNotificationPref(2);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
EXPECT_CALL(mock_controller_delegate, CloseRelaunchRequiredDialog());
SetNotificationPref(0);
::testing::Mock::VerifyAndClear(&mock_controller_delegate);
}