1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <algorithm>
6 #include <initializer_list>
7 #include <map>
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/callback.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h"
19 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h"
22 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h"
23 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/browser_dialogs.h"
26 #include "chrome/browser/ui/test/test_browser_dialog.h"
27 #include "chrome/browser/ui/views/settings_reset_prompt_dialog.h"
28 #include "content/public/test/browser_test.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "url/gurl.h"
32
33 namespace {
34
35 using safe_browsing::MockProfileResetter;
36 using safe_browsing::MockSettingsResetPromptConfig;
37 using testing::_;
38 using testing::ElementsAre;
39 using testing::NiceMock;
40 using testing::Not;
41 using testing::Return;
42 using testing::ReturnRef;
43
44 constexpr char kHomepageUrl[] = "http://www.some-homepage.com/some/path";
45 constexpr char kSearchUrl[] = "http://www.some-search.com/some/path/?q={%s}";
46 constexpr const char* kStartupUrls[] = {
47 "http://www.some-startup-1.com/some/path",
48 "http://www.some-startup-2.com/some/other/path",
49 "http://www.some-startup-3.com/some/third/path"};
50
51 enum class SettingType {
52 DEFAULT_SEARCH_ENGINE,
53 STARTUP_PAGE,
54 HOMEPAGE,
55 };
56
57 struct ModelParams {
58 SettingType setting_to_reset;
59 size_t startup_pages;
60 };
61
62 class MockSettingsResetPromptModel
63 : public safe_browsing::SettingsResetPromptModel {
64 public:
65 // Create a mock model that pretends that the settings passed in via
66 // |settings_to_reset| require resetting.
MockSettingsResetPromptModel(Profile * profile,const ModelParams & params)67 explicit MockSettingsResetPromptModel(Profile* profile,
68 const ModelParams& params)
69 : SettingsResetPromptModel(
70 profile,
71 std::make_unique<NiceMock<MockSettingsResetPromptConfig>>(),
72 std::make_unique<NiceMock<MockProfileResetter>>(profile)) {
73 EXPECT_LE(params.startup_pages, base::size(kStartupUrls));
74
75 // Set up startup URLs to be returned by member functions based on the
76 // constructor arguments.
77 for (size_t i = 0;
78 i < std::min(base::size(kStartupUrls), params.startup_pages); ++i) {
79 startup_urls_.push_back(GURL(kStartupUrls[i]));
80 }
81
82 if (params.setting_to_reset == SettingType::STARTUP_PAGE)
83 startup_urls_to_reset_ = startup_urls_;
84
85 ON_CALL(*this, ShouldPromptForReset()).WillByDefault(Return(true));
86 ON_CALL(*this, MockPerformReset(_, _)).WillByDefault(Return());
87 ON_CALL(*this, DialogShown()).WillByDefault(Return());
88
89 ON_CALL(*this, homepage()).WillByDefault(Return(GURL(kHomepageUrl)));
90 ON_CALL(*this, homepage_reset_state())
91 .WillByDefault(
92 Return(params.setting_to_reset == SettingType::HOMEPAGE
93 ? RESET_REQUIRED
94 : NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED));
95
96 ON_CALL(*this, default_search()).WillByDefault(Return(GURL(kSearchUrl)));
97 ON_CALL(*this, default_search_reset_state())
98 .WillByDefault(
99 Return(params.setting_to_reset == SettingType::DEFAULT_SEARCH_ENGINE
100 ? RESET_REQUIRED
101 : NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED));
102
103 ON_CALL(*this, startup_urls()).WillByDefault(ReturnRef(startup_urls_));
104 ON_CALL(*this, startup_urls_to_reset())
105 .WillByDefault(ReturnRef(startup_urls_to_reset_));
106 ON_CALL(*this, startup_urls_reset_state())
107 .WillByDefault(
108 Return(params.setting_to_reset == SettingType::STARTUP_PAGE
109 ? RESET_REQUIRED
110 : NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED));
111 }
~MockSettingsResetPromptModel()112 ~MockSettingsResetPromptModel() override {}
113
PerformReset(std::unique_ptr<BrandcodedDefaultSettings> default_settings,base::OnceClosure callback)114 void PerformReset(std::unique_ptr<BrandcodedDefaultSettings> default_settings,
115 base::OnceClosure callback) override {
116 MockPerformReset(default_settings.get(), std::move(callback));
117 }
118 MOCK_METHOD2(MockPerformReset,
119 void(BrandcodedDefaultSettings*, base::OnceClosure));
120 MOCK_CONST_METHOD0(ShouldPromptForReset, bool());
121 MOCK_METHOD0(DialogShown, void());
122 MOCK_CONST_METHOD0(homepage, GURL());
123 MOCK_CONST_METHOD0(homepage_reset_state, ResetState());
124 MOCK_CONST_METHOD0(default_search, GURL());
125 MOCK_CONST_METHOD0(default_search_reset_state, ResetState());
126 MOCK_CONST_METHOD0(startup_urls, const std::vector<GURL>&());
127 MOCK_CONST_METHOD0(startup_urls_to_reset, const std::vector<GURL>&());
128 MOCK_CONST_METHOD0(startup_urls_reset_state, ResetState());
129
130 private:
131 std::vector<GURL> startup_urls_;
132 std::vector<GURL> startup_urls_to_reset_;
133
134 DISALLOW_COPY_AND_ASSIGN(MockSettingsResetPromptModel);
135 };
136
137 class SettingsResetPromptDialogTest : public DialogBrowserTest {
138 public:
ShowUi(const std::string & name)139 void ShowUi(const std::string& name) override {
140 const std::map<std::string, ModelParams> name_to_model_params = {
141 {"DefaultSearchEngineChanged", {SettingType::DEFAULT_SEARCH_ENGINE, 0}},
142 {"SingleStartupPageChanged", {SettingType::STARTUP_PAGE, 1}},
143 {"MultipleStartupPagesChanged", {SettingType::STARTUP_PAGE, 2}},
144 {"HomePageChanged", {SettingType::HOMEPAGE, 0}},
145 };
146
147 ASSERT_NE(name_to_model_params.find(name), name_to_model_params.end());
148 auto model = std::make_unique<NiceMock<MockSettingsResetPromptModel>>(
149 browser()->profile(), name_to_model_params.find(name)->second);
150
151 chrome::ShowSettingsResetPrompt(
152 browser(),
153 new safe_browsing::SettingsResetPromptController(
154 std::move(model), std::make_unique<BrandcodedDefaultSettings>()));
155 }
156 };
157
IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,InvokeUi_DefaultSearchEngineChanged)158 IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,
159 InvokeUi_DefaultSearchEngineChanged) {
160 ShowAndVerifyUi();
161 }
IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,InvokeUi_SingleStartupPageChanged)162 IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,
163 InvokeUi_SingleStartupPageChanged) {
164 ShowAndVerifyUi();
165 }
IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,InvokeUi_MultipleStartupPagesChanged)166 IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,
167 InvokeUi_MultipleStartupPagesChanged) {
168 ShowAndVerifyUi();
169 }
IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,InvokeUi_HomePageChanged)170 IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogTest,
171 InvokeUi_HomePageChanged) {
172 ShowAndVerifyUi();
173 }
174
175 class SettingsResetPromptDialogCloseTest : public DialogBrowserTest {
176 public:
ShowUi(const std::string & name)177 void ShowUi(const std::string& name) override {
178 auto model = std::make_unique<NiceMock<MockSettingsResetPromptModel>>(
179 browser()->profile(),
180 ModelParams{SettingType::DEFAULT_SEARCH_ENGINE, 0});
181
182 dialog_ = new SettingsResetPromptDialog(
183 browser(),
184 new safe_browsing::SettingsResetPromptController(
185 std::move(model), std::make_unique<BrandcodedDefaultSettings>()));
186 dialog_->Show();
187 }
DismissUi()188 void DismissUi() override { dialog_->Close(); }
189
190 private:
191 SettingsResetPromptDialog* dialog_ = nullptr;
192 };
193
IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogCloseTest,InvokeUi_DoNotCrashOnClose)194 IN_PROC_BROWSER_TEST_F(SettingsResetPromptDialogCloseTest,
195 InvokeUi_DoNotCrashOnClose) {
196 ShowAndVerifyUi();
197 }
198
199 } // namespace
200