1 // Copyright (c) 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 "base/test/scoped_feature_list.h"
6 #include "content/browser/web_contents/web_contents_impl.h"
7 #include "content/common/content_navigation_policy.h"
8 #include "content/public/browser/render_frame_host.h"
9 #include "content/public/browser/web_contents_delegate.h"
10 #include "content/public/common/content_features.h"
11 #include "content/public/test/navigation_simulator.h"
12 #include "content/test/test_render_frame_host.h"
13 #include "content/test/test_render_view_host.h"
14 #include "content/test/test_web_contents.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 
17 namespace content {
18 
19 namespace {
20 
21 // Mock content::ColorChooser to test whether End() is called.
22 class MockColorChooser : public content::ColorChooser {
23  public:
24   MockColorChooser() = default;
25   ~MockColorChooser() override = default;
26 
27   MOCK_METHOD0(End, void());
28   MOCK_METHOD1(SetSelectedColor, void(SkColor color));
29 
30  private:
31   DISALLOW_COPY_AND_ASSIGN(MockColorChooser);
32 };
33 
34 // Delegate to override OpenColorChooser.
35 class OpenColorChooserDelegate : public WebContentsDelegate {
36  public:
OpenColorChooserDelegate(std::unique_ptr<MockColorChooser> mock_color_chooser)37   explicit OpenColorChooserDelegate(
38       std::unique_ptr<MockColorChooser> mock_color_chooser)
39       : mock_color_chooser_(std::move(mock_color_chooser)) {}
40 
41   ~OpenColorChooserDelegate() override = default;
42 
43   // WebContentsDelegate:
OpenColorChooser(WebContents * web_contents,SkColor color,const std::vector<blink::mojom::ColorSuggestionPtr> & suggestions)44   ColorChooser* OpenColorChooser(
45       WebContents* web_contents,
46       SkColor color,
47       const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions)
48       override {
49     return std::move(mock_color_chooser_).release();
50   }
51 
52  private:
53   std::unique_ptr<MockColorChooser> mock_color_chooser_;
54 
55   DISALLOW_COPY_AND_ASSIGN(OpenColorChooserDelegate);
56 };
57 
58 }  // namespace
59 
60 class ColorChooserUnitTest : public RenderViewHostImplTestHarness {};
61 
TEST_F(ColorChooserUnitTest,ColorChooserCallsEndOnNavigatingAway)62 TEST_F(ColorChooserUnitTest, ColorChooserCallsEndOnNavigatingAway) {
63   GURL kUrl1("https://foo.com");
64   GURL kUrl2("https://bar.com");
65 
66   // Navigate to A.
67   NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1);
68 
69   // End should be called at least once on navigating to a new URL.
70   std::unique_ptr<MockColorChooser> mock_color_chooser =
71       std::make_unique<MockColorChooser>();
72   EXPECT_CALL(*mock_color_chooser.get(), End()).Times(testing::AtLeast(1));
73 
74   // Set OpenColorChooserDelegate as the new WebContentsDelegate.
75   std::unique_ptr<OpenColorChooserDelegate> delegate =
76       std::make_unique<OpenColorChooserDelegate>(std::move(mock_color_chooser));
77   contents()->SetDelegate(delegate.get());
78 
79   mojo::PendingRemote<blink::mojom::ColorChooserClient> pending_client;
80   mojo::Remote<blink::mojom::ColorChooser> pending_remote;
81   mojo::PendingReceiver<blink::mojom::ColorChooser> pending_receiver =
82       pending_remote.BindNewPipeAndPassReceiver();
83 
84   // Call WebContentsImpl::OpenColorChooser.
85   static_cast<WebContentsImpl*>(contents())
86       ->OpenColorChooser(std::move(pending_receiver), std::move(pending_client),
87                          SkColorSetRGB(0, 0, 1), {});
88 
89   // Navigate to B.
90   NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl2);
91 
92   contents()->SetDelegate(nullptr);
93 }
94 
95 // Run tests with BackForwardCache.
96 class ColorChooserTestWithBackForwardCache : public ColorChooserUnitTest {
97  public:
ColorChooserTestWithBackForwardCache()98   ColorChooserTestWithBackForwardCache() {
99     scoped_feature_list_.InitWithFeaturesAndParameters(
100         {{features::kBackForwardCache, {GetFeatureParams()}}},
101         /*disabled_features=*/{});
102   }
103 
104  protected:
GetFeatureParams()105   base::FieldTrialParams GetFeatureParams() {
106     return {{"TimeToLiveInBackForwardCacheInSeconds", "3600"},
107             {"service_worker_supported", "true"}};
108   }
109 
110  private:
111   base::test::ScopedFeatureList scoped_feature_list_;
112 };
113 
TEST_F(ColorChooserTestWithBackForwardCache,ColorChooserCallsEndOnEnteringBackForwardCache)114 TEST_F(ColorChooserTestWithBackForwardCache,
115        ColorChooserCallsEndOnEnteringBackForwardCache) {
116   ASSERT_TRUE(IsBackForwardCacheEnabled());
117   GURL kUrl1("https://foo.com");
118   GURL kUrl2("https://bar.com");
119 
120   // Navigate to A.
121   NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1);
122   RenderFrameHost* rfh_a = contents()->GetMainFrame();
123 
124   // End should be called at least once on navigating to a new URL.
125   std::unique_ptr<MockColorChooser> mock_color_chooser =
126       std::make_unique<MockColorChooser>();
127   EXPECT_CALL(*mock_color_chooser.get(), End()).Times(testing::AtLeast(1));
128 
129   // Set OpenColorChooserDelegate as the new WebContentsDelegate.
130   std::unique_ptr<OpenColorChooserDelegate> delegate =
131       std::make_unique<OpenColorChooserDelegate>(std::move(mock_color_chooser));
132   contents()->SetDelegate(delegate.get());
133 
134   mojo::PendingRemote<blink::mojom::ColorChooserClient> pending_client;
135   mojo::Remote<blink::mojom::ColorChooser> pending_remote;
136   mojo::PendingReceiver<blink::mojom::ColorChooser> pending_receiver =
137       pending_remote.BindNewPipeAndPassReceiver();
138 
139   // Call WebContentsImpl::OpenColorChooser.
140   static_cast<WebContentsImpl*>(contents())
141       ->OpenColorChooser(std::move(pending_receiver), std::move(pending_client),
142                          SkColorSetRGB(0, 0, 1), {});
143 
144   // Navigate to B, A enters BackForwardCache.
145   NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl2);
146   EXPECT_TRUE(rfh_a->IsInBackForwardCache());
147 
148   contents()->SetDelegate(nullptr);
149 }
150 
151 }  // namespace content
152