1 // Copyright 2013 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 "chrome/browser/search/instant_service.h"
6 
7 #include <vector>
8 
9 #include "base/files/file_util.h"
10 #include "base/path_service.h"
11 #include "base/task/thread_pool/thread_pool_instance.h"
12 #include "base/test/mock_callback.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/search/background/ntp_background_service.h"
15 #include "chrome/browser/search/instant_service_observer.h"
16 #include "chrome/browser/search/instant_unittest_base.h"
17 #include "chrome/browser/themes/theme_properties.h"
18 #include "chrome/browser/themes/theme_service.h"
19 #include "chrome/browser/themes/theme_service_factory.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/search/instant_types.h"
23 #include "chrome/common/url_constants.h"
24 #include "components/ntp_tiles/features.h"
25 #include "components/ntp_tiles/ntp_tile.h"
26 #include "components/ntp_tiles/section_type.h"
27 #include "components/search/ntp_features.h"
28 #include "components/sync_preferences/testing_pref_service_syncable.h"
29 #include "content/public/test/test_utils.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "ui/native_theme/test_native_theme.h"
33 #include "url/gurl.h"
34 
35 namespace {
36 
37 class MockInstantServiceObserver : public InstantServiceObserver {
38  public:
39   MOCK_METHOD1(NtpThemeChanged, void(const NtpTheme&));
40   MOCK_METHOD1(MostVisitedInfoChanged, void(const InstantMostVisitedInfo&));
41 };
42 
GetBackgroundInfoAsDict(const GURL & background_url)43 base::DictionaryValue GetBackgroundInfoAsDict(const GURL& background_url) {
44   base::DictionaryValue background_info;
45   background_info.SetKey("background_url", base::Value(background_url.spec()));
46   background_info.SetKey("attribution_line_1", base::Value(std::string()));
47   background_info.SetKey("attribution_line_2", base::Value(std::string()));
48   background_info.SetKey("attribution_action_url", base::Value(std::string()));
49   background_info.SetKey("collection_id", base::Value(std::string()));
50   background_info.SetKey("resume_token", base::Value(std::string()));
51   background_info.SetKey("refresh_timestamp", base::Value(0));
52   return background_info;
53 }
54 
GetReferenceTime()55 base::Time GetReferenceTime() {
56   base::Time::Exploded exploded_reference_time;
57   exploded_reference_time.year = 2019;
58   exploded_reference_time.month = 1;
59   exploded_reference_time.day_of_month = 1;
60   exploded_reference_time.day_of_week = 1;
61   exploded_reference_time.hour = 0;
62   exploded_reference_time.minute = 0;
63   exploded_reference_time.second = 0;
64   exploded_reference_time.millisecond = 0;
65 
66   base::Time out_time;
67   EXPECT_TRUE(
68       base::Time::FromLocalExploded(exploded_reference_time, &out_time));
69   return out_time;
70 }
71 
72 class MockInstantService : public InstantService {
73  public:
MockInstantService(Profile * profile)74   explicit MockInstantService(Profile* profile) : InstantService(profile) {}
75   ~MockInstantService() override = default;
76 
77   MOCK_METHOD0(ResetCustomLinks, bool());
78   MOCK_METHOD0(ResetCustomBackgroundNtpTheme, void());
79 };
80 
CheckBackgroundColor(SkColor color,const base::DictionaryValue * background_info)81 bool CheckBackgroundColor(SkColor color,
82                           const base::DictionaryValue* background_info) {
83   if (!background_info)
84     return false;
85 
86   const base::Value* background_color =
87       background_info->FindKey(kNtpCustomBackgroundMainColor);
88   if (!background_color)
89     return false;
90 
91   return color == static_cast<uint32_t>(background_color->GetInt());
92 }
93 }  // namespace
94 
95 using InstantServiceTest = InstantUnitTestBase;
96 
TEST_F(InstantServiceTest,GetNTPTileSuggestion)97 TEST_F(InstantServiceTest, GetNTPTileSuggestion) {
98   ntp_tiles::NTPTile some_tile;
99   some_tile.source = ntp_tiles::TileSource::TOP_SITES;
100   some_tile.title_source = ntp_tiles::TileTitleSource::TITLE_TAG;
101   ntp_tiles::NTPTilesVector suggestions{some_tile};
102 
103   std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector> suggestions_map;
104   suggestions_map[ntp_tiles::SectionType::PERSONALIZED] = suggestions;
105 
106   instant_service_->OnURLsAvailable(suggestions_map);
107 
108   auto items = instant_service_->most_visited_info_->items;
109   ASSERT_EQ(1, (int)items.size());
110   EXPECT_EQ(ntp_tiles::TileSource::TOP_SITES, items[0].source);
111   EXPECT_EQ(ntp_tiles::TileTitleSource::TITLE_TAG, items[0].title_source);
112 }
113 
TEST_F(InstantServiceTest,DoesToggleMostVisitedOrCustomLinks)114 TEST_F(InstantServiceTest, DoesToggleMostVisitedOrCustomLinks) {
115   sync_preferences::TestingPrefServiceSyncable* pref_service =
116       profile()->GetTestingPrefService();
117   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
118   ASSERT_FALSE(pref_service->GetBoolean(prefs::kNtpUseMostVisitedTiles));
119   ASSERT_FALSE(instant_service_->most_visited_info_->use_most_visited);
120 
121   // Enable most visited tiles.
122   EXPECT_TRUE(instant_service_->ToggleMostVisitedOrCustomLinks());
123   EXPECT_TRUE(pref_service->GetBoolean(prefs::kNtpUseMostVisitedTiles));
124   EXPECT_TRUE(instant_service_->most_visited_info_->use_most_visited);
125 
126   // Disable most visited tiles.
127   EXPECT_TRUE(instant_service_->ToggleMostVisitedOrCustomLinks());
128   EXPECT_FALSE(pref_service->GetBoolean(prefs::kNtpUseMostVisitedTiles));
129   EXPECT_FALSE(instant_service_->most_visited_info_->use_most_visited);
130 
131   // Should do nothing if this is a non-Google NTP.
132   SetUserSelectedDefaultSearchProvider("https://www.search.com");
133   EXPECT_FALSE(instant_service_->ToggleMostVisitedOrCustomLinks());
134   EXPECT_FALSE(pref_service->GetBoolean(prefs::kNtpUseMostVisitedTiles));
135   EXPECT_FALSE(instant_service_->most_visited_info_->use_most_visited);
136 }
137 
TEST_F(InstantServiceTest,DoesToggleShortcutsVisibility)138 TEST_F(InstantServiceTest, DoesToggleShortcutsVisibility) {
139   testing::StrictMock<MockInstantServiceObserver> mock_observer;
140   instant_service_->AddObserver(&mock_observer);
141 
142   sync_preferences::TestingPrefServiceSyncable* pref_service =
143       profile()->GetTestingPrefService();
144   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
145   ASSERT_TRUE(pref_service->GetBoolean(prefs::kNtpShortcutsVisible));
146   ASSERT_TRUE(instant_service_->most_visited_info_->is_visible);
147 
148   // Hide shortcuts.
149   EXPECT_CALL(mock_observer, MostVisitedInfoChanged(testing::_)).Times(0);
150   EXPECT_TRUE(instant_service_->ToggleShortcutsVisibility(false));
151   EXPECT_FALSE(pref_service->GetBoolean(prefs::kNtpShortcutsVisible));
152   EXPECT_FALSE(instant_service_->most_visited_info_->is_visible);
153   task_environment()->RunUntilIdle();
154 
155   // Show shortcuts, and check that a notification was sent.
156   EXPECT_CALL(mock_observer, MostVisitedInfoChanged(testing::_)).Times(1);
157   EXPECT_TRUE(instant_service_->ToggleShortcutsVisibility(true));
158   EXPECT_TRUE(pref_service->GetBoolean(prefs::kNtpShortcutsVisible));
159   EXPECT_TRUE(instant_service_->most_visited_info_->is_visible);
160 
161   // Should do nothing if this is a non-Google NTP.
162   EXPECT_CALL(mock_observer, MostVisitedInfoChanged(testing::_)).Times(0);
163   SetUserSelectedDefaultSearchProvider("https://www.search.com");
164   EXPECT_FALSE(instant_service_->ToggleShortcutsVisibility(false));
165   EXPECT_TRUE(pref_service->GetBoolean(prefs::kNtpShortcutsVisible));
166   EXPECT_TRUE(instant_service_->most_visited_info_->is_visible);
167 }
168 
TEST_F(InstantServiceTest,DisableUndoCustomLinkActionForNonGoogleSearchProvider)169 TEST_F(InstantServiceTest,
170        DisableUndoCustomLinkActionForNonGoogleSearchProvider) {
171   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
172   EXPECT_TRUE(instant_service_->UndoCustomLinkAction());
173 
174   SetUserSelectedDefaultSearchProvider("https://www.search.com");
175   EXPECT_FALSE(instant_service_->UndoCustomLinkAction());
176 }
177 
TEST_F(InstantServiceTest,DisableResetCustomLinksForNonGoogleSearchProvider)178 TEST_F(InstantServiceTest, DisableResetCustomLinksForNonGoogleSearchProvider) {
179   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
180   EXPECT_TRUE(instant_service_->ResetCustomLinks());
181 
182   SetUserSelectedDefaultSearchProvider("https://www.search.com");
183   EXPECT_FALSE(instant_service_->ResetCustomLinks());
184 }
185 
TEST_F(InstantServiceTest,IsCustomLinksEnabled)186 TEST_F(InstantServiceTest, IsCustomLinksEnabled) {
187   sync_preferences::TestingPrefServiceSyncable* pref_service =
188       profile()->GetTestingPrefService();
189 
190   // Test that custom links are only enabled when Most Visited is toggled off
191   // and this is a Google NTP.
192   pref_service->SetBoolean(prefs::kNtpUseMostVisitedTiles, false);
193   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
194   EXPECT_TRUE(instant_service_->IsCustomLinksEnabled());
195 
196   // All other cases should return false.
197   SetUserSelectedDefaultSearchProvider("https://www.search.com");
198   EXPECT_FALSE(instant_service_->IsCustomLinksEnabled());
199   pref_service->SetBoolean(prefs::kNtpUseMostVisitedTiles, true);
200   EXPECT_FALSE(instant_service_->IsCustomLinksEnabled());
201   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
202   EXPECT_FALSE(instant_service_->IsCustomLinksEnabled());
203 }
204 
TEST_F(InstantServiceTest,SetCustomBackgroundURL)205 TEST_F(InstantServiceTest, SetCustomBackgroundURL) {
206   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
207   const GURL kUrl("https://www.foo.com");
208 
209   instant_service_->AddValidBackdropUrlForTesting(kUrl);
210   instant_service_->SetCustomBackgroundInfo(kUrl, "", "", GURL(), "");
211 
212   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
213   EXPECT_EQ(kUrl, theme->custom_background_url);
214   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
215 }
216 
TEST_F(InstantServiceTest,SetCustomBackgroundURLInvalidURL)217 TEST_F(InstantServiceTest, SetCustomBackgroundURLInvalidURL) {
218   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
219   const GURL kInvalidUrl("foo");
220   const GURL kValidUrl("https://www.foo.com");
221   instant_service_->AddValidBackdropUrlForTesting(kValidUrl);
222   instant_service_->SetCustomBackgroundInfo(kValidUrl, "", "", GURL(), "");
223 
224   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
225   EXPECT_EQ(kValidUrl.spec(), theme->custom_background_url.spec());
226 
227   instant_service_->SetCustomBackgroundInfo(kInvalidUrl, "", "", GURL(), "");
228 
229   theme = instant_service_->GetInitializedNtpTheme();
230   EXPECT_EQ("", theme->custom_background_url.spec());
231   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
232 }
233 
TEST_F(InstantServiceTest,SetCustomBackgroundInfo)234 TEST_F(InstantServiceTest, SetCustomBackgroundInfo) {
235   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
236   const GURL kUrl("https://www.foo.com");
237   const std::string kAttributionLine1 = "foo";
238   const std::string kAttributionLine2 = "bar";
239   const GURL kActionUrl("https://www.bar.com");
240   instant_service_->AddValidBackdropUrlForTesting(kUrl);
241   instant_service_->SetCustomBackgroundInfo(kUrl, kAttributionLine1,
242                                             kAttributionLine2, kActionUrl, "");
243 
244   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
245   EXPECT_EQ(kUrl, theme->custom_background_url);
246   EXPECT_EQ(kAttributionLine1, theme->custom_background_attribution_line_1);
247   EXPECT_EQ(kAttributionLine2, theme->custom_background_attribution_line_2);
248   EXPECT_EQ(kActionUrl, theme->custom_background_attribution_action_url);
249   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
250 }
251 
TEST_F(InstantServiceTest,ChangingSearchProviderClearsNtpThemeAndPref)252 TEST_F(InstantServiceTest, ChangingSearchProviderClearsNtpThemeAndPref) {
253   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
254   const GURL kUrl("https://www.foo.com");
255   const std::string kAttributionLine1 = "foo";
256   const std::string kAttributionLine2 = "bar";
257   const GURL kActionUrl("https://www.bar.com");
258 
259   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
260   instant_service_->AddValidBackdropUrlForTesting(kUrl);
261   instant_service_->SetCustomBackgroundInfo(kUrl, kAttributionLine1,
262                                             kAttributionLine2, kActionUrl, "");
263 
264   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
265   EXPECT_EQ(kUrl, theme->custom_background_url);
266   EXPECT_EQ(kAttributionLine1, theme->custom_background_attribution_line_1);
267   EXPECT_EQ(kAttributionLine2, theme->custom_background_attribution_line_2);
268   EXPECT_EQ(kActionUrl, theme->custom_background_attribution_action_url);
269   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
270 
271   SetUserSelectedDefaultSearchProvider("https://www.search.com");
272   instant_service_->UpdateNtpTheme();
273 
274   theme = instant_service_->GetInitializedNtpTheme();
275   EXPECT_EQ(GURL(), theme->custom_background_url);
276   EXPECT_EQ("", theme->custom_background_attribution_line_1);
277   EXPECT_EQ("", theme->custom_background_attribution_line_2);
278   EXPECT_EQ(GURL(), theme->custom_background_attribution_action_url);
279   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
280 
281   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
282   instant_service_->UpdateNtpTheme();
283 
284   theme = instant_service_->GetInitializedNtpTheme();
285   EXPECT_EQ(GURL(), theme->custom_background_url);
286   EXPECT_EQ("", theme->custom_background_attribution_line_1);
287   EXPECT_EQ("", theme->custom_background_attribution_line_2);
288   EXPECT_EQ(GURL(), theme->custom_background_attribution_action_url);
289   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
290 }
291 
TEST_F(InstantServiceTest,LocalBackgroundImageCopyCreated)292 TEST_F(InstantServiceTest, LocalBackgroundImageCopyCreated) {
293   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
294   const GURL kUrl("chrome-search://local-ntp/background.jpg");
295 
296   base::FilePath profile_path = profile()->GetPath();
297   base::FilePath path(profile_path.AppendASCII("test_file"));
298   base::FilePath copy_path(profile_path.AppendASCII(
299       chrome::kChromeSearchLocalNtpBackgroundFilename));
300 
301   base::WriteFile(path, "background_image", 16);
302 
303   instant_service_->SelectLocalBackgroundImage(path);
304 
305   task_environment()->RunUntilIdle();
306 
307   bool file_exists = base::PathExists(copy_path);
308 
309   EXPECT_EQ(true, file_exists);
310   EXPECT_EQ(true, profile()->GetTestingPrefService()->GetBoolean(
311                       prefs::kNtpCustomBackgroundLocalToDevice));
312   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
313 }
314 
TEST_F(InstantServiceTest,ChangingSearchProviderRemovesLocalBackgroundImageCopy)315 TEST_F(InstantServiceTest,
316        ChangingSearchProviderRemovesLocalBackgroundImageCopy) {
317   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
318   base::FilePath profile_path = profile()->GetPath();
319   base::FilePath path(profile_path.AppendASCII(
320       chrome::kChromeSearchLocalNtpBackgroundFilename));
321 
322   base::WriteFile(path, "background_image", 16);
323 
324   SetUserSelectedDefaultSearchProvider("https://www.search.com");
325   instant_service_->UpdateNtpTheme();
326 
327   task_environment()->RunUntilIdle();
328 
329   bool file_exists = base::PathExists(path);
330 
331   EXPECT_EQ(false, file_exists);
332   EXPECT_EQ(false, profile()->GetTestingPrefService()->GetBoolean(
333                        prefs::kNtpCustomBackgroundLocalToDevice));
334   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
335 }
336 
TEST_F(InstantServiceTest,SettingUrlRemovesLocalBackgroundImageCopy)337 TEST_F(InstantServiceTest, SettingUrlRemovesLocalBackgroundImageCopy) {
338   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
339   const GURL kUrl("https://www.foo.com");
340 
341   base::FilePath profile_path = profile()->GetPath();
342   base::FilePath path(profile_path.AppendASCII(
343       chrome::kChromeSearchLocalNtpBackgroundFilename));
344 
345   base::WriteFile(path, "background_image", 16);
346 
347   instant_service_->AddValidBackdropUrlForTesting(kUrl);
348   instant_service_->SetCustomBackgroundInfo(kUrl, "", "", GURL(), "");
349   instant_service_->UpdateNtpTheme();
350 
351   task_environment()->RunUntilIdle();
352 
353   bool file_exists = base::PathExists(path);
354 
355   EXPECT_EQ(false, file_exists);
356   EXPECT_EQ(false, profile()->GetTestingPrefService()->GetBoolean(
357                        prefs::kNtpCustomBackgroundLocalToDevice));
358   ASSERT_TRUE(instant_service_->IsCustomBackgroundSet());
359 }
360 
TEST_F(InstantServiceTest,CustomBackgroundAttributionActionUrlReset)361 TEST_F(InstantServiceTest, CustomBackgroundAttributionActionUrlReset) {
362   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
363   const GURL kUrl("https://www.foo.com");
364   const std::string kAttributionLine1 = "foo";
365   const std::string kAttributionLine2 = "bar";
366   const GURL kHttpsActionUrl("https://www.bar.com");
367   const GURL kHttpActionUrl("http://www.bar.com");
368 
369   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
370   instant_service_->AddValidBackdropUrlForTesting(kUrl);
371   instant_service_->SetCustomBackgroundInfo(
372       kUrl, kAttributionLine1, kAttributionLine2, kHttpsActionUrl, "");
373 
374   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
375   EXPECT_EQ(kHttpsActionUrl, theme->custom_background_attribution_action_url);
376   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
377 
378   instant_service_->SetCustomBackgroundInfo(
379       kUrl, kAttributionLine1, kAttributionLine2, kHttpActionUrl, "");
380 
381   theme = instant_service_->GetInitializedNtpTheme();
382   EXPECT_EQ(GURL(), theme->custom_background_attribution_action_url);
383   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
384 
385   instant_service_->SetCustomBackgroundInfo(
386       kUrl, kAttributionLine1, kAttributionLine2, kHttpsActionUrl, "");
387 
388   theme = instant_service_->GetInitializedNtpTheme();
389   EXPECT_EQ(kHttpsActionUrl, theme->custom_background_attribution_action_url);
390   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
391 
392   instant_service_->SetCustomBackgroundInfo(kUrl, kAttributionLine1,
393                                             kAttributionLine2, GURL(), "");
394 
395   theme = instant_service_->GetInitializedNtpTheme();
396   EXPECT_EQ(GURL(), theme->custom_background_attribution_action_url);
397   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
398 }
399 
TEST_F(InstantServiceTest,UpdatingPrefUpdatesNtpTheme)400 TEST_F(InstantServiceTest, UpdatingPrefUpdatesNtpTheme) {
401   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
402   const GURL kUrlFoo("https://www.foo.com");
403   const GURL kUrlBar("https://www.bar.com");
404 
405   sync_preferences::TestingPrefServiceSyncable* pref_service =
406       profile()->GetTestingPrefService();
407   pref_service->SetUserPref(
408       prefs::kNtpCustomBackgroundDict,
409       std::make_unique<base::Value>(GetBackgroundInfoAsDict(kUrlFoo)));
410 
411   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
412   EXPECT_EQ(kUrlFoo, theme->custom_background_url);
413   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
414 
415   pref_service->SetUserPref(
416       prefs::kNtpCustomBackgroundDict,
417       std::make_unique<base::Value>(GetBackgroundInfoAsDict(kUrlBar)));
418 
419   theme = instant_service_->GetInitializedNtpTheme();
420   EXPECT_EQ(kUrlBar, theme->custom_background_url);
421   EXPECT_EQ(false,
422             pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice));
423   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
424 }
425 
TEST_F(InstantServiceTest,SetLocalImage)426 TEST_F(InstantServiceTest, SetLocalImage) {
427   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
428   const GURL kUrl("chrome-search://local-ntp/background.jpg?123456789");
429 
430   sync_preferences::TestingPrefServiceSyncable* pref_service =
431       profile()->GetTestingPrefService();
432 
433   base::FilePath profile_path = profile()->GetPath();
434   base::FilePath path(profile_path.AppendASCII(
435       chrome::kChromeSearchLocalNtpBackgroundFilename));
436   base::WriteFile(path, "background_image", 16);
437   base::ThreadPoolInstance::Get()->FlushForTesting();
438 
439   instant_service_->SelectLocalBackgroundImage(path);
440   task_environment()->RunUntilIdle();
441 
442   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
443   EXPECT_TRUE(base::StartsWith(theme->custom_background_url.spec(),
444                                chrome::kChromeSearchLocalNtpBackgroundUrl,
445                                base::CompareCase::SENSITIVE));
446   EXPECT_TRUE(
447       pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice));
448   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
449 }
450 
TEST_F(InstantServiceTest,SyncPrefOverridesAndRemovesLocalImage)451 TEST_F(InstantServiceTest, SyncPrefOverridesAndRemovesLocalImage) {
452   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
453   const GURL kUrl("https://www.foo.com/");
454 
455   sync_preferences::TestingPrefServiceSyncable* pref_service =
456       profile()->GetTestingPrefService();
457 
458   base::FilePath profile_path = profile()->GetPath();
459   base::FilePath path(profile_path.AppendASCII(
460       chrome::kChromeSearchLocalNtpBackgroundFilename));
461   base::WriteFile(path, "background_image", 16);
462   base::ThreadPoolInstance::Get()->FlushForTesting();
463 
464   instant_service_->SelectLocalBackgroundImage(path);
465   task_environment()->RunUntilIdle();
466 
467   EXPECT_TRUE(
468       pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice));
469   EXPECT_TRUE(base::PathExists(path));
470 
471   // Update theme info via Sync.
472   pref_service->SetUserPref(
473       prefs::kNtpCustomBackgroundDict,
474       std::make_unique<base::Value>(GetBackgroundInfoAsDict(kUrl)));
475   task_environment()->RunUntilIdle();
476 
477   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
478   EXPECT_EQ(kUrl, theme->custom_background_url);
479   EXPECT_FALSE(
480       pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice));
481   EXPECT_FALSE(base::PathExists(path));
482   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
483 }
484 
TEST_F(InstantServiceTest,ValidateBackdropUrls)485 TEST_F(InstantServiceTest, ValidateBackdropUrls) {
486   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
487   const GURL kBackdropUrl1("https://www.foo.com");
488   const GURL kBackdropUrl2("https://www.bar.com");
489   const GURL kNonBackdropUrl1("https://www.test.com");
490   const GURL kNonBackdropUrl2("https://www.foo.com/path");
491 
492   instant_service_->AddValidBackdropUrlForTesting(kBackdropUrl1);
493   instant_service_->AddValidBackdropUrlForTesting(kBackdropUrl2);
494 
495   instant_service_->SetCustomBackgroundInfo(kBackdropUrl1, "", "", GURL(), "");
496   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
497   EXPECT_EQ(kBackdropUrl1, theme->custom_background_url);
498   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
499 
500   instant_service_->SetCustomBackgroundInfo(kNonBackdropUrl1, "", "", GURL(),
501                                             "");
502   theme = instant_service_->GetInitializedNtpTheme();
503   EXPECT_EQ(GURL(), theme->custom_background_url);
504   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
505 
506   instant_service_->SetCustomBackgroundInfo(kBackdropUrl2, "", "", GURL(), "");
507   theme = instant_service_->GetInitializedNtpTheme();
508   EXPECT_EQ(kBackdropUrl2, theme->custom_background_url);
509   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
510 
511   instant_service_->SetCustomBackgroundInfo(kNonBackdropUrl2, "", "", GURL(),
512                                             "");
513   theme = instant_service_->GetInitializedNtpTheme();
514   EXPECT_EQ(GURL(), theme->custom_background_url);
515   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
516 }
517 
TEST_F(InstantServiceTest,TestNoNtpTheme)518 TEST_F(InstantServiceTest, TestNoNtpTheme) {
519   instant_service_->theme_ = nullptr;
520   EXPECT_NE(nullptr, instant_service_->GetInitializedNtpTheme());
521 
522   instant_service_->theme_ = nullptr;
523   // As |FallbackToDefaultNtpTheme| uses |theme_| it should initialize it
524   // otherwise the test should crash.
525   instant_service_->FallbackToDefaultNtpTheme();
526   EXPECT_NE(nullptr, instant_service_->theme_);
527 }
528 
TEST_F(InstantServiceTest,TestResetToDefault)529 TEST_F(InstantServiceTest, TestResetToDefault) {
530   MockInstantService mock_instant_service_(profile());
531   EXPECT_CALL(mock_instant_service_, ResetCustomLinks());
532   EXPECT_CALL(mock_instant_service_, ResetCustomBackgroundNtpTheme());
533   mock_instant_service_.ResetToDefault();
534 }
535 
536 class InstantServiceThemeTest : public InstantServiceTest {
537  public:
InstantServiceThemeTest()538   InstantServiceThemeTest() {}
~InstantServiceThemeTest()539   ~InstantServiceThemeTest() override {}
540 
theme()541   ui::TestNativeTheme* theme() { return &theme_; }
542 
543  private:
544   ui::TestNativeTheme theme_;
545 
546   DISALLOW_COPY_AND_ASSIGN(InstantServiceThemeTest);
547 };
548 
TEST_F(InstantServiceTest,LocalImageDoesNotHaveAttribution)549 TEST_F(InstantServiceTest, LocalImageDoesNotHaveAttribution) {
550   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
551   const GURL kUrl("https://www.foo.com");
552   const std::string kAttributionLine1 = "foo";
553   const std::string kAttributionLine2 = "bar";
554   const GURL kActionUrl("https://www.bar.com");
555 
556   sync_preferences::TestingPrefServiceSyncable* pref_service =
557       profile()->GetTestingPrefService();
558   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
559   instant_service_->AddValidBackdropUrlForTesting(kUrl);
560   instant_service_->SetCustomBackgroundInfo(kUrl, kAttributionLine1,
561                                             kAttributionLine2, kActionUrl, "");
562 
563   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
564   ASSERT_EQ(kAttributionLine1, theme->custom_background_attribution_line_1);
565   ASSERT_EQ(kAttributionLine2, theme->custom_background_attribution_line_2);
566   ASSERT_EQ(kActionUrl, theme->custom_background_attribution_action_url);
567   ASSERT_TRUE(instant_service_->IsCustomBackgroundSet());
568 
569   base::FilePath profile_path = profile()->GetPath();
570   base::FilePath path(profile_path.AppendASCII(
571       chrome::kChromeSearchLocalNtpBackgroundFilename));
572   base::WriteFile(path, "background_image", 16);
573   base::ThreadPoolInstance::Get()->FlushForTesting();
574 
575   instant_service_->SelectLocalBackgroundImage(path);
576   task_environment()->RunUntilIdle();
577 
578   theme = instant_service_->GetInitializedNtpTheme();
579   EXPECT_TRUE(base::StartsWith(theme->custom_background_url.spec(),
580                                chrome::kChromeSearchLocalNtpBackgroundUrl,
581                                base::CompareCase::SENSITIVE));
582   EXPECT_TRUE(
583       pref_service->GetBoolean(prefs::kNtpCustomBackgroundLocalToDevice));
584   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
585   EXPECT_EQ("", theme->custom_background_attribution_line_1);
586   EXPECT_EQ("", theme->custom_background_attribution_line_2);
587   EXPECT_EQ(GURL(), theme->custom_background_attribution_action_url);
588 }
589 
TEST_F(InstantServiceTest,TestUpdateCustomBackgroundColor)590 TEST_F(InstantServiceTest, TestUpdateCustomBackgroundColor) {
591   SkBitmap bitmap;
592   bitmap.allocN32Pixels(32, 32);
593   bitmap.eraseColor(SK_ColorRED);
594   gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap);
595   sync_preferences::TestingPrefServiceSyncable* pref_service =
596       profile()->GetTestingPrefService();
597 
598   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
599 
600   // Background color will not update if no background is set.
601   instant_service_->UpdateCustomBackgroundColorAsync(
602       base::TimeTicks::Now(), image, image_fetcher::RequestMetadata());
603   task_environment()->RunUntilIdle();
604   EXPECT_FALSE(CheckBackgroundColor(
605       SK_ColorRED,
606       pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict)));
607 
608   const GURL kUrl("https://www.foo.com");
609   const std::string kAttributionLine1 = "foo";
610   const std::string kAttributionLine2 = "bar";
611   const GURL kActionUrl("https://www.bar.com");
612 
613   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
614   instant_service_->AddValidBackdropUrlForTesting(kUrl);
615   instant_service_->SetCustomBackgroundInfo(kUrl, kAttributionLine1,
616                                             kAttributionLine2, kActionUrl, "");
617 
618   // Background color will not update if background timestamp has changed.
619   instant_service_->UpdateCustomBackgroundColorAsync(
620       base::TimeTicks::Now(), image, image_fetcher::RequestMetadata());
621   task_environment()->RunUntilIdle();
622   EXPECT_FALSE(CheckBackgroundColor(
623       SK_ColorRED,
624       pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict)));
625 
626   // Background color should update.
627   instant_service_->UpdateCustomBackgroundColorAsync(
628       instant_service_->GetBackgroundUpdatedTimestampForTesting(), image,
629       image_fetcher::RequestMetadata());
630   task_environment()->RunUntilIdle();
631   EXPECT_TRUE(CheckBackgroundColor(
632       SK_ColorRED,
633       pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict)));
634 }
635 
TEST_F(InstantServiceTest,LocalImageDoesNotUpdateCustomBackgroundColor)636 TEST_F(InstantServiceTest, LocalImageDoesNotUpdateCustomBackgroundColor) {
637   SkBitmap bitmap;
638   bitmap.allocN32Pixels(32, 32);
639   bitmap.eraseColor(SK_ColorRED);
640   gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap);
641   sync_preferences::TestingPrefServiceSyncable* pref_service =
642       profile()->GetTestingPrefService();
643 
644   base::FilePath profile_path = profile()->GetPath();
645   base::FilePath path(profile_path.AppendASCII("test_file"));
646   base::FilePath copy_path(profile_path.AppendASCII(
647       chrome::kChromeSearchLocalNtpBackgroundFilename));
648   base::WriteFile(path, "background_image", 16);
649 
650   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
651 
652   const GURL kUrl("https://www.foo.com");
653   const std::string kAttributionLine1 = "foo";
654   const std::string kAttributionLine2 = "bar";
655   const GURL kActionUrl("https://www.bar.com");
656 
657   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
658   instant_service_->AddValidBackdropUrlForTesting(kUrl);
659   instant_service_->SetCustomBackgroundInfo(kUrl, kAttributionLine1,
660                                             kAttributionLine2, kActionUrl, "");
661   base::TimeTicks time_set =
662       instant_service_->GetBackgroundUpdatedTimestampForTesting();
663 
664   instant_service_->SelectLocalBackgroundImage(path);
665   task_environment()->RunUntilIdle();
666 
667   // Background color will not update if a local image was uploaded in the
668   // meantime.
669   instant_service_->UpdateCustomBackgroundColorAsync(
670       time_set, image, image_fetcher::RequestMetadata());
671   task_environment()->RunUntilIdle();
672   EXPECT_FALSE(CheckBackgroundColor(
673       SK_ColorRED,
674       pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict)));
675 }
676 
TEST_F(InstantServiceTest,SetCustomBackgroundCollectionId)677 TEST_F(InstantServiceTest, SetCustomBackgroundCollectionId) {
678   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
679   const std::string kInvalidId("aarrtt");
680   const std::string kValidId("art");
681 
682   // A valid id should update the pref/background.
683   CollectionImage image;
684   image.collection_id = kValidId;
685   image.image_url = GURL("https://www.test.com/");
686   instant_service_->SetNextCollectionImageForTesting(image);
687 
688   instant_service_->AddValidBackdropCollectionForTesting(kValidId);
689   instant_service_->SetCustomBackgroundInfo(GURL(), "", "", GURL(), kValidId);
690   task_environment()->RunUntilIdle();
691 
692   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
693   EXPECT_EQ(kValidId, theme->collection_id);
694   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
695 
696   // An invalid id should clear the pref/background.
697   CollectionImage image2;
698   instant_service_->SetNextCollectionImageForTesting(image2);
699   instant_service_->SetCustomBackgroundInfo(GURL(), "", "", GURL(), kInvalidId);
700   task_environment()->RunUntilIdle();
701 
702   theme = instant_service_->GetInitializedNtpTheme();
703   EXPECT_EQ(std::string(), theme->collection_id);
704   EXPECT_FALSE(instant_service_->IsCustomBackgroundSet());
705 }
706 
TEST_F(InstantServiceTest,CollectionIdTakePriorityOverBackgroundURL)707 TEST_F(InstantServiceTest, CollectionIdTakePriorityOverBackgroundURL) {
708   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
709   const std::string kValidId("art");
710   const GURL kUrl("https://www.foo.com/");
711 
712   CollectionImage image;
713   image.collection_id = kValidId;
714   image.image_url = GURL("https://www.test.com/");
715   instant_service_->SetNextCollectionImageForTesting(image);
716   instant_service_->AddValidBackdropUrlForTesting(kUrl);
717   instant_service_->AddValidBackdropCollectionForTesting(kValidId);
718 
719   instant_service_->SetCustomBackgroundInfo(kUrl, "", "", GURL(), kValidId);
720   task_environment()->RunUntilIdle();
721 
722   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
723   EXPECT_EQ(kValidId, theme->collection_id);
724   EXPECT_EQ("https://www.test.com/", theme->custom_background_url);
725   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
726 }
727 
TEST_F(InstantServiceTest,RefreshesBackgroundAfter24Hours)728 TEST_F(InstantServiceTest, RefreshesBackgroundAfter24Hours) {
729   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
730   const std::string kValidId("art");
731   const GURL kImageUrl1("https://www.test.com/1/");
732   const GURL kImageUrl2("https://www.test.com/2/");
733 
734   instant_service_->SetClockForTesting(clock_);
735   clock_->SetNow(GetReferenceTime());
736 
737   // A valid id should update the pref/background.
738   CollectionImage image;
739   image.collection_id = kValidId;
740   image.image_url = kImageUrl1;
741   instant_service_->SetNextCollectionImageForTesting(image);
742 
743   instant_service_->AddValidBackdropCollectionForTesting(kValidId);
744   instant_service_->SetCustomBackgroundInfo(GURL(), "", "", GURL(), kValidId);
745   task_environment()->RunUntilIdle();
746 
747   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
748   EXPECT_EQ(kValidId, theme->collection_id);
749   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
750 
751   CollectionImage image2;
752   image2.collection_id = kValidId;
753   image2.image_url = kImageUrl2;
754   instant_service_->SetNextCollectionImageForTesting(image2);
755 
756   // Should not refresh background.
757   theme = instant_service_->GetInitializedNtpTheme();
758   task_environment()->RunUntilIdle();
759   EXPECT_EQ(kValidId, theme->collection_id);
760   EXPECT_EQ(kImageUrl1, theme->custom_background_url);
761   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
762 
763   clock_->Advance(base::TimeDelta::FromHours(25));
764 
765   // Should refresh background after >24 hours.
766   theme = instant_service_->GetInitializedNtpTheme();
767   task_environment()->RunUntilIdle();
768   EXPECT_EQ(kValidId, theme->collection_id);
769   EXPECT_EQ(kImageUrl2, theme->custom_background_url);
770   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
771 }
772 
TEST_F(InstantServiceTest,SetNTPElementsNtpTheme)773 TEST_F(InstantServiceTest, SetNTPElementsNtpTheme) {
774   const auto& theme_provider =
775       ThemeService::GetThemeProviderForProfile(profile());
776   SkColor default_text_color =
777       theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT);
778   SkColor default_logo_color =
779       theme_provider.GetColor(ThemeProperties::COLOR_NTP_LOGO);
780   SkColor default_shortcut_color =
781       theme_provider.GetColor(ThemeProperties::COLOR_NTP_SHORTCUT);
782 
783   ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
784 
785   // Check defaults when no theme and no custom backgrounds is set.
786   NtpTheme* theme = instant_service_->GetInitializedNtpTheme();
787   EXPECT_EQ(default_text_color, theme->text_color);
788   EXPECT_FALSE(theme->logo_alternate);
789   EXPECT_EQ(default_logo_color, theme->logo_color);
790   EXPECT_EQ(default_shortcut_color, theme->shortcut_color);
791 
792   // Install colors, theme update should trigger SetNTPElementsNtpTheme() and
793   // update NTP themed elements info.
794   ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile());
795   content::WindowedNotificationObserver theme_change_observer(
796       chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
797       content::Source<ThemeService>(theme_service));
798   theme_service->BuildAutogeneratedThemeFromColor(SK_ColorRED);
799   theme_change_observer.Wait();
800 
801   theme = instant_service_->GetInitializedNtpTheme();
802   EXPECT_NE(default_text_color, theme->text_color);
803   EXPECT_TRUE(theme->logo_alternate);
804   EXPECT_NE(default_logo_color, theme->logo_color);
805   EXPECT_NE(default_shortcut_color, theme->shortcut_color);
806 
807   // Setting a custom background should call SetNTPElementsNtpTheme() and
808   // update NTP themed elements info.
809   const GURL kUrl("https://www.foo.com");
810   instant_service_->AddValidBackdropUrlForTesting(kUrl);
811   instant_service_->SetCustomBackgroundInfo(kUrl, "", "", GURL(), "");
812   ASSERT_TRUE(instant_service_->IsCustomBackgroundSet());
813 
814   theme = instant_service_->GetInitializedNtpTheme();
815   EXPECT_NE(default_text_color, theme->text_color);
816   EXPECT_TRUE(theme->logo_alternate);
817   EXPECT_EQ(default_logo_color, theme->logo_color);
818   // The shortcut color with a background set should always use the light mode
819   // default regardless of system setting.
820   EXPECT_EQ(ThemeProperties::GetDefaultColor(
821                 ThemeProperties::COLOR_NTP_SHORTCUT, false),
822             theme->shortcut_color);
823 }
824