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 <memory>
6 #include <string>
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/json/string_escape.h"
11 #include "base/memory/ref_counted_memory.h"
12 #include "base/optional.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/test/metrics/histogram_tester.h"
16 #include "build/build_config.h"
17 #include "chrome/browser/search/instant_service.h"
18 #include "chrome/browser/search/instant_service_factory.h"
19 #include "chrome/browser/search_provider_logos/logo_service_factory.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/search/instant_test_utils.h"
22 #include "chrome/browser/ui/search/local_ntp_browsertest_base.h"
23 #include "chrome/browser/ui/search/local_ntp_test_utils.h"
24 #include "chrome/common/url_constants.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "components/keyed_service/content/browser_context_dependency_manager.h"
28 #include "components/search_provider_logos/logo_service.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/test/browser_test.h"
31 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/test_navigation_observer.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "url/gurl.h"
35 
36 using search_provider_logos::EncodedLogo;
37 using search_provider_logos::EncodedLogoCallback;
38 using search_provider_logos::LogoCallbacks;
39 using search_provider_logos::LogoCallbackReason;
40 using search_provider_logos::LogoObserver;
41 using search_provider_logos::LogoService;
42 using search_provider_logos::LogoType;
43 using testing::_;
44 using testing::DoAll;
45 using testing::Eq;
46 using testing::IsEmpty;
47 
48 namespace {
49 
50 const char kCachedB64[] = "\161\247\041\171\337\276";  // b64decode("cached++")
51 const char kFreshB64[] = "abc";                        // b64decode("YWJj")
52 const int kRealboxTopPx = 56 + 200 + 38;  // top margin + height + bottom margin
53 
54 #if defined(OS_WIN) || defined(OS_MAC)
55 const char kFreshDarkB64[] = "xyz";  // b64decode("eHl6");
56 #endif
57 
58 // A base64 encoding of a tiny but valid gif file.
59 const char kTinyGifData[] =
60     "R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
61 
MakeRefPtr(std::string content)62 scoped_refptr<base::RefCountedString> MakeRefPtr(std::string content) {
63   return base::RefCountedString::TakeString(&content);
64 }
65 
66 class MockLogoService : public LogoService {
67  public:
68   MOCK_METHOD1(GetLogoPtr, void(LogoCallbacks* callbacks));
69 
GetLogo(LogoCallbacks callbacks,bool for_webui_ntp)70   void GetLogo(LogoCallbacks callbacks, bool for_webui_ntp) override {
71     GetLogoPtr(&callbacks);
72   }
GetLogo(LogoObserver * observer)73   void GetLogo(LogoObserver* observer) override { NOTREACHED(); }
74 };
75 
ACTION_P2(ReturnCachedLogo,reason,logo)76 ACTION_P2(ReturnCachedLogo, reason, logo) {
77   if (arg0->on_cached_encoded_logo_available) {
78     std::move(arg0->on_cached_encoded_logo_available).Run(reason, logo);
79   }
80 }
81 
ACTION_P2(ReturnFreshLogo,reason,logo)82 ACTION_P2(ReturnFreshLogo, reason, logo) {
83   if (arg0->on_fresh_encoded_logo_available) {
84     std::move(arg0->on_fresh_encoded_logo_available).Run(reason, logo);
85   }
86 }
87 
88 // A simple class to add a test failure if any console message comes in for
89 // the given WebContents.
90 class FailOnConsoleMessage : public content::WebContentsObserver {
91  public:
FailOnConsoleMessage(content::WebContents * web_contents)92   explicit FailOnConsoleMessage(content::WebContents* web_contents)
93       : WebContentsObserver(web_contents) {}
94   FailOnConsoleMessage(const FailOnConsoleMessage& other) = delete;
95   FailOnConsoleMessage& operator=(const FailOnConsoleMessage& other) = delete;
96   ~FailOnConsoleMessage() override = default;
97 
98  private:
99   // content::WebContentsObserver:
OnDidAddMessageToConsole(content::RenderFrameHost * source_frame,blink::mojom::ConsoleMessageLevel log_level,const base::string16 & message,int32_t line_no,const base::string16 & source_id)100   void OnDidAddMessageToConsole(content::RenderFrameHost* source_frame,
101                                 blink::mojom::ConsoleMessageLevel log_level,
102                                 const base::string16& message,
103                                 int32_t line_no,
104                                 const base::string16& source_id) override {
105     ADD_FAILURE() << "Unexpected console message: " << message;
106   }
107 };
108 
109 }  // namespace
110 
111 class LocalNTPDoodleTest : public InProcessBrowserTest {
112  protected:
LocalNTPDoodleTest()113   LocalNTPDoodleTest() {}
114 
logo_service()115   MockLogoService* logo_service() {
116     return static_cast<MockLogoService*>(
117         LogoServiceFactory::GetForProfile(browser()->profile()));
118   }
119 
GetDimension(content::WebContents * tab,const std::string & id,const std::string & dimension)120   base::Optional<int> GetDimension(content::WebContents* tab,
121                                    const std::string& id,
122                                    const std::string& dimension) {
123     double value = 0.0;
124     if (instant_test_utils::GetDoubleFromJS(
125             tab,
126             base::StringPrintf(
127                 "document.getElementById(%s).getBoundingClientRect()[%s]",
128                 base::GetQuotedJSONString(id).c_str(),
129                 base::GetQuotedJSONString(dimension).c_str()),
130             &value)) {
131       return value;
132     }
133     return base::nullopt;
134   }
135 
TeardownWindowOpenTest(content::WebContents * tab)136   void TeardownWindowOpenTest(content::WebContents* tab) {
137     ASSERT_TRUE(content::ExecuteScript(tab, "window.open = windowOpenOld"));
138   }
139 
SetupWindowOpenTest(content::WebContents * tab)140   void SetupWindowOpenTest(content::WebContents* tab) {
141     ASSERT_TRUE(content::ExecuteScript(tab,
142                                        "var windowOpenOld = window.open; "
143                                        "window.open = (w) => { openedWindow = "
144                                        "w };"));
145   }
146 
GetWindowOpenURL(content::WebContents * tab)147   base::Optional<std::string> GetWindowOpenURL(content::WebContents* tab) {
148     std::string target_url;
149     if (instant_test_utils::GetStringFromJS(tab, "openedWindow", &target_url)) {
150       return target_url;
151     }
152     return base::nullopt;
153   }
154 
TeardownNavigatorTest(content::WebContents * tab)155   void TeardownNavigatorTest(content::WebContents* tab) {
156     ASSERT_TRUE(content::ExecuteScript(tab, "window.navigator = navigatorOld"));
157   }
158 
SetupBeaconTest(content::WebContents * tab)159   void SetupBeaconTest(content::WebContents* tab) {
160     ASSERT_TRUE(content::ExecuteScript(tab,
161                                        "var navigatorOld = window.navigator; "
162                                        "window.navigator = {};"
163                                        "window.navigator.sendBeacon = "
164                                        "(url) => { sentbeacon = url };"));
165   }
166 
GetBeaconURL(content::WebContents * tab)167   base::Optional<std::string> GetBeaconURL(content::WebContents* tab) {
168     std::string target_url;
169     if (instant_test_utils::GetStringFromJS(tab, "sentbeacon", &target_url)) {
170       return target_url;
171     }
172     return base::nullopt;
173   }
174 
ElementExists(content::WebContents * tab,const std::string & id)175   bool ElementExists(content::WebContents* tab, const std::string& id) {
176     return ExecuteBooleanJS(
177         tab, base::StringPrintf("!!document.getElementById(%s)",
178                                 base::GetQuotedJSONString(id).c_str()));
179   }
180 
DialogIsOpen(content::WebContents * tab,const std::string & id)181   bool DialogIsOpen(content::WebContents* tab, const std::string& id) {
182     return ExecuteBooleanJS(
183         tab,
184         base::StringPrintf("!!document.getElementById(%s).hasAttribute('open')",
185                            base::GetQuotedJSONString(id).c_str()));
186   }
187 
ExecuteBooleanJS(content::WebContents * tab,const std::string & js)188   bool ExecuteBooleanJS(content::WebContents* tab, const std::string& js) {
189     bool value;
190     if (instant_test_utils::GetBoolFromJS(tab, js, &value)) {
191       return value;
192     }
193     return false;
194   }
195 
GetComputedStyle(content::WebContents * tab,const std::string & id,const std::string & css_name)196   base::Optional<std::string> GetComputedStyle(content::WebContents* tab,
197                                                const std::string& id,
198                                                const std::string& css_name) {
199     std::string css_value;
200     if (instant_test_utils::GetStringFromJS(
201             tab,
202             base::StringPrintf(
203                 "getComputedStyle(document.getElementById(%s))[%s]",
204                 base::GetQuotedJSONString(id).c_str(),
205                 base::GetQuotedJSONString(css_name).c_str()),
206             &css_value)) {
207       return css_value;
208     }
209     return base::nullopt;
210   }
211 
GetComputedOpacity(content::WebContents * tab,const std::string & id)212   base::Optional<double> GetComputedOpacity(content::WebContents* tab,
213                                             const std::string& id) {
214     auto css_value = GetComputedStyle(tab, id, "opacity");
215     double double_value;
216     if ((css_value != base::nullopt) &&
217         base::StringToDouble(*css_value, &double_value)) {
218       return double_value;
219     }
220     return base::nullopt;
221   }
222 
GetComputedDisplay(content::WebContents * tab,const std::string & id)223   base::Optional<std::string> GetComputedDisplay(content::WebContents* tab,
224                                                  const std::string& id) {
225     return GetComputedStyle(tab, id, "display");
226   }
227 
228   // Gets $(id)[property]. Coerces to string.
GetElementProperty(content::WebContents * tab,const std::string & id,const std::string & property)229   base::Optional<std::string> GetElementProperty(content::WebContents* tab,
230                                                  const std::string& id,
231                                                  const std::string& property) {
232     std::string value;
233     if (instant_test_utils::GetStringFromJS(
234             tab,
235             base::StringPrintf("document.getElementById(%s)[%s] + ''",
236                                base::GetQuotedJSONString(id).c_str(),
237                                base::GetQuotedJSONString(property).c_str()),
238             &value)) {
239       return value;
240     }
241     return base::nullopt;
242   }
243 
WaitForFadeIn(content::WebContents * tab,const std::string & id)244   void WaitForFadeIn(content::WebContents* tab, const std::string& id) {
245     content::WebContentsConsoleObserver console_observer(tab);
246     console_observer.SetPattern("WaitForFadeIn");
247 
248     bool result = false;
249     if (!instant_test_utils::GetBoolFromJS(
250             tab,
251             base::StringPrintf(
252                 R"js(
253                   (function(id, message) {
254                     var element = document.getElementById(id);
255                     var fn = function() {
256                       if (element.classList.contains('show-logo') &&
257                           (window.getComputedStyle(element).opacity == 1.0)) {
258                         console.log(message);
259                       } else {
260                         element.addEventListener('transitionend', fn);
261                       }
262                     };
263                     fn();
264                     return true;
265                   })(%s, 'WaitForFadeIn')
266                 )js",
267                 base::GetQuotedJSONString(id).c_str()),
268             &result) &&
269         result) {
270       ADD_FAILURE() << "failed to wait for fade-in";
271       return;
272     }
273 
274     console_observer.Wait();
275   }
276 
WaitForLogoSwap(content::WebContents * tab,const std::string & id)277   void WaitForLogoSwap(content::WebContents* tab, const std::string& id) {
278     content::WebContentsConsoleObserver console_observer(tab);
279     console_observer.SetPattern("WaitForFadeIn");
280 
281     bool result = false;
282     if (!instant_test_utils::GetBoolFromJS(
283             tab,
284             base::StringPrintf(
285                 R"js(
286                   (function(id, message) {
287                     var element = document.getElementById(id);
288                     var fn = function() {
289                       if (element.classList.contains('show-logo') &&
290                           (window.getComputedStyle(element).opacity == 1.0)) {
291                         console.log(message);
292                       }
293                     };
294                     element.addEventListener('transitionend', fn);
295                     return true;
296                   })(%s, 'WaitForFadeIn')
297                 )js",
298                 base::GetQuotedJSONString(id).c_str()),
299             &result) &&
300         result) {
301       ADD_FAILURE() << "failed to wait for fade-in";
302       return;
303     }
304 
305     console_observer.Wait();
306   }
307 
308   // See enum LogoImpressionType in ntp_user_data_logger.cc.
309   static const int kLogoImpressionStatic = 0;
310   static const int kLogoImpressionCta = 1;
311 
312   // See enum LogoClickType in ntp_user_data_logger.cc.
313   static const int kLogoClickCta = 1;
314 
315  private:
SetUp()316   void SetUp() override {
317     InProcessBrowserTest::SetUp();
318   }
319 
SetUpInProcessBrowserTestFixture()320   void SetUpInProcessBrowserTestFixture() override {
321     create_services_subscription_ =
322         BrowserContextDependencyManager::GetInstance()
323             ->RegisterCreateServicesCallbackForTesting(base::BindRepeating(
324                 &LocalNTPDoodleTest::OnWillCreateBrowserContextServices,
325                 base::Unretained(this)));
326   }
327 
CreateLogoService(content::BrowserContext * context)328   static std::unique_ptr<KeyedService> CreateLogoService(
329       content::BrowserContext* context) {
330     return std::make_unique<MockLogoService>();
331   }
332 
OnWillCreateBrowserContextServices(content::BrowserContext * context)333   void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
334     LogoServiceFactory::GetInstance()->SetTestingFactory(
335         context, base::BindRepeating(&LocalNTPDoodleTest::CreateLogoService));
336   }
337 
338   std::unique_ptr<
339       BrowserContextDependencyManager::CreateServicesCallbackList::Subscription>
340       create_services_subscription_;
341 };
342 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldBeUnchangedOnLogoFetchCancelled)343 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
344                        ShouldBeUnchangedOnLogoFetchCancelled) {
345   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
346       .WillRepeatedly(
347           DoAll(ReturnCachedLogo(LogoCallbackReason::CANCELED, base::nullopt),
348                 ReturnFreshLogo(LogoCallbackReason::CANCELED, base::nullopt)));
349 
350   // Open a new blank tab, then go to local NTP and listen for console messages.
351   content::WebContents* active_tab =
352       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
353 
354   FailOnConsoleMessage console_observer(active_tab);
355   base::HistogramTester histograms;
356   ui_test_utils::NavigateToURL(browser(),
357                                GURL(chrome::kChromeSearchLocalNtpUrl));
358 
359   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
360   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(1.0));
361   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(0.0));
362 
363   histograms.ExpectTotalCount("NewTabPage.LogoShown", 0);
364   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0);
365   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 0);
366   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 0);
367 }
368 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldBeUnchangedWhenNoCachedOrFreshDoodle)369 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
370                        ShouldBeUnchangedWhenNoCachedOrFreshDoodle) {
371   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
372       .WillRepeatedly(DoAll(
373           ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
374           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
375 
376   // Open a new blank tab, then go to local NTP and listen for console messages.
377   content::WebContents* active_tab =
378       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
379   FailOnConsoleMessage console_observer(active_tab);
380   base::HistogramTester histograms;
381   ui_test_utils::NavigateToURL(browser(),
382                                GURL(chrome::kChromeSearchLocalNtpUrl));
383 
384   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
385   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(1.0));
386   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(0.0));
387 
388   histograms.ExpectTotalCount("NewTabPage.LogoShown", 0);
389   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0);
390   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 0);
391   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 0);
392 }
393 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldShowDoodleWhenCached)394 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldShowDoodleWhenCached) {
395   EncodedLogo cached_logo;
396   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
397   cached_logo.metadata.mime_type = "image/png";
398   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
399   cached_logo.metadata.alt_text = "Chromium";
400 
401   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
402       .WillRepeatedly(DoAll(
403           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
404           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
405 
406   // Open a new blank tab, then go to local NTP and listen for console messages.
407   content::WebContents* active_tab =
408       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
409   FailOnConsoleMessage console_observer(active_tab);
410   base::HistogramTester histograms;
411   ui_test_utils::NavigateToURL(browser(),
412                                GURL(chrome::kChromeSearchLocalNtpUrl));
413 
414   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
415   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
416   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
417   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
418               Eq<std::string>("inline-block"));
419   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
420               Eq<std::string>("none"));
421   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
422               Eq<std::string>("Chromium"));
423   // TODO(sfiera): check href by clicking on button.
424 
425   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
426   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
427                                1);
428   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 1);
429   histograms.ExpectBucketCount("NewTabPage.LogoShown.FromCache",
430                                kLogoImpressionStatic, 1);
431   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 0);
432   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
433 }
434 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldShowInteractiveLogo)435 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldShowInteractiveLogo) {
436   EncodedLogo cached_logo;
437   cached_logo.encoded_image = MakeRefPtr(std::string());
438   cached_logo.metadata.mime_type = "image/png";
439   cached_logo.metadata.type = LogoType::INTERACTIVE;
440   cached_logo.metadata.full_page_url =
441       GURL("https://www.chromium.org/interactive");
442   cached_logo.metadata.alt_text = "alt text";
443   cached_logo.metadata.iframe_width_px = 500;
444   cached_logo.metadata.iframe_height_px = 200;
445 
446   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
447       .WillRepeatedly(DoAll(
448           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
449           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
450 
451   // Open a new blank tab, then go to local NTP.
452   content::WebContents* active_tab =
453       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
454   base::HistogramTester histograms;
455   ui_test_utils::NavigateToURL(browser(),
456                                GURL(chrome::kChromeSearchLocalNtpUrl));
457 
458   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
459   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
460   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
461   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
462               Eq<std::string>("none"));
463   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
464               Eq<std::string>("block"));
465 
466   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-iframe", "src"),
467               Eq<std::string>("https://www.chromium.org/interactive"));
468   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-iframe", "title"),
469               Eq<std::string>("alt text"));
470 }
471 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldShowInteractiveLogoWithoutImage)472 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
473                        ShouldShowInteractiveLogoWithoutImage) {
474   EncodedLogo cached_logo;
475   cached_logo.encoded_image = nullptr;
476   cached_logo.metadata.type = LogoType::INTERACTIVE;
477   cached_logo.metadata.full_page_url =
478       GURL("https://www.chromium.org/interactive");
479   cached_logo.metadata.alt_text = "alt text";
480   cached_logo.metadata.iframe_width_px = 500;
481   cached_logo.metadata.iframe_height_px = 200;
482 
483   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
484       .WillRepeatedly(DoAll(
485           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
486           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
487 
488   // Open a new blank tab, then go to local NTP.
489   content::WebContents* active_tab =
490       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
491   base::HistogramTester histograms;
492   ui_test_utils::NavigateToURL(browser(),
493                                GURL(chrome::kChromeSearchLocalNtpUrl));
494 
495   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
496   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
497   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
498   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
499               Eq<std::string>("none"));
500   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
501               Eq<std::string>("block"));
502 
503   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-iframe", "src"),
504               Eq<std::string>("https://www.chromium.org/interactive"));
505   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-iframe", "title"),
506               Eq<std::string>("alt text"));
507 }
508 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldFadeSimpleDoodleToDefaultWhenFetched)509 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
510                        ShouldFadeSimpleDoodleToDefaultWhenFetched) {
511   EncodedLogo cached_logo;
512   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
513   cached_logo.metadata.mime_type = "image/png";
514   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
515   cached_logo.metadata.alt_text = "Chromium";
516 
517   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
518       .WillOnce(
519           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
520                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, base::nullopt)))
521       .WillRepeatedly(DoAll(
522           ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
523           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
524 
525   // Open a new blank tab, then go to local NTP.
526   content::WebContents* active_tab =
527       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
528   base::HistogramTester histograms;
529   ui_test_utils::NavigateToURL(browser(),
530                                GURL(chrome::kChromeSearchLocalNtpUrl));
531 
532   WaitForFadeIn(active_tab, "logo-default");
533   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
534   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(1.0));
535   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(0.0));
536 
537   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
538   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
539                                1);
540   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 1);
541   histograms.ExpectBucketCount("NewTabPage.LogoShown.FromCache",
542                                kLogoImpressionStatic, 1);
543   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 0);
544   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
545 }
546 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldFadeDefaultToSimpleDoodleWhenFetched)547 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
548                        ShouldFadeDefaultToSimpleDoodleWhenFetched) {
549   EncodedLogo fresh_logo;
550   fresh_logo.encoded_image = MakeRefPtr(kFreshB64);
551   fresh_logo.metadata.mime_type = "image/png";
552   fresh_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
553   fresh_logo.metadata.alt_text = "Chromium";
554 
555   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
556       .WillOnce(
557           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
558                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, fresh_logo)))
559       .WillRepeatedly(DoAll(
560           ReturnCachedLogo(LogoCallbackReason::DETERMINED, fresh_logo),
561           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
562 
563   // Open a new blank tab, then go to local NTP.
564   content::WebContents* active_tab =
565       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
566   base::HistogramTester histograms;
567   ui_test_utils::NavigateToURL(browser(),
568                                GURL(chrome::kChromeSearchLocalNtpUrl));
569 
570   WaitForFadeIn(active_tab, "logo-doodle");
571   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
572   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
573   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
574   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
575               Eq<std::string>("inline-block"));
576   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
577               Eq<std::string>("none"));
578   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
579               Eq<std::string>("Chromium"));
580   // TODO(sfiera): check href by clicking on button.
581 
582   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
583   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
584                                1);
585   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0);
586   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 1);
587   histograms.ExpectBucketCount("NewTabPage.LogoShown.Fresh",
588                                kLogoImpressionStatic, 1);
589   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
590 }
591 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldFadeDefaultToInteractiveDoodleWhenFetched)592 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
593                        ShouldFadeDefaultToInteractiveDoodleWhenFetched) {
594   EncodedLogo fresh_logo;
595   fresh_logo.encoded_image = MakeRefPtr(std::string());
596   fresh_logo.metadata.mime_type = "image/png";
597   fresh_logo.metadata.type = LogoType::INTERACTIVE;
598   fresh_logo.metadata.full_page_url =
599       GURL("https://www.chromium.org/interactive");
600   fresh_logo.metadata.alt_text = "alt text";
601   fresh_logo.metadata.iframe_width_px = 500;
602   fresh_logo.metadata.iframe_height_px = 200;
603 
604   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
605       .WillOnce(
606           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
607                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, fresh_logo)))
608       .WillRepeatedly(DoAll(
609           ReturnCachedLogo(LogoCallbackReason::DETERMINED, fresh_logo),
610           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
611 
612   // Open a new blank tab, then go to local NTP.
613   content::WebContents* active_tab =
614       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
615   ui_test_utils::NavigateToURL(browser(),
616                                GURL(chrome::kChromeSearchLocalNtpUrl));
617 
618   WaitForFadeIn(active_tab, "logo-doodle");
619   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
620   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
621   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
622   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
623               Eq<std::string>("none"));
624   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
625               Eq<std::string>("block"));
626   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-iframe", "src"),
627               Eq<std::string>("https://www.chromium.org/interactive"));
628 }
629 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldNotFadeFromInteractiveDoodle)630 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldNotFadeFromInteractiveDoodle) {
631   EncodedLogo cached_logo;
632   cached_logo.encoded_image = MakeRefPtr(std::string());
633   cached_logo.metadata.mime_type = "image/png";
634   cached_logo.metadata.type = LogoType::INTERACTIVE;
635   cached_logo.metadata.full_page_url =
636       GURL("https://www.chromium.org/interactive");
637   cached_logo.metadata.alt_text = "alt text";
638   cached_logo.metadata.iframe_width_px = 500;
639   cached_logo.metadata.iframe_height_px = 200;
640 
641   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
642       .WillOnce(
643           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
644                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, base::nullopt)))
645       .WillRepeatedly(DoAll(
646           ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
647           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
648 
649   // Open a new blank tab, then go to local NTP.
650   content::WebContents* active_tab =
651       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
652   ui_test_utils::NavigateToURL(browser(),
653                                GURL(chrome::kChromeSearchLocalNtpUrl));
654 
655   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
656   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
657   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
658   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
659               Eq<std::string>("none"));
660   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
661               Eq<std::string>("block"));
662   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-iframe", "src"),
663               Eq<std::string>("https://www.chromium.org/interactive"));
664 }
665 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldFadeSimpleDoodleToSimpleDoodleWhenFetched)666 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
667                        ShouldFadeSimpleDoodleToSimpleDoodleWhenFetched) {
668   EncodedLogo cached_logo;
669   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
670   cached_logo.metadata.mime_type = "image/png";
671   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/cached");
672   cached_logo.metadata.alt_text = "cached alt text";
673 
674   EncodedLogo fresh_logo;
675   fresh_logo.encoded_image = MakeRefPtr(kFreshB64);
676   fresh_logo.metadata.mime_type = "image/png";
677   fresh_logo.metadata.on_click_url = GURL("https://www.chromium.org/fresh");
678   fresh_logo.metadata.alt_text = "fresh alt text";
679 
680   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
681       .WillOnce(
682           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
683                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, fresh_logo)))
684       .WillRepeatedly(DoAll(
685           ReturnCachedLogo(LogoCallbackReason::DETERMINED, fresh_logo),
686           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
687 
688   // Open a new blank tab, then go to local NTP.
689   content::WebContents* active_tab =
690       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
691   base::HistogramTester histograms;
692   ui_test_utils::NavigateToURL(browser(),
693                                GURL(chrome::kChromeSearchLocalNtpUrl));
694 
695   WaitForFadeIn(active_tab, "logo-doodle");
696   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
697   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
698   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
699   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
700               Eq<std::string>("inline-block"));
701   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
702               Eq<std::string>("none"));
703   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"),
704               Eq<std::string>("data:image/png;base64,YWJj"));
705   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
706               Eq<std::string>("fresh alt text"));
707   // TODO(sfiera): check href by clicking on button.
708 
709   // LogoShown is recorded for both cached and fresh Doodle, but LogoShownTime2
710   // is only recorded once per NTP.
711   histograms.ExpectTotalCount("NewTabPage.LogoShown", 2);
712   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
713                                2);
714   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 1);
715   histograms.ExpectBucketCount("NewTabPage.LogoShown.FromCache",
716                                kLogoImpressionStatic, 1);
717   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 1);
718   histograms.ExpectBucketCount("NewTabPage.LogoShown.Fresh",
719                                kLogoImpressionStatic, 1);
720   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
721 }
722 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldUpdateMetadataWhenChanged)723 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldUpdateMetadataWhenChanged) {
724   EncodedLogo cached_logo;
725   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
726   cached_logo.metadata.mime_type = "image/png";
727   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/cached");
728   cached_logo.metadata.alt_text = "cached alt text";
729 
730   EncodedLogo fresh_logo;
731   fresh_logo.encoded_image = cached_logo.encoded_image;
732   fresh_logo.metadata.mime_type = cached_logo.metadata.mime_type;
733   fresh_logo.metadata.on_click_url = GURL("https://www.chromium.org/fresh");
734   fresh_logo.metadata.alt_text = "fresh alt text";
735 
736   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
737       .WillOnce(
738           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
739                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, fresh_logo)))
740       .WillRepeatedly(DoAll(
741           ReturnCachedLogo(LogoCallbackReason::DETERMINED, fresh_logo),
742           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
743 
744   // Open a new blank tab, then go to local NTP.
745   content::WebContents* active_tab =
746       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
747   base::HistogramTester histograms;
748   ui_test_utils::NavigateToURL(browser(),
749                                GURL(chrome::kChromeSearchLocalNtpUrl));
750 
751   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
752   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
753   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
754   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
755               Eq<std::string>("inline-block"));
756   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
757               Eq<std::string>("none"));
758 
759   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
760               Eq<std::string>("fresh alt text"));
761   // TODO(sfiera): check href by clicking on button.
762 
763   // Metadata update does not count as a new impression.
764   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
765   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
766                                1);
767   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 1);
768   histograms.ExpectBucketCount("NewTabPage.LogoShown.FromCache",
769                                kLogoImpressionStatic, 1);
770   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 0);
771   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
772 }
773 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldAppendShareButtonWhenCached)774 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldAppendShareButtonWhenCached) {
775   EncodedLogo cached_logo;
776   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
777   cached_logo.metadata.mime_type = "image/png";
778   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
779   cached_logo.metadata.alt_text = "Chromium";
780   cached_logo.metadata.short_link = GURL("https://g.co");
781   cached_logo.metadata.share_button_x = 12;
782   cached_logo.metadata.share_button_y = 39;
783   cached_logo.metadata.share_button_opacity = 0.8;
784   cached_logo.metadata.share_button_icon = "sbimg";
785   cached_logo.metadata.share_button_bg = "#ffff00";
786 
787   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
788       .WillRepeatedly(DoAll(
789           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
790           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
791 
792   // Open a new blank tab, then go to local NTP and listen for console messages.
793   content::WebContents* active_tab =
794       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
795   FailOnConsoleMessage console_observer(active_tab);
796   base::HistogramTester histograms;
797   ui_test_utils::NavigateToURL(browser(),
798                                GURL(chrome::kChromeSearchLocalNtpUrl));
799 
800   EXPECT_TRUE(ElementExists(active_tab, "ddlsb"));
801   EXPECT_TRUE(ElementExists(active_tab, "ddlsb-img"));
802   EXPECT_THAT(GetComputedStyle(active_tab, "ddlsb", "left"),
803               Eq<std::string>("12px"));
804   EXPECT_THAT(GetComputedStyle(active_tab, "ddlsb", "top"),
805               Eq<std::string>("39px"));
806   EXPECT_THAT(GetComputedStyle(active_tab, "ddlsb", "background-color"),
807               Eq<std::string>("rgba(255, 255, 0, 0.8)"));
808   EXPECT_THAT(GetElementProperty(active_tab, "ddlsb-img", "src"),
809               Eq<std::string>("data:image/png;base64,sbimg"));
810 }
811 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldNotAppendShareButtonWhenCacheEmpty)812 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
813                        ShouldNotAppendShareButtonWhenCacheEmpty) {
814   EncodedLogo cached_logo;
815   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
816   cached_logo.metadata.mime_type = "image/png";
817   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
818   cached_logo.metadata.alt_text = "Chromium";
819   cached_logo.metadata.short_link = GURL("https://g.co");
820   cached_logo.metadata.share_button_x = -1;
821   cached_logo.metadata.share_button_y = -1;
822   cached_logo.metadata.share_button_opacity = 0;
823   cached_logo.metadata.share_button_icon = "";
824   cached_logo.metadata.share_button_bg = "";
825 
826   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
827       .WillRepeatedly(DoAll(
828           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
829           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
830 
831   // Open a new blank tab, then go to local NTP and listen for console messages.
832   content::WebContents* active_tab =
833       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
834   FailOnConsoleMessage console_observer(active_tab);
835   ui_test_utils::NavigateToURL(browser(),
836                                GURL(chrome::kChromeSearchLocalNtpUrl));
837 
838   EXPECT_FALSE(ElementExists(active_tab, "ddlsb"));
839   EXPECT_FALSE(ElementExists(active_tab, "ddlsb-img"));
840 }
841 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldNotAppendShareButtonWhenCacheIncomplete)842 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
843                        ShouldNotAppendShareButtonWhenCacheIncomplete) {
844   EncodedLogo cached_logo;
845   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
846   cached_logo.metadata.mime_type = "image/png";
847   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
848   cached_logo.metadata.alt_text = "Chromium";
849   cached_logo.metadata.short_link = GURL("https://g.co");
850   cached_logo.metadata.share_button_x = 12;
851   cached_logo.metadata.share_button_y = 36;
852   cached_logo.metadata.share_button_opacity = 0.8;
853   cached_logo.metadata.share_button_icon = "";
854   cached_logo.metadata.share_button_bg = "#ffff00";
855 
856   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
857       .WillRepeatedly(DoAll(
858           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
859           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
860 
861   // Open a new blank tab, then go to local NTP and listen for console messages.
862   content::WebContents* active_tab =
863       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
864   FailOnConsoleMessage console_observer(active_tab);
865   ui_test_utils::NavigateToURL(browser(),
866                                GURL(chrome::kChromeSearchLocalNtpUrl));
867 
868   EXPECT_FALSE(ElementExists(active_tab, "ddlsb"));
869   EXPECT_FALSE(ElementExists(active_tab, "ddlsb-img"));
870 }
871 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldShowShareDialogWhenShareButtonClicked)872 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
873                        ShouldShowShareDialogWhenShareButtonClicked) {
874   EncodedLogo cached_logo;
875   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
876   cached_logo.metadata.mime_type = "image/png";
877   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
878   cached_logo.metadata.alt_text = "Chromium";
879   cached_logo.metadata.short_link = GURL("https://g.co");
880   cached_logo.metadata.share_button_x = 12;
881   cached_logo.metadata.share_button_y = 36;
882   cached_logo.metadata.share_button_opacity = 0.8;
883   cached_logo.metadata.share_button_icon = "sbimg";
884   cached_logo.metadata.share_button_bg = "#ffff00";
885 
886   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
887       .WillRepeatedly(DoAll(
888           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
889           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
890 
891   // Open a new blank tab, then go to local NTP and listen for console messages.
892   content::WebContents* active_tab =
893       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
894   FailOnConsoleMessage console_observer(active_tab);
895   ui_test_utils::NavigateToURL(browser(),
896                                GURL(chrome::kChromeSearchLocalNtpUrl));
897 
898   EXPECT_FALSE(DialogIsOpen(active_tab, "ddlsd"));
899   ASSERT_TRUE(content::ExecuteScript(
900       active_tab, "document.getElementById('ddlsb').click();"));
901   EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd"));
902 
903   // Check title
904   std::string title;
905   ASSERT_TRUE(instant_test_utils::GetStringFromJS(
906       active_tab, "document.getElementById('ddlsd-title').innerHTML", &title));
907   EXPECT_THAT(title, Eq<std::string>(cached_logo.metadata.alt_text));
908 
909   // Check share link inside textbox
910   std::string link;
911   ASSERT_TRUE(instant_test_utils::GetStringFromJS(
912       active_tab, "document.getElementById('ddlsd-text').value", &link));
913   EXPECT_THAT(link, Eq<std::string>("https://g.co/"));
914 
915   ASSERT_TRUE(content::ExecuteScript(
916       active_tab, "document.getElementById('ddlsd-close').click();"));
917   EXPECT_FALSE(DialogIsOpen(active_tab, "ddlsd"));
918 }
919 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldOpenFacebookInShareDialog)920 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldOpenFacebookInShareDialog) {
921   EncodedLogo cached_logo;
922   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
923   cached_logo.metadata.mime_type = "image/png";
924   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
925   cached_logo.metadata.alt_text = "Chromium";
926   cached_logo.metadata.short_link = GURL("https://g.co");
927   cached_logo.metadata.share_button_x = 12;
928   cached_logo.metadata.share_button_y = 36;
929   cached_logo.metadata.share_button_opacity = 0.8;
930   cached_logo.metadata.share_button_icon = "sbimg";
931   cached_logo.metadata.share_button_bg = "#ffff00";
932 
933   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
934       .WillRepeatedly(DoAll(
935           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
936           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
937 
938   // Open a new blank tab, then go to local NTP and listen for console messages.
939   content::WebContents* active_tab =
940       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
941   ui_test_utils::NavigateToURL(browser(),
942                                GURL(chrome::kChromeSearchLocalNtpUrl));
943 
944   ASSERT_TRUE(content::ExecuteScript(
945       active_tab, "document.getElementById('ddlsb').click();"));
946   EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd"));
947   SetupWindowOpenTest(active_tab);
948   ASSERT_TRUE(content::ExecuteScript(
949       active_tab, "document.getElementById('ddlsd-fbb').click();"));
950   EXPECT_THAT(GetWindowOpenURL(active_tab),
951               Eq<std::string>(
952                   "https://www.facebook.com/dialog/share?app_id=738026486351791"
953                   "&href=https%3A%2F%2Fg.co%2F&hashtag=%23GoogleDoodle"));
954 }
955 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldOpenTwitterInShareDialog)956 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldOpenTwitterInShareDialog) {
957   EncodedLogo cached_logo;
958   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
959   cached_logo.metadata.mime_type = "image/png";
960   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
961   cached_logo.metadata.alt_text = "Chromium";
962   cached_logo.metadata.short_link = GURL("https://g.co");
963   cached_logo.metadata.share_button_x = 12;
964   cached_logo.metadata.share_button_y = 36;
965   cached_logo.metadata.share_button_opacity = 0.8;
966   cached_logo.metadata.share_button_icon = "sbimg";
967   cached_logo.metadata.share_button_bg = "#ffff00";
968 
969   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
970       .WillRepeatedly(DoAll(
971           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
972           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
973 
974   // Open a new blank tab, then go to local NTP and listen for console messages.
975   content::WebContents* active_tab =
976       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
977   ui_test_utils::NavigateToURL(browser(),
978                                GURL(chrome::kChromeSearchLocalNtpUrl));
979 
980   ASSERT_TRUE(content::ExecuteScript(
981       active_tab, "document.getElementById('ddlsb').click();"));
982   EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd"));
983   SetupWindowOpenTest(active_tab);
984   ASSERT_TRUE(content::ExecuteScript(
985       active_tab, "document.getElementById('ddlsd-twb').click();"));
986   EXPECT_THAT(GetWindowOpenURL(active_tab),
987               Eq<std::string>("https://twitter.com/intent/tweet"
988                               "?text=Chromium%0Ahttps%3A%2F%2Fg.co%2F"));
989 }
990 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldCopyLinkInShareDialog)991 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldCopyLinkInShareDialog) {
992   EncodedLogo cached_logo;
993   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
994   cached_logo.metadata.mime_type = "image/png";
995   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
996   cached_logo.metadata.alt_text = "Chromium";
997   cached_logo.metadata.short_link = GURL("https://g.co");
998   cached_logo.metadata.share_button_x = 12;
999   cached_logo.metadata.share_button_y = 36;
1000   cached_logo.metadata.share_button_opacity = 0.8;
1001   cached_logo.metadata.share_button_icon = "sbimg";
1002   cached_logo.metadata.share_button_bg = "#ffff00";
1003 
1004   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1005       .WillRepeatedly(DoAll(
1006           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1007           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1008 
1009   // Open a new blank tab, then go to local NTP and listen for console messages.
1010   content::WebContents* active_tab =
1011       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1012   ui_test_utils::NavigateToURL(browser(),
1013                                GURL(chrome::kChromeSearchLocalNtpUrl));
1014 
1015   ASSERT_TRUE(content::ExecuteScript(
1016       active_tab, "document.getElementById('ddlsb').click();"));
1017   EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd"));
1018 
1019   ASSERT_TRUE(content::ExecuteScript(
1020       active_tab, "document.getElementById('ddlsd-copy').click();"));
1021   std::string short_link;
1022   ASSERT_TRUE(instant_test_utils::GetStringFromJS(
1023       active_tab, "window.getSelection().toString()", &short_link));
1024   EXPECT_EQ("https://g.co/", short_link);
1025 }
1026 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldLogShareClicksNoEventId)1027 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldLogShareClicksNoEventId) {
1028   EncodedLogo cached_logo;
1029   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
1030   cached_logo.metadata.mime_type = "image/png";
1031   cached_logo.metadata.on_click_url =
1032       GURL("https://www.chrotmium.org/?ct=test");
1033   cached_logo.metadata.alt_text = "Chromium";
1034   cached_logo.metadata.short_link = GURL("https://g.co");
1035   cached_logo.metadata.share_button_x = 12;
1036   cached_logo.metadata.share_button_y = 36;
1037   cached_logo.metadata.share_button_opacity = 0.8;
1038   cached_logo.metadata.share_button_icon = "sbimg";
1039   cached_logo.metadata.share_button_bg = "#ffff00";
1040 
1041   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1042       .WillRepeatedly(DoAll(
1043           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1044           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1045 
1046   // Open a new blank tab, then go to local NTP and listen for console messages.
1047   content::WebContents* active_tab =
1048       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1049   ui_test_utils::NavigateToURL(browser(),
1050                                GURL(chrome::kChromeSearchLocalNtpUrl));
1051 
1052   // Replace window.open so we stay in the same tab.
1053   SetupWindowOpenTest(active_tab);
1054   SetupBeaconTest(active_tab);
1055 
1056   ASSERT_TRUE(content::ExecuteScript(
1057       active_tab, "document.getElementById('ddlsb').click();"));
1058 
1059   ASSERT_TRUE(content::ExecuteScript(
1060       active_tab, "document.getElementById('ddlsd-fbb').click();"));
1061   EXPECT_THAT(
1062       GetBeaconURL(active_tab),
1063       Eq<std::string>("https://www.google.com/gen_204"
1064                       "?atyp=i&ct=doodle&cad=sh%2C2%2Cct%3Atest&ntp=1"));
1065 
1066   ASSERT_TRUE(content::ExecuteScript(
1067       active_tab, "document.getElementById('ddlsd-twb').click();"));
1068   EXPECT_THAT(
1069       GetBeaconURL(active_tab),
1070       Eq<std::string>("https://www.google.com/gen_204"
1071                       "?atyp=i&ct=doodle&cad=sh%2C3%2Cct%3Atest&ntp=1"));
1072 
1073   ASSERT_TRUE(content::ExecuteScript(
1074       active_tab, "document.getElementById('ddlsd-emb').click();"));
1075   EXPECT_THAT(
1076       GetBeaconURL(active_tab),
1077       Eq<std::string>("https://www.google.com/gen_204"
1078                       "?atyp=i&ct=doodle&cad=sh%2C5%2Cct%3Atest&ntp=1"));
1079 
1080   ASSERT_TRUE(content::ExecuteScript(
1081       active_tab, "document.getElementById('ddlsd-copy').click();"));
1082   std::string short_link;
1083   EXPECT_THAT(
1084       GetBeaconURL(active_tab),
1085       Eq<std::string>("https://www.google.com/gen_204"
1086                       "?atyp=i&ct=doodle&cad=sh%2C6%2Cct%3Atest&ntp=1"));
1087 }
1088 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldLogShareClicksWithEventId)1089 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldLogShareClicksWithEventId) {
1090   EncodedLogo cached_logo;
1091   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
1092   cached_logo.metadata.mime_type = "image/png";
1093   cached_logo.metadata.on_click_url =
1094       GURL("https://www.chrotmium.org/?ct=test");
1095   cached_logo.metadata.alt_text = "Chromium";
1096   cached_logo.metadata.short_link = GURL("https://g.co");
1097   cached_logo.metadata.share_button_x = 12;
1098   cached_logo.metadata.share_button_y = 36;
1099   cached_logo.metadata.share_button_opacity = 0.8;
1100   cached_logo.metadata.share_button_icon = "sbimg";
1101   cached_logo.metadata.share_button_bg = "#ffff00";
1102 
1103   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1104       .WillRepeatedly(DoAll(
1105           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1106           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1107 
1108   // Open a new blank tab, then go to local NTP and listen for console messages.
1109   content::WebContents* active_tab =
1110       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1111   ui_test_utils::NavigateToURL(browser(),
1112                                GURL(chrome::kChromeSearchLocalNtpUrl));
1113 
1114   // Replace window.open so we stay in the same tab.
1115   SetupWindowOpenTest(active_tab);
1116   SetupBeaconTest(active_tab);
1117 
1118   ASSERT_TRUE(content::ExecuteScript(active_tab, "doodles.ei = 'test_ei';"));
1119 
1120   ASSERT_TRUE(content::ExecuteScript(
1121       active_tab, "document.getElementById('ddlsb').click();"));
1122 
1123   ASSERT_TRUE(content::ExecuteScript(
1124       active_tab, "document.getElementById('ddlsd-fbb').click();"));
1125   EXPECT_THAT(
1126       GetBeaconURL(active_tab),
1127       Eq<std::string>("https://www.google.com/gen_204?atyp=i"
1128                       "&ct=doodle&cad=sh%2C2%2Cct%3Atest&ntp=1&ei=test_ei"));
1129 
1130   ASSERT_TRUE(content::ExecuteScript(
1131       active_tab, "document.getElementById('ddlsd-twb').click();"));
1132   EXPECT_THAT(
1133       GetBeaconURL(active_tab),
1134       Eq<std::string>("https://www.google.com/gen_204?atyp=i"
1135                       "&ct=doodle&cad=sh%2C3%2Cct%3Atest&ntp=1&ei=test_ei"));
1136 
1137   ASSERT_TRUE(content::ExecuteScript(
1138       active_tab, "document.getElementById('ddlsd-emb').click();"));
1139   EXPECT_THAT(
1140       GetBeaconURL(active_tab),
1141       Eq<std::string>("https://www.google.com/gen_204?atyp=i"
1142                       "&ct=doodle&cad=sh%2C5%2Cct%3Atest&ntp=1&ei=test_ei"));
1143 
1144   ASSERT_TRUE(content::ExecuteScript(
1145       active_tab, "document.getElementById('ddlsd-copy').click();"));
1146   std::string short_link;
1147   EXPECT_THAT(
1148       GetBeaconURL(active_tab),
1149       Eq<std::string>("https://www.google.com/gen_204?atyp=i"
1150                       "&ct=doodle&cad=sh%2C6%2Cct%3Atest&ntp=1&ei=test_ei"));
1151 }
1152 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldAnimateLogoWhenClicked)1153 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldAnimateLogoWhenClicked) {
1154   EncodedLogo cached_logo;
1155   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
1156   cached_logo.metadata.mime_type = "image/png";
1157   cached_logo.metadata.type = LogoType::ANIMATED;
1158   cached_logo.metadata.animated_url = GURL("data:image/png;base64,eHl6");
1159   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
1160   cached_logo.metadata.alt_text = "alt text";
1161 
1162   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1163       .WillRepeatedly(DoAll(
1164           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1165           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1166 
1167   // Open a new blank tab, then go to local NTP.
1168   content::WebContents* active_tab =
1169       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1170   base::HistogramTester histograms;
1171   ui_test_utils::NavigateToURL(browser(),
1172                                GURL(chrome::kChromeSearchLocalNtpUrl));
1173 
1174   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1175   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
1176   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
1177   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
1178               Eq<std::string>("inline-block"));
1179   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
1180               Eq<std::string>("none"));
1181 
1182   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"),
1183               Eq<std::string>("data:image/png;base64,cached++"));
1184   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
1185               Eq<std::string>("alt text"));
1186 
1187   // Click image, swapping out for animated URL.
1188   ASSERT_TRUE(content::ExecuteScript(
1189       active_tab, "document.getElementById('logo-doodle-button').click();"));
1190 
1191   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1192   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"),
1193               Eq(cached_logo.metadata.animated_url.spec()));
1194   // TODO(sfiera): check href by clicking on button.
1195 
1196   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
1197   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionCta, 1);
1198   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 1);
1199   histograms.ExpectBucketCount("NewTabPage.LogoShown.FromCache",
1200                                kLogoImpressionCta, 1);
1201   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 0);
1202   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
1203   histograms.ExpectTotalCount("NewTabPage.LogoClick", 1);
1204   histograms.ExpectBucketCount("NewTabPage.LogoClick", kLogoClickCta, 1);
1205 }
1206 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldAddShareButtonInAnimatedDoodle)1207 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,
1208                        ShouldAddShareButtonInAnimatedDoodle) {
1209   EncodedLogo cached_logo;
1210   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
1211   cached_logo.metadata.mime_type = "image/png";
1212   cached_logo.metadata.type = LogoType::ANIMATED;
1213   cached_logo.metadata.animated_url = GURL("data:image/png;base64,eHl6");
1214   cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
1215   cached_logo.metadata.alt_text = "alt text";
1216   cached_logo.metadata.short_link = GURL("https://g.co");
1217   cached_logo.metadata.share_button_x = 12;
1218   cached_logo.metadata.share_button_y = 36;
1219   cached_logo.metadata.share_button_opacity = 0.8;
1220   cached_logo.metadata.share_button_icon = "sbimg";
1221   cached_logo.metadata.share_button_bg = "#ffff00";
1222 
1223   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1224       .WillRepeatedly(DoAll(
1225           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1226           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1227 
1228   // Open a new blank tab, then go to local NTP.
1229   content::WebContents* active_tab =
1230       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1231   base::HistogramTester histograms;
1232   ui_test_utils::NavigateToURL(browser(),
1233                                GURL(chrome::kChromeSearchLocalNtpUrl));
1234 
1235   // Share button should not be present pre-CTA click
1236   EXPECT_FALSE(ElementExists(active_tab, "ddlsb"));
1237   ASSERT_TRUE(content::ExecuteScript(
1238       active_tab, "document.getElementById('logo-doodle-button').click();"));
1239 
1240   // Share button is only added post-CTA click when the animation is playing
1241   EXPECT_TRUE(ElementExists(active_tab, "ddlsb"));
1242 }
1243 
WaitForDdllogResponse(content::WebContents * tab,int expected_ddllog_count)1244 std::string WaitForDdllogResponse(content::WebContents* tab,
1245                                   int expected_ddllog_count) {
1246   std::string response;
1247   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
1248       tab,
1249       base::StringPrintf(R"js(
1250         if (doodles.numDdllogResponsesReceived == %i) {
1251           window.domAutomationController.send(doodles.lastDdllogResponse);
1252         } else {
1253           doodles.onDdllogResponse = function() {
1254             if (doodles.numDdllogResponsesReceived == %i) {
1255               window.domAutomationController.send(doodles.lastDdllogResponse);
1256               doodles.onDdllogResponse = null;
1257             }
1258           }
1259         }                )js",
1260                          expected_ddllog_count, expected_ddllog_count),
1261       &response));
1262   return response;
1263 }
1264 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldLogForSimpleDoodle)1265 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldLogForSimpleDoodle) {
1266   // Start a test server to provide the ddllog response.
1267   net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
1268   test_server.ServeFilesFromSourceDirectory("chrome/test/data/local_ntp");
1269   ASSERT_TRUE(test_server.Start());
1270   const GURL on_click_url = test_server.GetURL("/simple.html");
1271   const GURL log_url = test_server.GetURL("/ddllog-target_url_params");
1272 
1273   EncodedLogo cached_logo;
1274   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
1275   cached_logo.metadata.mime_type = "image/png";
1276   cached_logo.metadata.on_click_url = on_click_url;
1277   cached_logo.metadata.alt_text = "Chromium";
1278   cached_logo.metadata.log_url = log_url;
1279 
1280   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1281       .WillRepeatedly(DoAll(
1282           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1283           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1284 
1285   // Open a new blank tab, then go to local NTP and listen for console messages.
1286   content::WebContents* active_tab =
1287       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1288   FailOnConsoleMessage console_observer(active_tab);
1289   ui_test_utils::NavigateToURL(browser(),
1290                                GURL(chrome::kChromeSearchLocalNtpUrl));
1291 
1292   ASSERT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
1293 
1294   // Wait for the ddllog request to get resolved.
1295   std::string response = WaitForDdllogResponse(active_tab, 1);
1296   EXPECT_EQ("target_url_params a=b&c=d", response);
1297 
1298   content::TestNavigationObserver nav_observer(active_tab);
1299   ASSERT_TRUE(content::ExecuteScript(
1300       active_tab, "document.getElementById('logo-doodle-button').click();"));
1301   nav_observer.Wait();
1302   ASSERT_TRUE(nav_observer.last_navigation_succeeded());
1303 
1304   std::string target_url;
1305   ASSERT_TRUE(instant_test_utils::GetStringFromJS(
1306       active_tab, "document.location.href", &target_url));
1307   EXPECT_EQ(on_click_url.spec() + "?a=b&c=d", target_url);
1308 }
1309 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldLogForAnimatedDoodle)1310 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldLogForAnimatedDoodle) {
1311   // Start a test server to provide the ddllog responses.
1312   net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
1313   test_server.ServeFilesFromSourceDirectory("chrome/test/data/local_ntp");
1314   ASSERT_TRUE(test_server.Start());
1315   const GURL on_click_url = test_server.GetURL("/simple.html");
1316   const GURL cta_log_url = test_server.GetURL("/ddllog-interaction_log_url");
1317   const GURL log_url = test_server.GetURL("/ddllog-target_url_params");
1318 
1319   EncodedLogo cached_logo;
1320   cached_logo.encoded_image = MakeRefPtr(kCachedB64);
1321   cached_logo.metadata.mime_type = "image/png";
1322   cached_logo.metadata.type = LogoType::ANIMATED;
1323   cached_logo.metadata.animated_url =
1324       GURL(std::string("data:image/gif;base64,") + kTinyGifData);
1325   cached_logo.metadata.on_click_url = on_click_url;
1326   cached_logo.metadata.alt_text = "alt text";
1327   cached_logo.metadata.cta_log_url = cta_log_url;
1328   cached_logo.metadata.log_url = log_url;
1329 
1330   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1331       .WillRepeatedly(DoAll(
1332           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1333           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1334 
1335   // Open a new blank tab, then go to local NTP and listen for console messages.
1336   content::WebContents* active_tab =
1337       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1338   FailOnConsoleMessage console_observer(active_tab);
1339   ui_test_utils::NavigateToURL(browser(),
1340                                GURL(chrome::kChromeSearchLocalNtpUrl));
1341 
1342   ASSERT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
1343 
1344   // Wait for the first (CTA) ddllog request to get resolved.
1345   std::string cta_response = WaitForDdllogResponse(active_tab, 1);
1346   EXPECT_EQ(
1347       "interaction_log_url https://www.chromium.org/doodle_interaction_log",
1348       cta_response);
1349 
1350   // Click image, swapping out for animated URL.
1351   ASSERT_TRUE(content::ExecuteScript(
1352       active_tab, "document.getElementById('logo-doodle-button').click();"));
1353   ASSERT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"),
1354               Eq(cached_logo.metadata.animated_url.spec()));
1355 
1356   // Wait for the second (non-CTA) ddllog request to get resolved.
1357   std::string anim_response = WaitForDdllogResponse(active_tab, 2);
1358   EXPECT_EQ("target_url_params a=b&c=d", anim_response);
1359 
1360   content::TestNavigationObserver nav_observer(active_tab);
1361   ASSERT_TRUE(content::ExecuteScript(
1362       active_tab, "document.getElementById('logo-doodle-button').click();"));
1363   nav_observer.Wait();
1364   ASSERT_TRUE(nav_observer.last_navigation_succeeded());
1365 
1366   std::string target_url;
1367   ASSERT_TRUE(instant_test_utils::GetStringFromJS(
1368       active_tab, "document.location.href", &target_url));
1369   EXPECT_EQ(on_click_url.spec() + "?a=b&c=d", target_url);
1370 }
1371 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldNotMoveFakeboxForIframeSizes)1372 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldNotMoveFakeboxForIframeSizes) {
1373   for (int height : {0, 150, 229, 500}) {
1374     EncodedLogo cached_logo;
1375     cached_logo.encoded_image = MakeRefPtr(std::string());
1376     cached_logo.metadata.mime_type = "image/png";
1377     cached_logo.metadata.type = LogoType::INTERACTIVE;
1378     cached_logo.metadata.full_page_url =
1379         GURL("https://www.chromium.org/interactive");
1380     cached_logo.metadata.alt_text = "alt text";
1381     cached_logo.metadata.iframe_width_px = 500;
1382     cached_logo.metadata.iframe_height_px = height;
1383 
1384     EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1385         .WillRepeatedly(DoAll(
1386             ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1387             ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1388 
1389     // Open a new blank tab, then go to local NTP.
1390     content::WebContents* active_tab =
1391         local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1392     base::HistogramTester histograms;
1393     ui_test_utils::NavigateToURL(browser(),
1394                                  GURL(chrome::kChromeSearchLocalNtpUrl));
1395 
1396     EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx))
1397         << "iframe_height_px = " << height;
1398   }
1399 }
1400 
IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest,ShouldMoveFakeboxWhenIframeResized)1401 IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldMoveFakeboxWhenIframeResized) {
1402   EncodedLogo cached_logo;
1403   cached_logo.encoded_image = MakeRefPtr(std::string());
1404   cached_logo.metadata.mime_type = "image/png";
1405   cached_logo.metadata.type = LogoType::INTERACTIVE;
1406   cached_logo.metadata.full_page_url =
1407       GURL("https://www.chromium.org/interactive");
1408   cached_logo.metadata.alt_text = "alt text";
1409   cached_logo.metadata.iframe_width_px = 400;
1410   cached_logo.metadata.iframe_height_px = 220;  // > 200, so smaller margin
1411 
1412   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1413       .WillRepeatedly(DoAll(
1414           ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo),
1415           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1416 
1417   // Open a new blank tab, then go to local NTP.
1418   content::WebContents* active_tab =
1419       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1420   base::HistogramTester histograms;
1421   ui_test_utils::NavigateToURL(browser(),
1422                                GURL(chrome::kChromeSearchLocalNtpUrl));
1423 
1424   // Initial dimensions are correct:
1425   EXPECT_THAT(*GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1426   EXPECT_THAT(*GetDimension(active_tab, "logo-doodle-iframe", "width"),
1427               Eq(400));
1428   EXPECT_THAT(*GetDimension(active_tab, "logo-doodle-iframe", "height"),
1429               Eq(220));
1430 
1431   // Trigger resize. The duration parameter is left untested, since that would
1432   // require introducing a potentially-flaky sleep in the test. Additionally,
1433   // this would really be a cross-origin postMessage, from the Doodle iframe,
1434   // origin google.com.
1435   ASSERT_TRUE(content::ExecuteScript(active_tab,
1436                                      R"js(
1437                                          window.postMessage({
1438                                              cmd: "resizeDoodle",
1439                                              width: "100%",
1440                                              height: "400px",  // 180px more
1441                                              duration: "0s",
1442                                          }, "chrome-search://local-ntp");
1443                                      )js"));
1444 
1445   // Fakebox is now 180px lower, with the iframe larger, as requested.
1446   EXPECT_THAT(*GetDimension(active_tab, "realbox", "top"),
1447               Eq(kRealboxTopPx + 180));
1448   EXPECT_THAT(*GetDimension(active_tab, "logo-doodle-iframe", "width"),
1449               Eq(*GetDimension(active_tab, "logo", "width")));
1450   EXPECT_THAT(*GetDimension(active_tab, "logo-doodle-iframe", "height"),
1451               Eq(400));
1452 
1453   ASSERT_TRUE(content::ExecuteScript(active_tab,
1454                                      R"js(
1455                                          window.postMessage({
1456                                              cmd: "resizeDoodle",
1457                                              width: "400px",
1458                                              height: "220px",
1459                                              duration: "0s",
1460                                          }, "chrome-search://local-ntp");
1461                                      )js"));
1462 
1463   // Back to the original dimensions now.
1464   EXPECT_THAT(*GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1465   EXPECT_THAT(*GetDimension(active_tab, "logo-doodle-iframe", "width"),
1466               Eq(400));
1467   EXPECT_THAT(*GetDimension(active_tab, "logo-doodle-iframe", "height"),
1468               Eq(220));
1469 }
1470 
1471 // TODO(crbug/980638): Update/Remove when Linux and/or ChromeOS support dark
1472 // mode.
1473 #if defined(OS_WIN) || defined(OS_MAC)
1474 
1475 // Tests that dark mode styling is properly applied to the local NTP Doodle.
1476 class LocalNTPDarkModeDoodleTest : public LocalNTPDoodleTest,
1477                                    public DarkModeTestBase {
1478  public:
1479   LocalNTPDarkModeDoodleTest() {}
1480 
1481  private:
1482   void SetUpOnMainThread() override {
1483     LocalNTPDoodleTest::SetUpOnMainThread();
1484 
1485     theme()->AddColorSchemeNativeThemeObserver(
1486         ui::NativeTheme::GetInstanceForWeb());
1487   }
1488 };
1489 
1490 IN_PROC_BROWSER_TEST_F(LocalNTPDarkModeDoodleTest,
1491                        ShouldFadeDefaultToSimpleDoodleWhenFetched) {
1492   InstantService* instant_service =
1493       InstantServiceFactory::GetForProfile(browser()->profile());
1494   theme()->SetDarkMode(true);
1495   instant_service->SetNativeThemeForTesting(theme());
1496   theme()->NotifyObservers();
1497 
1498   EncodedLogo fresh_logo;
1499   fresh_logo.encoded_image = MakeRefPtr(kFreshB64);
1500   fresh_logo.dark_encoded_image = MakeRefPtr(kFreshDarkB64);
1501   fresh_logo.metadata.mime_type = "image/png";
1502   fresh_logo.metadata.dark_mime_type = "image/png";
1503   fresh_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
1504   fresh_logo.metadata.alt_text = "Chromium";
1505   fresh_logo.metadata.dark_background_color = "#ABCDEF";
1506 
1507   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1508       .WillOnce(
1509           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
1510                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, fresh_logo)))
1511       .WillRepeatedly(DoAll(
1512           ReturnCachedLogo(LogoCallbackReason::DETERMINED, fresh_logo),
1513           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1514 
1515   // Open a new blank tab, then go to local NTP.
1516   content::WebContents* active_tab =
1517       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1518   base::HistogramTester histograms;
1519   ui_test_utils::NavigateToURL(browser(),
1520                                GURL(chrome::kChromeSearchLocalNtpUrl));
1521 
1522   WaitForFadeIn(active_tab, "logo-doodle");
1523   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1524   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
1525   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
1526   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
1527               Eq<std::string>("inline-block"));
1528   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-wrapper"),
1529               Eq<std::string>("inline-block"));
1530   EXPECT_THAT(
1531       GetComputedStyle(active_tab, "logo-doodle-wrapper", "background-color"),
1532       Eq<std::string>("rgb(171, 205, 239)"));
1533   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
1534               Eq<std::string>("none"));
1535   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
1536               Eq<std::string>("Chromium"));
1537   // TODO(sfiera): check href by clicking on button.
1538 
1539   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
1540   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
1541                                1);
1542   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0);
1543   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 1);
1544   histograms.ExpectBucketCount("NewTabPage.LogoShown.Fresh",
1545                                kLogoImpressionStatic, 1);
1546   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
1547 }
1548 
IN_PROC_BROWSER_TEST_F(LocalNTPDarkModeDoodleTest,DoodleUpdatesOnDarkModeChanged)1549 IN_PROC_BROWSER_TEST_F(LocalNTPDarkModeDoodleTest,
1550                        DoodleUpdatesOnDarkModeChanged) {
1551   InstantService* instant_service =
1552       InstantServiceFactory::GetForProfile(browser()->profile());
1553   theme()->SetDarkMode(false);
1554   instant_service->SetNativeThemeForTesting(theme());
1555   theme()->NotifyObservers();
1556 
1557   EncodedLogo fresh_logo;
1558   fresh_logo.encoded_image = MakeRefPtr(kFreshB64);
1559   fresh_logo.dark_encoded_image = MakeRefPtr(kFreshDarkB64);
1560   fresh_logo.metadata.mime_type = "image/png";
1561   fresh_logo.metadata.dark_mime_type = "image/png";
1562   fresh_logo.metadata.on_click_url = GURL("https://www.chromium.org/");
1563   fresh_logo.metadata.alt_text = "Chromium";
1564   fresh_logo.metadata.dark_background_color = "#ABCDEF";
1565 
1566   EXPECT_CALL(*logo_service(), GetLogoPtr(_))
1567       .WillOnce(
1568           DoAll(ReturnCachedLogo(LogoCallbackReason::DETERMINED, base::nullopt),
1569                 ReturnFreshLogo(LogoCallbackReason::DETERMINED, fresh_logo)))
1570       .WillRepeatedly(DoAll(
1571           ReturnCachedLogo(LogoCallbackReason::DETERMINED, fresh_logo),
1572           ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt)));
1573 
1574   // Open a new blank tab, then go to local NTP.
1575   content::WebContents* active_tab =
1576       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
1577   base::HistogramTester histograms;
1578   ui_test_utils::NavigateToURL(browser(),
1579                                GURL(chrome::kChromeSearchLocalNtpUrl));
1580 
1581   WaitForFadeIn(active_tab, "logo-doodle");
1582   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1583   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
1584   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
1585   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
1586               Eq<std::string>("inline-block"));
1587   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-wrapper"),
1588               Eq<std::string>("inline-block"));
1589   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
1590               Eq<std::string>("none"));
1591   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
1592               Eq<std::string>("Chromium"));
1593   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"),
1594               Eq<std::string>("data:image/png;base64,YWJj"));
1595   // TODO(sfiera): check href by clicking on button.
1596 
1597   histograms.ExpectTotalCount("NewTabPage.LogoShown", 1);
1598   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
1599                                1);
1600   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0);
1601   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 1);
1602   histograms.ExpectBucketCount("NewTabPage.LogoShown.Fresh",
1603                                kLogoImpressionStatic, 1);
1604   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
1605 
1606   content::DOMMessageQueue msg_queue(active_tab);
1607   theme()->SetDarkMode(true);
1608   theme()->NotifyObservers();
1609 
1610   local_ntp_test_utils::WaitUntilTilesLoaded(active_tab, &msg_queue,
1611                                              /*delay=*/1000);
1612 
1613   WaitForLogoSwap(active_tab, "logo-doodle");
1614   EXPECT_TRUE(GetIsDarkModeApplied(active_tab));
1615   EXPECT_THAT(GetDimension(active_tab, "realbox", "top"), Eq(kRealboxTopPx));
1616   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0));
1617   EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0));
1618   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"),
1619               Eq<std::string>("inline-block"));
1620   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-wrapper"),
1621               Eq<std::string>("inline-block"));
1622   EXPECT_THAT(
1623       GetComputedStyle(active_tab, "logo-doodle-wrapper", "background-color"),
1624       Eq<std::string>("rgb(171, 205, 239)"));
1625   EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"),
1626               Eq<std::string>("none"));
1627   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"),
1628               Eq<std::string>("Chromium"));
1629   EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"),
1630               Eq<std::string>("data:image/png;base64,eHl6"));
1631   // TODO(sfiera): check href by clicking on button.
1632 
1633   histograms.ExpectTotalCount("NewTabPage.LogoShown", 2);
1634   histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic,
1635                                2);
1636   histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0);
1637   histograms.ExpectTotalCount("NewTabPage.LogoShown.Fresh", 2);
1638   histograms.ExpectBucketCount("NewTabPage.LogoShown.Fresh",
1639                                kLogoImpressionStatic, 2);
1640   histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1);
1641 }
1642 
1643 #endif
1644