1 // Copyright 2020 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/ui/webui/settings/chromeos/ambient_mode_handler.h"
6 
7 #include <memory>
8 
9 #include "ash/public/cpp/ambient/common/ambient_settings.h"
10 #include "ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h"
11 #include "ash/public/cpp/test/test_image_downloader.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "chrome/test/base/browser_with_test_window_test.h"
14 #include "content/public/test/test_web_ui.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace chromeos {
18 
19 namespace settings {
20 
21 namespace {
22 
23 const char kWebCallbackFunctionName[] = "cr.webUIListenerCallback";
24 
25 class TestAmbientModeHandler : public AmbientModeHandler {
26  public:
27   TestAmbientModeHandler() = default;
28   ~TestAmbientModeHandler() override = default;
29 
30   // Make public for testing.
31   using AmbientModeHandler::AllowJavascript;
32   using AmbientModeHandler::RegisterMessages;
33   using AmbientModeHandler::set_web_ui;
34 };
35 
36 }  // namespace
37 
38 class AmbientModeHandlerTest : public testing::Test {
39  public:
40   AmbientModeHandlerTest() = default;
41   ~AmbientModeHandlerTest() override = default;
42 
SetUp()43   void SetUp() override {
44     web_ui_ = std::make_unique<content::TestWebUI>();
45     handler_ = std::make_unique<TestAmbientModeHandler>();
46     handler_->set_web_ui(web_ui_.get());
47     handler_->RegisterMessages();
48     handler_->AllowJavascript();
49     fake_backend_controller_ =
50         std::make_unique<ash::FakeAmbientBackendControllerImpl>();
51     image_downloader_ = std::make_unique<ash::TestImageDownloader>();
52   }
53 
web_ui()54   content::TestWebUI* web_ui() { return web_ui_.get(); }
55 
histogram_tester() const56   const base::HistogramTester& histogram_tester() const {
57     return histogram_tester_;
58   }
59 
SetTopicSource(ash::AmbientModeTopicSource topic_source)60   void SetTopicSource(ash::AmbientModeTopicSource topic_source) {
61     if (!handler_->settings_)
62       handler_->settings_ = ash::AmbientSettings();
63 
64     handler_->settings_->topic_source = topic_source;
65   }
66 
RequestSettings()67   void RequestSettings() {
68     base::ListValue args;
69     handler_->HandleRequestSettings(&args);
70   }
71 
RequestAlbums(ash::AmbientModeTopicSource topic_source)72   void RequestAlbums(ash::AmbientModeTopicSource topic_source) {
73     base::ListValue args;
74     args.Append(static_cast<int>(topic_source));
75     handler_->HandleRequestAlbums(&args);
76   }
77 
HandleSetSelectedAlbums(const base::ListValue * args)78   void HandleSetSelectedAlbums(const base::ListValue* args) {
79     handler_->HandleSetSelectedAlbums(args);
80   }
81 
FetchSettings()82   void FetchSettings() {
83     handler_->RequestSettingsAndAlbums(/*topic_source=*/base::nullopt);
84   }
85 
UpdateSettings()86   void UpdateSettings() {
87     if (!handler_->settings_)
88       handler_->settings_ = ash::AmbientSettings();
89 
90     handler_->UpdateSettings();
91   }
92 
HasPendingFetchRequestAtHandler() const93   bool HasPendingFetchRequestAtHandler() const {
94     return handler_->has_pending_fetch_request_;
95   }
96 
IsUpdateSettingsPendingAtHandler() const97   bool IsUpdateSettingsPendingAtHandler() const {
98     return handler_->is_updating_backend_;
99   }
100 
HasPendingUpdatesAtHandler() const101   bool HasPendingUpdatesAtHandler() const {
102     return handler_->has_pending_updates_for_backend_;
103   }
104 
GetFetchSettingsDelay()105   base::TimeDelta GetFetchSettingsDelay() {
106     return handler_->fetch_settings_retry_backoff_.GetTimeUntilRelease();
107   }
108 
GetUpdateSettingsDelay()109   base::TimeDelta GetUpdateSettingsDelay() {
110     return handler_->update_settings_retry_backoff_.GetTimeUntilRelease();
111   }
112 
FastForwardBy(base::TimeDelta time)113   void FastForwardBy(base::TimeDelta time) {
114     task_environment_.FastForwardBy(time);
115   }
116 
IsFetchSettingsPendingAtBackend() const117   bool IsFetchSettingsPendingAtBackend() const {
118     return fake_backend_controller_->IsFetchSettingsAndAlbumsPending();
119   }
120 
ReplyFetchSettingsAndAlbums(bool success)121   void ReplyFetchSettingsAndAlbums(bool success) {
122     fake_backend_controller_->ReplyFetchSettingsAndAlbums(success);
123   }
124 
IsUpdateSettingsPendingAtBackend() const125   bool IsUpdateSettingsPendingAtBackend() const {
126     return fake_backend_controller_->IsUpdateSettingsPending();
127   }
128 
ReplyUpdateSettings(bool success)129   void ReplyUpdateSettings(bool success) {
130     fake_backend_controller_->ReplyUpdateSettings(success);
131   }
132 
BoolToString(bool x)133   std::string BoolToString(bool x) { return x ? "true" : "false"; }
134 
VerifySettingsSent(ash::AmbientModeTopicSource topic_source,const std::string & temperature_unit)135   void VerifySettingsSent(ash::AmbientModeTopicSource topic_source,
136                           const std::string& temperature_unit) {
137     EXPECT_EQ(2U, web_ui_->call_data().size());
138 
139     // The call is structured such that the function name is the "web callback"
140     // name and the first argument is the name of the message being sent.
141     const auto& topic_source_call_data = *web_ui_->call_data().front();
142     const auto& temperature_unit_call_data = *web_ui_->call_data().back();
143 
144     // Topic Source
145     EXPECT_EQ(kWebCallbackFunctionName, topic_source_call_data.function_name());
146     EXPECT_EQ("topic-source-changed",
147               topic_source_call_data.arg1()->GetString());
148     const base::DictionaryValue* dictionary = nullptr;
149     topic_source_call_data.arg2()->GetAsDictionary(&dictionary);
150     const base::Value* topic_source_value = dictionary->FindKey("topicSource");
151     EXPECT_EQ(static_cast<int>(topic_source), topic_source_value->GetInt());
152 
153     // Temperature Unit
154     EXPECT_EQ(kWebCallbackFunctionName,
155               temperature_unit_call_data.function_name());
156     EXPECT_EQ("temperature-unit-changed",
157               temperature_unit_call_data.arg1()->GetString());
158     EXPECT_EQ(temperature_unit, temperature_unit_call_data.arg2()->GetString());
159   }
160 
VerifyAlbumsSent(ash::AmbientModeTopicSource topic_source)161   void VerifyAlbumsSent(ash::AmbientModeTopicSource topic_source) {
162     // Art gallery has an extra call to update the topic source to Art gallery.
163     std::vector<std::unique_ptr<content::TestWebUI::CallData>>::size_type call_size =
164         topic_source == ash::AmbientModeTopicSource::kGooglePhotos ? 1U : 2U;
165     EXPECT_EQ(call_size, web_ui_->call_data().size());
166 
167     if (topic_source == ash::AmbientModeTopicSource::kArtGallery) {
168       const auto& topic_source_call_data = *web_ui_->call_data().front();
169       const base::DictionaryValue* dictionary = nullptr;
170       topic_source_call_data.arg2()->GetAsDictionary(&dictionary);
171       const base::Value* topic_source_value =
172           dictionary->FindKey("topicSource");
173       EXPECT_EQ(static_cast<int>(topic_source), topic_source_value->GetInt());
174     }
175 
176     const content::TestWebUI::CallData& call_data =
177         *web_ui_->call_data().back();
178 
179     // The call is structured such that the function name is the "web callback"
180     // name and the first argument is the name of the message being sent.
181     EXPECT_EQ(kWebCallbackFunctionName, call_data.function_name());
182     EXPECT_EQ("albums-changed", call_data.arg1()->GetString());
183 
184     // The test data is set in FakeAmbientBackendControllerImpl.
185     const base::DictionaryValue* dictionary = nullptr;
186     call_data.arg2()->GetAsDictionary(&dictionary);
187 
188     const base::Value* topic_source_value = dictionary->FindKey("topicSource");
189     EXPECT_EQ(static_cast<int>(topic_source), topic_source_value->GetInt());
190 
191     const base::Value* albums = dictionary->FindKey("albums");
192     EXPECT_EQ(2U, albums->GetList().size());
193 
194     const base::DictionaryValue* album0;
195     albums->GetList()[0].GetAsDictionary(&album0);
196     EXPECT_EQ("0", album0->FindKey("albumId")->GetString());
197 
198     const base::DictionaryValue* album1;
199     albums->GetList()[1].GetAsDictionary(&album1);
200     EXPECT_EQ("1", album1->FindKey("albumId")->GetString());
201 
202     if (topic_source == ash::AmbientModeTopicSource::kGooglePhotos) {
203       EXPECT_EQ(false, album0->FindKey("checked")->GetBool());
204       EXPECT_EQ("album0", album0->FindKey("title")->GetString());
205 
206       EXPECT_EQ(true, album1->FindKey("checked")->GetBool());
207       EXPECT_EQ("album1", album1->FindKey("title")->GetString());
208     } else {
209       EXPECT_EQ(true, album0->FindKey("checked")->GetBool());
210       EXPECT_EQ("art0", album0->FindKey("title")->GetString());
211 
212       EXPECT_EQ(false, album1->FindKey("checked")->GetBool());
213       EXPECT_EQ("art1", album1->FindKey("title")->GetString());
214     }
215   }
216 
217  private:
218   base::test::TaskEnvironment task_environment_{
219       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
220   std::unique_ptr<content::TestWebUI> web_ui_;
221   std::unique_ptr<ash::FakeAmbientBackendControllerImpl>
222       fake_backend_controller_;
223   std::unique_ptr<ash::TestImageDownloader> image_downloader_;
224   std::unique_ptr<TestAmbientModeHandler> handler_;
225   base::HistogramTester histogram_tester_;
226 };
227 
TEST_F(AmbientModeHandlerTest,TestSendTemperatureUnitAndTopicSource)228 TEST_F(AmbientModeHandlerTest, TestSendTemperatureUnitAndTopicSource) {
229   RequestSettings();
230   ReplyFetchSettingsAndAlbums(/*success=*/true);
231 
232   // In FakeAmbientBackendControllerImpl, the |topic_source| is kGooglePhotos,
233   // the |temperature_unit| is kCelsius.
234   VerifySettingsSent(ash::AmbientModeTopicSource::kGooglePhotos, "celsius");
235 }
236 
TEST_F(AmbientModeHandlerTest,TestSendAlbumsForGooglePhotos)237 TEST_F(AmbientModeHandlerTest, TestSendAlbumsForGooglePhotos) {
238   ash::AmbientModeTopicSource topic_source =
239       ash::AmbientModeTopicSource::kGooglePhotos;
240   RequestAlbums(topic_source);
241   ReplyFetchSettingsAndAlbums(/*success=*/true);
242   VerifyAlbumsSent(topic_source);
243 }
244 
TEST_F(AmbientModeHandlerTest,TestSendAlbumsForArtGallery)245 TEST_F(AmbientModeHandlerTest, TestSendAlbumsForArtGallery) {
246   ash::AmbientModeTopicSource topic_source =
247       ash::AmbientModeTopicSource::kArtGallery;
248   RequestAlbums(topic_source);
249   ReplyFetchSettingsAndAlbums(/*success=*/true);
250   VerifyAlbumsSent(topic_source);
251 }
252 
TEST_F(AmbientModeHandlerTest,TestFetchSettings)253 TEST_F(AmbientModeHandlerTest, TestFetchSettings) {
254   FetchSettings();
255   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
256 
257   ReplyFetchSettingsAndAlbums(/*success=*/true);
258   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
259 }
260 
TEST_F(AmbientModeHandlerTest,TestFetchSettingsFailedWillRetry)261 TEST_F(AmbientModeHandlerTest, TestFetchSettingsFailedWillRetry) {
262   FetchSettings();
263   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
264 
265   ReplyFetchSettingsAndAlbums(/*success=*/false);
266   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
267 
268   FastForwardBy(GetFetchSettingsDelay() * 1.5);
269   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
270 }
271 
TEST_F(AmbientModeHandlerTest,TestFetchSettingsSecondRetryWillBackoff)272 TEST_F(AmbientModeHandlerTest, TestFetchSettingsSecondRetryWillBackoff) {
273   FetchSettings();
274   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
275 
276   ReplyFetchSettingsAndAlbums(/*success=*/false);
277   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
278 
279   base::TimeDelta delay1 = GetFetchSettingsDelay();
280   FastForwardBy(delay1 * 1.5);
281   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
282 
283   ReplyFetchSettingsAndAlbums(/*success=*/false);
284   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
285 
286   base::TimeDelta delay2 = GetFetchSettingsDelay();
287   EXPECT_GT(delay2, delay1);
288 
289   FastForwardBy(delay2 * 1.5);
290   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
291 }
292 
TEST_F(AmbientModeHandlerTest,TestFetchSettingsWillNotRetryMoreThanThreeTimes)293 TEST_F(AmbientModeHandlerTest,
294        TestFetchSettingsWillNotRetryMoreThanThreeTimes) {
295   FetchSettings();
296   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
297 
298   ReplyFetchSettingsAndAlbums(/*success=*/false);
299   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
300 
301   // 1st retry.
302   FastForwardBy(GetFetchSettingsDelay() * 1.5);
303   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
304 
305   ReplyFetchSettingsAndAlbums(/*success=*/false);
306   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
307 
308   // 2nd retry.
309   FastForwardBy(GetFetchSettingsDelay() * 1.5);
310   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
311 
312   ReplyFetchSettingsAndAlbums(/*success=*/false);
313   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
314 
315   // 3rd retry.
316   FastForwardBy(GetFetchSettingsDelay() * 1.5);
317   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
318 
319   ReplyFetchSettingsAndAlbums(/*success=*/false);
320   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
321 
322   // Will not retry.
323   FastForwardBy(GetFetchSettingsDelay() * 1.5);
324   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
325 }
326 
TEST_F(AmbientModeHandlerTest,TestUpdateSettings)327 TEST_F(AmbientModeHandlerTest, TestUpdateSettings) {
328   UpdateSettings();
329   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
330   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
331   EXPECT_FALSE(HasPendingUpdatesAtHandler());
332 
333   ReplyUpdateSettings(/*success=*/true);
334   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
335   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
336   EXPECT_FALSE(HasPendingUpdatesAtHandler());
337 }
338 
TEST_F(AmbientModeHandlerTest,TestUpdateSettingsTwice)339 TEST_F(AmbientModeHandlerTest, TestUpdateSettingsTwice) {
340   UpdateSettings();
341   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
342   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
343   EXPECT_FALSE(HasPendingUpdatesAtHandler());
344 
345   UpdateSettings();
346   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
347   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
348   EXPECT_TRUE(HasPendingUpdatesAtHandler());
349 
350   ReplyUpdateSettings(/*success=*/true);
351   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
352   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
353   EXPECT_TRUE(HasPendingUpdatesAtHandler());
354 
355   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
356   EXPECT_FALSE(HasPendingUpdatesAtHandler());
357 }
358 
TEST_F(AmbientModeHandlerTest,TestUpdateSettingsFailedWillRetry)359 TEST_F(AmbientModeHandlerTest, TestUpdateSettingsFailedWillRetry) {
360   UpdateSettings();
361   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
362   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
363   EXPECT_FALSE(HasPendingUpdatesAtHandler());
364 
365   ReplyUpdateSettings(/*success=*/false);
366   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
367   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
368   EXPECT_FALSE(HasPendingUpdatesAtHandler());
369 
370   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
371   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
372   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
373   EXPECT_FALSE(HasPendingUpdatesAtHandler());
374 }
375 
TEST_F(AmbientModeHandlerTest,TestUpdateSettingsSecondRetryWillBackoff)376 TEST_F(AmbientModeHandlerTest, TestUpdateSettingsSecondRetryWillBackoff) {
377   UpdateSettings();
378   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
379   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
380   EXPECT_FALSE(HasPendingUpdatesAtHandler());
381 
382   ReplyUpdateSettings(/*success=*/false);
383   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
384   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
385   EXPECT_FALSE(HasPendingUpdatesAtHandler());
386 
387   base::TimeDelta delay1 = GetUpdateSettingsDelay();
388   FastForwardBy(delay1 * 1.5);
389   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
390   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
391   EXPECT_FALSE(HasPendingUpdatesAtHandler());
392 
393   ReplyUpdateSettings(/*success=*/false);
394   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
395   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
396   EXPECT_FALSE(HasPendingUpdatesAtHandler());
397 
398   base::TimeDelta delay2 = GetUpdateSettingsDelay();
399   EXPECT_GT(delay2, delay1);
400 
401   FastForwardBy(delay2 * 1.5);
402   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
403   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
404   EXPECT_FALSE(HasPendingUpdatesAtHandler());
405 }
406 
TEST_F(AmbientModeHandlerTest,TestUpdateSettingsWillNotRetryMoreThanThreeTimes)407 TEST_F(AmbientModeHandlerTest,
408        TestUpdateSettingsWillNotRetryMoreThanThreeTimes) {
409   UpdateSettings();
410   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
411   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
412   EXPECT_FALSE(HasPendingUpdatesAtHandler());
413 
414   ReplyUpdateSettings(/*success=*/false);
415   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
416   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
417   EXPECT_FALSE(HasPendingUpdatesAtHandler());
418 
419   // 1st retry.
420   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
421   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
422   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
423   EXPECT_FALSE(HasPendingUpdatesAtHandler());
424 
425   ReplyUpdateSettings(/*success=*/false);
426   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
427   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
428   EXPECT_FALSE(HasPendingUpdatesAtHandler());
429 
430   // 2nd retry.
431   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
432   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
433   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
434   EXPECT_FALSE(HasPendingUpdatesAtHandler());
435 
436   ReplyUpdateSettings(/*success=*/false);
437   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
438   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
439   EXPECT_FALSE(HasPendingUpdatesAtHandler());
440 
441   // 3rd retry.
442   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
443   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
444   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
445   EXPECT_FALSE(HasPendingUpdatesAtHandler());
446 
447   ReplyUpdateSettings(/*success=*/false);
448   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
449   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
450   EXPECT_FALSE(HasPendingUpdatesAtHandler());
451 
452   // Will not retry.
453   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
454   EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
455   EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
456   EXPECT_FALSE(HasPendingUpdatesAtHandler());
457 }
458 
TEST_F(AmbientModeHandlerTest,TestNoFetchRequestWhenUpdatingSettings)459 TEST_F(AmbientModeHandlerTest, TestNoFetchRequestWhenUpdatingSettings) {
460   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
461   UpdateSettings();
462   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
463 
464   RequestSettings();
465   EXPECT_TRUE(HasPendingFetchRequestAtHandler());
466   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
467 }
468 
TEST_F(AmbientModeHandlerTest,TestSendSettingsWhenUpdatedSettings)469 TEST_F(AmbientModeHandlerTest, TestSendSettingsWhenUpdatedSettings) {
470   // Simulate initial page request.
471   RequestSettings();
472   ReplyFetchSettingsAndAlbums(/*success=*/true);
473 
474   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
475   SetTopicSource(ash::AmbientModeTopicSource::kArtGallery);
476   UpdateSettings();
477   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
478 
479   RequestSettings();
480   EXPECT_TRUE(HasPendingFetchRequestAtHandler());
481   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
482 
483   web_ui()->ClearTrackedCalls();
484   ReplyUpdateSettings(/*success=*/true);
485 
486   // In FakeAmbientBackendControllerImpl, the |topic_source| is kGooglePhotos,
487   // the |temperature_unit| is kCelsius.
488   VerifySettingsSent(ash::AmbientModeTopicSource::kArtGallery, "celsius");
489   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
490 }
491 
TEST_F(AmbientModeHandlerTest,TestSendAlbumsOfGooglePhotosWhenUpdatedSettings)492 TEST_F(AmbientModeHandlerTest,
493        TestSendAlbumsOfGooglePhotosWhenUpdatedSettings) {
494   // Simulate initial page request.
495   ash::AmbientModeTopicSource topic_source =
496       ash::AmbientModeTopicSource::kGooglePhotos;
497   RequestAlbums(topic_source);
498   ReplyFetchSettingsAndAlbums(/*success=*/true);
499   web_ui()->ClearTrackedCalls();
500 
501   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
502   UpdateSettings();
503   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
504 
505   RequestAlbums(topic_source);
506   EXPECT_TRUE(HasPendingFetchRequestAtHandler());
507   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
508 
509   ReplyUpdateSettings(/*success=*/true);
510   VerifyAlbumsSent(topic_source);
511   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
512 }
513 
TEST_F(AmbientModeHandlerTest,TestSendAlbumsOfArtGalleryWhenUpdatedSettings)514 TEST_F(AmbientModeHandlerTest, TestSendAlbumsOfArtGalleryWhenUpdatedSettings) {
515   // Simulate initial page request.
516   ash::AmbientModeTopicSource topic_source =
517       ash::AmbientModeTopicSource::kGooglePhotos;
518   RequestAlbums(topic_source);
519   ReplyFetchSettingsAndAlbums(/*success=*/true);
520   web_ui()->ClearTrackedCalls();
521 
522   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
523   UpdateSettings();
524   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
525 
526   RequestAlbums(topic_source);
527   EXPECT_TRUE(HasPendingFetchRequestAtHandler());
528   EXPECT_FALSE(IsFetchSettingsPendingAtBackend());
529 
530   ReplyUpdateSettings(/*success=*/true);
531   VerifyAlbumsSent(topic_source);
532   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
533 }
534 
TEST_F(AmbientModeHandlerTest,TestNotUpdateUIWhenFetechedSettings)535 TEST_F(AmbientModeHandlerTest, TestNotUpdateUIWhenFetechedSettings) {
536   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
537   RequestSettings();
538   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
539   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
540 
541   UpdateSettings();
542   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
543   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
544 
545   ReplyFetchSettingsAndAlbums(/*success=*/true);
546   EXPECT_EQ(0U, web_ui()->call_data().size());
547 }
548 
TEST_F(AmbientModeHandlerTest,TestNotSendSettingsWhenFetechedSettings)549 TEST_F(AmbientModeHandlerTest, TestNotSendSettingsWhenFetechedSettings) {
550   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
551   RequestSettings();
552   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
553   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
554 
555   UpdateSettings();
556   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
557   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
558 
559   ReplyFetchSettingsAndAlbums(/*success=*/true);
560   EXPECT_EQ(0U, web_ui()->call_data().size());
561 }
562 
TEST_F(AmbientModeHandlerTest,TestNotSendAlbumsWhenFetechedSettings)563 TEST_F(AmbientModeHandlerTest, TestNotSendAlbumsWhenFetechedSettings) {
564   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
565 
566   ash::AmbientModeTopicSource topic_source =
567       ash::AmbientModeTopicSource::kGooglePhotos;
568   RequestAlbums(topic_source);
569   EXPECT_TRUE(IsFetchSettingsPendingAtBackend());
570   EXPECT_FALSE(HasPendingFetchRequestAtHandler());
571 
572   UpdateSettings();
573   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
574   EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
575 
576   ReplyFetchSettingsAndAlbums(/*success=*/true);
577   EXPECT_EQ(0U, web_ui()->call_data().size());
578 }
579 
TEST_F(AmbientModeHandlerTest,TestSendSettingsWhenUpdateSettingsFailed)580 TEST_F(AmbientModeHandlerTest, TestSendSettingsWhenUpdateSettingsFailed) {
581   // Simulate initial page request.
582   RequestSettings();
583   ReplyFetchSettingsAndAlbums(/*success=*/true);
584 
585   SetTopicSource(ash::AmbientModeTopicSource::kArtGallery);
586   UpdateSettings();
587   ReplyUpdateSettings(/*success=*/false);
588 
589   // 1st retry.
590   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
591   ReplyUpdateSettings(/*success=*/false);
592 
593   // 2nd retry.
594   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
595   ReplyUpdateSettings(/*success=*/false);
596 
597   web_ui()->ClearTrackedCalls();
598   EXPECT_EQ(0U, web_ui()->call_data().size());
599 
600   // 3rd retry.
601   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
602   ReplyUpdateSettings(/*success=*/false);
603   // In FakeAmbientBackendControllerImpl, the |topic_source| is kGooglePhotos,
604   // the |temperature_unit| is kCelsius.
605   VerifySettingsSent(ash::AmbientModeTopicSource::kGooglePhotos, "celsius");
606 }
607 
TEST_F(AmbientModeHandlerTest,TestSendAlbumsOfGooglePhotosWhenUpdateSettingsFailed)608 TEST_F(AmbientModeHandlerTest,
609        TestSendAlbumsOfGooglePhotosWhenUpdateSettingsFailed) {
610   // Simulate initial page request.
611   ash::AmbientModeTopicSource topic_source =
612       ash::AmbientModeTopicSource::kGooglePhotos;
613   SetTopicSource(topic_source);
614   RequestAlbums(topic_source);
615   ReplyFetchSettingsAndAlbums(/*success=*/true);
616 
617   UpdateSettings();
618   ReplyUpdateSettings(/*success=*/false);
619 
620   // 1st retry.
621   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
622   ReplyUpdateSettings(/*success=*/false);
623 
624   // 2nd retry.
625   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
626   ReplyUpdateSettings(/*success=*/false);
627 
628   web_ui()->ClearTrackedCalls();
629   EXPECT_EQ(0U, web_ui()->call_data().size());
630 
631   // 3rd retry.
632   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
633   ReplyUpdateSettings(/*success=*/false);
634   VerifyAlbumsSent(topic_source);
635 }
636 
TEST_F(AmbientModeHandlerTest,TestSendAlbumsOfArtGalleryWhenUpdateSettingsFailed)637 TEST_F(AmbientModeHandlerTest,
638        TestSendAlbumsOfArtGalleryWhenUpdateSettingsFailed) {
639   // Simulate initial page request.
640   ash::AmbientModeTopicSource topic_source =
641       ash::AmbientModeTopicSource::kArtGallery;
642   SetTopicSource(topic_source);
643   RequestAlbums(topic_source);
644   ReplyFetchSettingsAndAlbums(/*success=*/true);
645 
646   UpdateSettings();
647   ReplyUpdateSettings(/*success=*/false);
648 
649   // 1st retry.
650   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
651   ReplyUpdateSettings(/*success=*/false);
652 
653   // 2nd retry.
654   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
655   ReplyUpdateSettings(/*success=*/false);
656 
657   web_ui()->ClearTrackedCalls();
658   EXPECT_EQ(0U, web_ui()->call_data().size());
659 
660   // 3rd retry.
661   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
662   ReplyUpdateSettings(/*success=*/false);
663   VerifyAlbumsSent(topic_source);
664 }
665 
666 // Test that there are two updates, the first update succeeded and the second
667 // update failed. When the second update failed, it will update UI to restore
668 // the latest successfully updated settings.
TEST_F(AmbientModeHandlerTest,TestSendSettingsWithCachedSettings)669 TEST_F(AmbientModeHandlerTest, TestSendSettingsWithCachedSettings) {
670   ash::AmbientModeTopicSource topic_source_google_photos =
671       ash::AmbientModeTopicSource::kGooglePhotos;
672   ash::AmbientModeTopicSource topic_source_art_gallery =
673       ash::AmbientModeTopicSource::kArtGallery;
674 
675   // Simulate initial page request.
676   RequestSettings();
677   ReplyFetchSettingsAndAlbums(/*success=*/true);
678 
679   // The first update.
680   SetTopicSource(topic_source_art_gallery);
681   UpdateSettings();
682   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
683 
684   // There is the second change and pending update before retry.
685   SetTopicSource(topic_source_google_photos);
686   UpdateSettings();
687   EXPECT_TRUE(HasPendingUpdatesAtHandler());
688 
689   // First update returns true and will start the second update.
690   ReplyUpdateSettings(/*success=*/true);
691   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
692   EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
693 
694   ReplyUpdateSettings(/*success=*/false);
695 
696   // 1st retry.
697   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
698   ReplyUpdateSettings(/*success=*/false);
699 
700   // 2nd retry.
701   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
702   ReplyUpdateSettings(/*success=*/false);
703 
704   web_ui()->ClearTrackedCalls();
705   EXPECT_EQ(0U, web_ui()->call_data().size());
706 
707   // 3rd retry.
708   FastForwardBy(GetUpdateSettingsDelay() * 1.5);
709   ReplyUpdateSettings(/*success=*/false);
710   VerifySettingsSent(topic_source_art_gallery, "celsius");
711 }
712 
TEST_F(AmbientModeHandlerTest,TestAlbumNumbersAreRecorded)713 TEST_F(AmbientModeHandlerTest, TestAlbumNumbersAreRecorded) {
714   RequestSettings();
715   ReplyFetchSettingsAndAlbums(/*success=*/true);
716 
717   base::ListValue args;
718   base::DictionaryValue dictionary;
719   ash::AmbientModeTopicSource topic_source =
720       ash::AmbientModeTopicSource::kGooglePhotos;
721   dictionary.SetKey("topicSource", base::Value(static_cast<int>(topic_source)));
722 
723   base::Value albums(base::Value::Type::LIST);
724   base::Value album(base::Value::Type::DICTIONARY);
725   album.SetKey("albumId", base::Value("0"));
726   albums.Append(std::move(album));
727   dictionary.SetKey("albums", std::move(albums));
728 
729   args.Append(std::move(dictionary));
730   HandleSetSelectedAlbums(&args);
731 
732   histogram_tester().ExpectTotalCount("Ash.AmbientMode.TotalNumberOfAlbums",
733                                       /*count=*/1);
734   histogram_tester().ExpectTotalCount("Ash.AmbientMode.SelectedNumberOfAlbums",
735                                       /*count=*/1);
736 }
737 
738 }  // namespace settings
739 }  // namespace chromeos
740