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 "components/subresource_filter/content/browser/navigation_console_logger.h"
6 
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/stl_util.h"
10 #include "content/public/browser/navigation_handle.h"
11 #include "content/public/browser/web_contents_observer.h"
12 #include "content/public/test/navigation_simulator.h"
13 #include "content/public/test/test_renderer_host.h"
14 #include "net/base/net_errors.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace subresource_filter {
18 
19 namespace {
20 
GetConsoleMessages(content::RenderFrameHost * rfh)21 const std::vector<std::string>& GetConsoleMessages(
22     content::RenderFrameHost* rfh) {
23   return content::RenderFrameHostTester::For(rfh)->GetConsoleMessages();
24 }
25 
26 }  // namespace
27 
28 using NavigationConsoleLoggerTest = content::RenderViewHostTestHarness;
29 
30 using NavigationCallback =
31     base::RepeatingCallback<void(content::NavigationHandle*)>;
32 class NavigationFinishCaller : public content::WebContentsObserver {
33  public:
NavigationFinishCaller(content::WebContents * contents,const NavigationCallback & callback)34   NavigationFinishCaller(content::WebContents* contents,
35                          const NavigationCallback& callback)
36       : content::WebContentsObserver(contents), callback_(callback) {}
37   ~NavigationFinishCaller() override = default;
38 
39   // content::WebContentsObserver:
DidFinishNavigation(content::NavigationHandle * handle)40   void DidFinishNavigation(content::NavigationHandle* handle) override {
41     callback_.Run(handle);
42   }
43 
44  private:
45   NavigationCallback callback_;
46 };
47 
TEST_F(NavigationConsoleLoggerTest,NavigationFails_NoLog)48 TEST_F(NavigationConsoleLoggerTest, NavigationFails_NoLog) {
49   auto navigation = content::NavigationSimulator::CreateRendererInitiated(
50       GURL("http://example.test/"), main_rfh());
51   navigation->Start();
52   NavigationConsoleLogger::LogMessageOnCommit(
53       navigation->GetNavigationHandle(),
54       blink::mojom::ConsoleMessageLevel::kWarning, "foo");
55   navigation->Fail(net::ERR_ABORTED);
56 
57   EXPECT_TRUE(GetConsoleMessages(main_rfh()).empty());
58 }
59 
TEST_F(NavigationConsoleLoggerTest,NavigationCommitsToErrorPage_NoLog)60 TEST_F(NavigationConsoleLoggerTest, NavigationCommitsToErrorPage_NoLog) {
61   auto navigation = content::NavigationSimulator::CreateRendererInitiated(
62       GURL("http://example.test/"), main_rfh());
63   navigation->Start();
64   NavigationConsoleLogger::LogMessageOnCommit(
65       navigation->GetNavigationHandle(),
66       blink::mojom::ConsoleMessageLevel::kWarning, "foo");
67   navigation->Fail(net::ERR_TIMED_OUT);
68 
69   EXPECT_TRUE(GetConsoleMessages(main_rfh()).empty());
70 }
71 
TEST_F(NavigationConsoleLoggerTest,NavigationCommitsSuccessfully_Logs)72 TEST_F(NavigationConsoleLoggerTest, NavigationCommitsSuccessfully_Logs) {
73   auto navigation = content::NavigationSimulator::CreateRendererInitiated(
74       GURL("http://example.test/"), main_rfh());
75   navigation->Start();
76   NavigationConsoleLogger::LogMessageOnCommit(
77       navigation->GetNavigationHandle(),
78       blink::mojom::ConsoleMessageLevel::kWarning, "foo");
79 
80   EXPECT_TRUE(GetConsoleMessages(main_rfh()).empty());
81   navigation->Commit();
82 
83   EXPECT_TRUE(base::Contains(GetConsoleMessages(main_rfh()), "foo"));
84 }
85 
TEST_F(NavigationConsoleLoggerTest,NavigationAlreadyCommit_Logs)86 TEST_F(NavigationConsoleLoggerTest, NavigationAlreadyCommit_Logs) {
87   auto on_finish = [](content::NavigationHandle* handle) {
88     NavigationConsoleLogger::LogMessageOnCommit(
89         handle, blink::mojom::ConsoleMessageLevel::kWarning, "foo");
90   };
91   NavigationFinishCaller caller(web_contents(), base::BindRepeating(on_finish));
92   NavigateAndCommit(GURL("http://example.test/"));
93   EXPECT_TRUE(base::Contains(GetConsoleMessages(main_rfh()), "foo"));
94 }
95 
TEST_F(NavigationConsoleLoggerTest,NavigationAlreadyFailed_NoLog)96 TEST_F(NavigationConsoleLoggerTest, NavigationAlreadyFailed_NoLog) {
97   auto on_finish = [](content::NavigationHandle* handle) {
98     NavigationConsoleLogger::LogMessageOnCommit(
99         handle, blink::mojom::ConsoleMessageLevel::kWarning, "foo");
100   };
101   NavigationFinishCaller caller(web_contents(), base::BindRepeating(on_finish));
102   content::NavigationSimulator::NavigateAndFailFromBrowser(
103       web_contents(), GURL("http://example.test/"), net::ERR_TIMED_OUT);
104   EXPECT_TRUE(GetConsoleMessages(main_rfh()).empty());
105 }
106 
TEST_F(NavigationConsoleLoggerTest,MultipleNavigations_OneLog)107 TEST_F(NavigationConsoleLoggerTest, MultipleNavigations_OneLog) {
108   {
109     auto navigation = content::NavigationSimulator::CreateRendererInitiated(
110         GURL("http://example.test/"), main_rfh());
111     navigation->Start();
112     NavigationConsoleLogger::LogMessageOnCommit(
113         navigation->GetNavigationHandle(),
114         blink::mojom::ConsoleMessageLevel::kWarning, "foo");
115     navigation->Commit();
116   }
117   NavigateAndCommit(GURL("http://example.test/"));
118   EXPECT_EQ(1u, GetConsoleMessages(main_rfh()).size());
119 }
120 
TEST_F(NavigationConsoleLoggerTest,MultipleMessages)121 TEST_F(NavigationConsoleLoggerTest, MultipleMessages) {
122   auto navigation = content::NavigationSimulator::CreateRendererInitiated(
123       GURL("http://example.test/"), main_rfh());
124   navigation->Start();
125   NavigationConsoleLogger::LogMessageOnCommit(
126       navigation->GetNavigationHandle(),
127       blink::mojom::ConsoleMessageLevel::kWarning, "foo");
128   NavigationConsoleLogger::LogMessageOnCommit(
129       navigation->GetNavigationHandle(),
130       blink::mojom::ConsoleMessageLevel::kWarning, "bar");
131 
132   EXPECT_TRUE(GetConsoleMessages(main_rfh()).empty());
133   navigation->Commit();
134 
135   EXPECT_EQ(2u, GetConsoleMessages(main_rfh()).size());
136 }
137 
TEST_F(NavigationConsoleLoggerTest,SyncNavigationDuringNavigation)138 TEST_F(NavigationConsoleLoggerTest, SyncNavigationDuringNavigation) {
139   NavigateAndCommit(GURL("http://example.test/"));
140 
141   auto navigation = content::NavigationSimulator::CreateRendererInitiated(
142       GURL("http://example.test/path"), main_rfh());
143   navigation->Start();
144   NavigationConsoleLogger::LogMessageOnCommit(
145       navigation->GetNavigationHandle(),
146       blink::mojom::ConsoleMessageLevel::kWarning, "foo");
147 
148   content::NavigationSimulator::CreateRendererInitiated(
149       GURL("http://example.test/#hash"), main_rfh())
150       ->CommitSameDocument();
151   EXPECT_EQ(0u, GetConsoleMessages(main_rfh()).size());
152 
153   navigation->Commit();
154   EXPECT_EQ(1u, GetConsoleMessages(main_rfh()).size());
155 }
156 
157 }  // namespace subresource_filter
158