1 // Copyright 2018 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 
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/no_destructor.h"
13 #include "base/path_service.h"
14 #include "base/run_loop.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/search/instant_service.h"
19 #include "chrome/browser/search/instant_service_factory.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/search/local_ntp_test_utils.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "components/ntp_tiles/features.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/render_widget_host.h"
27 #include "content/public/browser/render_widget_host_view.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/test/browser_test.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "third_party/skia/include/core/SkBitmap.h"
32 #include "ui/compositor/compositor_switches.h"
33 #include "ui/gfx/codec/png_codec.h"
34 #include "ui/gfx/geometry/rect.h"
35 #include "ui/gfx/geometry/size.h"
36 
37 namespace {
38 
39 // Where the captures are stored.
GetTestDataDir()40 const base::FilePath& GetTestDataDir() {
41   static base::NoDestructor<base::FilePath> dir([]() {
42     base::FilePath dir;
43     base::PathService::Get(base::DIR_SOURCE_ROOT, &dir);
44     dir = dir.AppendASCII("components")
45               .AppendASCII("test")
46               .AppendASCII("data")
47               .AppendASCII("ntp")
48               .AppendASCII("render");
49     return dir;
50   }());
51   return *dir;
52 }
53 
54 class LocalNTPRenderTest : public InProcessBrowserTest {
55  public:
SetUp()56   void SetUp() override {
57     EnablePixelOutput();
58     InProcessBrowserTest::SetUp();
59   }
60 
LoadNewTabPageAndCapture(int viewport_width,int viewport_height,const std::string & filename)61   void LoadNewTabPageAndCapture(int viewport_width,
62                                 int viewport_height,
63                                 const std::string& filename) {
64     // Open an NTP and wait until it has fully loaded (tiles may animate, so we
65     // give this some delay).
66     local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser(),
67                                                           /*delay=*/1000);
68     content::WebContents* active_tab =
69         browser()->tab_strip_model()->GetActiveWebContents();
70     content::RenderFrameSubmissionObserver render_frame_observer(active_tab);
71 
72     content::RenderWidgetHost* render_widget_host =
73         active_tab->GetMainFrame()->GetRenderViewHost()->GetWidget();
74     content::RenderWidgetHostView* view = render_widget_host->GetView();
75     ASSERT_TRUE(view && view->IsSurfaceAvailableForCopy());
76 
77     // Resize the view to the desired size.
78     view->SetSize(gfx::Size(viewport_width, viewport_height));
79 
80     gfx::Rect copy_rect = gfx::Rect(view->GetViewBounds().size());
81     ASSERT_TRUE(!copy_rect.IsEmpty());
82     const cc::RenderFrameMetadata& last_metadata =
83         render_frame_observer.LastRenderFrameMetadata();
84     ASSERT_TRUE(last_metadata.is_scroll_offset_at_top);
85 
86     run_loop_ = std::make_unique<base::RunLoop>();
87     view->CopyFromSurface(copy_rect, copy_rect.size(),
88                           base::BindOnce(&LocalNTPRenderTest::OnCapturedBitmap,
89                                          base::Unretained(this), filename));
90     run_loop_->Run();
91   }
92 
93  private:
94   // Will write |bitmap| as a png in the test data directory with |filename|.
OnCapturedBitmap(const std::string & filename,const SkBitmap & bitmap)95   void OnCapturedBitmap(const std::string& filename, const SkBitmap& bitmap) {
96     std::vector<unsigned char> bitmap_data;
97     bool result =
98         gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data);
99     DCHECK(result);
100     base::ScopedAllowBlockingForTesting allow_blocking;
101     EXPECT_TRUE(
102         base::WriteFile(GetTestDataDir().AppendASCII(filename), bitmap_data));
103     run_loop_->Quit();
104   }
105 
106   std::unique_ptr<base::RunLoop> run_loop_;
107 };
108 
109 IN_PROC_BROWSER_TEST_F(LocalNTPRenderTest, 1200x800_DefaultMV) {
110   LoadNewTabPageAndCapture(/*viewport_width=*/1200, /*viewport_height=*/800,
111                            /*filename=*/"1200x800_DefaultMV.png");
112 }
113 
114 IN_PROC_BROWSER_TEST_F(LocalNTPRenderTest, 1200x800_MVWithCustomLinks) {
115   InstantService* instant_service =
116       InstantServiceFactory::GetForProfile(browser()->profile());
117   instant_service->AddCustomLink(GURL("http://192.168.1.1"), "My Router");
118   instant_service->AddCustomLink(GURL("https://www.apple.com"), "Apple");
119   instant_service->AddCustomLink(GURL("https://bobpay.xyz"), "BobPay");
120   instant_service->AddCustomLink(GURL("https://cnn.com"), "CNN");
121   instant_service->AddCustomLink(GURL("https://paymentrequest.show"),
122                                  "Payment Request Demo Site");
123   instant_service->AddCustomLink(GURL("https://google.com"), "Google");
124   instant_service->AddCustomLink(GURL("https://reddit.com/r/whatever"),
125                                  "Reddit");
126   instant_service->AddCustomLink(GURL("https://samsung.com"), "Samsung");
127 
128   LoadNewTabPageAndCapture(/*viewport_width=*/1200, /*viewport_height=*/800,
129                            /*filename=*/"1200x800_MVWithCustomLinks.png");
130 }
131 
132 }  // namespace
133