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