1 // Copyright 2019 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/files/file_util.h"
6 #include "base/test/simple_test_clock.h"
7 #include "base/threading/thread_restrictions.h"
8 #include "chrome/browser/infobars/infobar_service.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/test/base/in_process_browser_test.h"
13 #include "chrome/test/base/ui_test_utils.h"
14 #include "components/infobars/core/confirm_infobar_delegate.h"
15 #include "components/infobars/core/infobar.h"
16 #include "content/public/browser/network_service_instance.h"
17 #include "content/public/test/browser_test.h"
18 #include "content/public/test/browser_test_utils.h"
19 #include "net/cert/crl_set.h"
20 #include "net/test/embedded_test_server/embedded_test_server.h"
21 #include "net/test/test_data_directory.h"
22 #include "ui/base/window_open_disposition.h"
23
24 namespace {
25
GetInfobarCount(content::WebContents * contents)26 size_t GetInfobarCount(content::WebContents* contents) {
27 InfoBarService* infobar_service = InfoBarService::FromWebContents(contents);
28 if (!infobar_service)
29 return 0;
30 return infobar_service->infobar_count();
31 }
32
GetInfobar(content::WebContents * contents)33 infobars::InfoBar* GetInfobar(content::WebContents* contents) {
34 InfoBarService* infobar_service = InfoBarService::FromWebContents(contents);
35 DCHECK(infobar_service);
36 return infobar_service->infobar_at(0);
37 }
38
39 // Follows same logic as clicking the "Continue" button would.
CloseInfobar(content::WebContents * contents)40 void CloseInfobar(content::WebContents* contents) {
41 infobars::InfoBar* infobar = GetInfobar(contents);
42 if (!infobar)
43 return;
44
45 ConfirmInfoBarDelegate* delegate =
46 static_cast<ConfirmInfoBarDelegate*>(infobar->delegate());
47 delegate->Accept();
48 infobar->RemoveSelf();
49 }
50
51 } // namespace
52
53 class KnownInterceptionDisclosureInfobarTest : public InProcessBrowserTest {
54 public:
KnownInterceptionDisclosureInfobarTest()55 KnownInterceptionDisclosureInfobarTest()
56 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
57 https_server_.AddDefaultHandlers(GetChromeTestDataDir());
58 }
59
60 KnownInterceptionDisclosureInfobarTest(
61 const KnownInterceptionDisclosureInfobarTest&) = delete;
62 KnownInterceptionDisclosureInfobarTest& operator=(
63 const KnownInterceptionDisclosureInfobarTest&) = delete;
64
SetUpOnMainThread()65 void SetUpOnMainThread() override {
66 ASSERT_TRUE(https_server_.Start());
67
68 // Load a CRLSet that marks the root as a known MITM.
69 std::string crl_set_bytes;
70 {
71 base::ScopedAllowBlockingForTesting allow_blocking;
72 base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
73 "crlset_known_interception_by_root.raw"),
74 &crl_set_bytes);
75 }
76 network::mojom::NetworkService* network_service =
77 content::GetNetworkService();
78 DCHECK(network_service);
79 base::RunLoop run_loop;
80 network_service->UpdateCRLSet(
81 base::as_bytes(base::make_span(crl_set_bytes)), run_loop.QuitClosure());
82 run_loop.Run();
83 }
84
85 protected:
86 net::EmbeddedTestServer https_server_;
87 };
88
IN_PROC_BROWSER_TEST_F(KnownInterceptionDisclosureInfobarTest,OnlyShowDisclosureOncePerSession)89 IN_PROC_BROWSER_TEST_F(KnownInterceptionDisclosureInfobarTest,
90 OnlyShowDisclosureOncePerSession) {
91 const GURL kInterceptedUrl(https_server_.GetURL("/ssl/google.html"));
92
93 TabStripModel* tab_strip_model = browser()->tab_strip_model();
94 content::WebContents* tab1 = tab_strip_model->GetActiveWebContents();
95
96 auto* clock = new base::SimpleTestClock();
97 clock->SetNow(base::Time::Now());
98 KnownInterceptionDisclosureCooldown::GetInstance()->SetClockForTesting(
99 std::unique_ptr<base::Clock>(clock));
100
101 // Trigger the disclosure infobar by navigating to a page served by a root
102 // marked as known interception.
103 ui_test_utils::NavigateToURL(browser(), kInterceptedUrl);
104 EXPECT_EQ(1u, GetInfobarCount(tab1));
105
106 // Test that the infobar is shown on new tabs after it has been triggered
107 // once.
108 ui_test_utils::NavigateToURLWithDisposition(
109 browser(), GURL("about:blank"), WindowOpenDisposition::NEW_FOREGROUND_TAB,
110 ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
111 content::WebContents* tab2 = tab_strip_model->GetActiveWebContents();
112 EXPECT_EQ(1u, GetInfobarCount(tab2));
113
114 // Close the new tab.
115 tab_strip_model->CloseWebContentsAt(tab_strip_model->active_index(),
116 TabStripModel::CLOSE_USER_GESTURE);
117
118 // Reload the first page -- infobar should still show.
119 ui_test_utils::NavigateToURL(browser(), kInterceptedUrl);
120 EXPECT_EQ(1u, GetInfobarCount(tab1));
121
122 // Dismiss the infobar.
123 CloseInfobar(tab1);
124 EXPECT_EQ(0u, GetInfobarCount(tab1));
125
126 // Try to trigger again by reloading the page -- infobar should not show.
127 ui_test_utils::NavigateToURL(browser(), kInterceptedUrl);
128 EXPECT_EQ(0u, GetInfobarCount(tab1));
129
130 // Move clock ahead 8 days.
131 clock->Advance(base::TimeDelta::FromDays(8));
132
133 // Trigger the infobar again -- infobar should show again.
134 ui_test_utils::NavigateToURL(browser(), kInterceptedUrl);
135 EXPECT_EQ(1u, GetInfobarCount(tab1));
136 }
137
IN_PROC_BROWSER_TEST_F(KnownInterceptionDisclosureInfobarTest,PRE_CooldownResetsOnBrowserRestartDesktop)138 IN_PROC_BROWSER_TEST_F(KnownInterceptionDisclosureInfobarTest,
139 PRE_CooldownResetsOnBrowserRestartDesktop) {
140 const GURL kInterceptedUrl(https_server_.GetURL("/ssl/google.html"));
141
142 // Trigger the disclosure infobar.
143 content::WebContents* tab =
144 browser()->tab_strip_model()->GetActiveWebContents();
145 ui_test_utils::NavigateToURL(browser(), kInterceptedUrl);
146 EXPECT_EQ(1u, GetInfobarCount(tab));
147
148 // Dismiss the infobar.
149 CloseInfobar(tab);
150 EXPECT_EQ(0u, GetInfobarCount(tab));
151 }
152
IN_PROC_BROWSER_TEST_F(KnownInterceptionDisclosureInfobarTest,CooldownResetsOnBrowserRestartDesktop)153 IN_PROC_BROWSER_TEST_F(KnownInterceptionDisclosureInfobarTest,
154 CooldownResetsOnBrowserRestartDesktop) {
155 const GURL kInterceptedUrl(https_server_.GetURL("/ssl/google.html"));
156
157 // On restart, no infobar should be shown initially.
158 content::WebContents* tab =
159 browser()->tab_strip_model()->GetActiveWebContents();
160 EXPECT_EQ(0u, GetInfobarCount(tab));
161
162 // Triggering the disclosure infobar again after browser restart should show
163 // the infobar (the cooldown period should no longer apply on Desktop).
164 ui_test_utils::NavigateToURL(browser(), kInterceptedUrl);
165 EXPECT_EQ(1u, GetInfobarCount(tab));
166 }
167