1 // Copyright 2014 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.
5 #include "base/command_line.h"
6 #include "base/prefs/pref_service.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/values.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/history/history_service_factory.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/supervised_user/supervised_user_constants.h"
14 #include "chrome/browser/supervised_user/supervised_user_interstitial.h"
15 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
16 #include "chrome/browser/supervised_user/supervised_user_service.h"
17 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
18 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
19 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_navigator.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "components/infobars/core/confirm_infobar_delegate.h"
28 #include "components/infobars/core/infobar.h"
29 #include "components/pref_registry/pref_registry_syncable.h"
30 #include "content/public/browser/interstitial_page.h"
31 #include "content/public/browser/navigation_controller.h"
32 #include "content/public/browser/navigation_entry.h"
33 #include "content/public/browser/notification_service.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/browser/web_contents_observer.h"
36 #include "content/public/test/browser_test_utils.h"
37 #include "testing/gmock/include/gmock/gmock.h"
39 using content::InterstitialPage
;
40 using content::NavigationController
;
41 using content::NavigationEntry
;
42 using content::WebContents
;
46 // Tests the filter mode in which all sites are blocked by default.
47 class SupervisedUserBlockModeTest
: public InProcessBrowserTest
{
49 // Indicates whether the interstitial should proceed or not.
50 enum InterstitialAction
{
52 INTERSTITIAL_DONTPROCEED
,
55 SupervisedUserBlockModeTest() : supervised_user_service_(NULL
) {}
56 ~SupervisedUserBlockModeTest() override
{}
58 void CheckShownPageIsInterstitial(WebContents
* tab
) {
59 CheckShownPage(tab
, content::PAGE_TYPE_INTERSTITIAL
);
62 void CheckShownPageIsNotInterstitial(WebContents
* tab
) {
63 CheckShownPage(tab
, content::PAGE_TYPE_NORMAL
);
66 // Checks to see if the type of the current page is |page_type|.
67 void CheckShownPage(WebContents
* tab
, content::PageType page_type
) {
68 ASSERT_FALSE(tab
->IsCrashed());
69 NavigationEntry
* entry
= tab
->GetController().GetActiveEntry();
71 ASSERT_EQ(page_type
, entry
->GetPageType());
74 void SendAccessRequest(WebContents
* tab
) {
75 InterstitialPage
* interstitial_page
= tab
->GetInterstitialPage();
76 ASSERT_TRUE(interstitial_page
);
78 // Get the SupervisedUserInterstitial delegate.
79 content::InterstitialPageDelegate
* delegate
=
80 interstitial_page
->GetDelegateForTesting();
82 // Simulate the click on the "request" button.
83 delegate
->CommandReceived("\"request\"");
86 void GoBack(WebContents
* tab
) {
87 InterstitialPage
* interstitial_page
= tab
->GetInterstitialPage();
88 ASSERT_TRUE(interstitial_page
);
90 // Get the SupervisedUserInterstitial delegate.
91 content::InterstitialPageDelegate
* delegate
=
92 interstitial_page
->GetDelegateForTesting();
94 // Simulate the click on the "back" button.
95 delegate
->CommandReceived("\"back\"");
99 void SetUpOnMainThread() override
{
100 // Set up the SupervisedUserNavigationObserver manually since the profile
101 // was not supervised when the browser was created.
102 content::WebContents
* web_contents
=
103 browser()->tab_strip_model()->GetActiveWebContents();
104 SupervisedUserNavigationObserver::CreateForWebContents(web_contents
);
106 Profile
* profile
= browser()->profile();
107 supervised_user_service_
=
108 SupervisedUserServiceFactory::GetForProfile(profile
);
109 SupervisedUserSettingsService
* supervised_user_settings_service
=
110 SupervisedUserSettingsServiceFactory::GetForProfile(profile
);
111 supervised_user_settings_service
->SetLocalSetting(
112 supervised_users::kContentPackDefaultFilteringBehavior
,
113 scoped_ptr
<base::Value
>(
114 new base::FundamentalValue(SupervisedUserURLFilter::BLOCK
)));
117 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
118 // Enable the test server and remap all URLs to it.
119 ASSERT_TRUE(test_server()->Start());
120 std::string host_port
= test_server()->host_port_pair().ToString();
121 command_line
->AppendSwitchASCII(switches::kHostResolverRules
,
122 "MAP *.example.com " + host_port
+ "," +
123 "MAP *.new-example.com " + host_port
+ "," +
124 "MAP *.a.com " + host_port
);
126 command_line
->AppendSwitchASCII(switches::kSupervisedUserId
, "asdf");
129 // Acts like a synchronous call to history's QueryHistory. Modified from
130 // history_querying_unittest.cc.
131 void QueryHistory(history::HistoryService
* history_service
,
132 const std::string
& text_query
,
133 const history::QueryOptions
& options
,
134 history::QueryResults
* results
) {
135 base::RunLoop run_loop
;
136 base::CancelableTaskTracker history_task_tracker
;
137 history_service
->QueryHistory(
138 base::UTF8ToUTF16(text_query
),
140 base::Bind(&SupervisedUserBlockModeTest::QueryHistoryComplete
,
141 base::Unretained(this),
144 &history_task_tracker
);
145 run_loop
.Run(); // Will go until ...Complete calls Quit.
148 void QueryHistoryComplete(history::QueryResults
* new_results
,
149 base::RunLoop
* run_loop
,
150 history::QueryResults
* results
) {
151 results
->Swap(new_results
);
152 run_loop
->Quit(); // Will return out to QueryHistory.
155 SupervisedUserService
* supervised_user_service_
;
158 class MockTabStripModelObserver
: public TabStripModelObserver
{
160 explicit MockTabStripModelObserver(TabStripModel
* tab_strip
)
161 : tab_strip_(tab_strip
) {
162 tab_strip_
->AddObserver(this);
165 ~MockTabStripModelObserver() {
166 tab_strip_
->RemoveObserver(this);
169 MOCK_METHOD3(TabClosingAt
, void(TabStripModel
*, content::WebContents
*, int));
172 TabStripModel
* tab_strip_
;
175 // Navigates to a blocked URL.
176 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest
,
177 SendAccessRequestOnBlockedURL
) {
178 GURL
test_url("http://www.example.com/files/simple.html");
179 ui_test_utils::NavigateToURL(browser(), test_url
);
181 WebContents
* tab
= browser()->tab_strip_model()->GetActiveWebContents();
183 CheckShownPageIsInterstitial(tab
);
185 SendAccessRequest(tab
);
187 // TODO(sergiu): Properly check that the access request was sent here.
191 // Make sure that the tab is still there.
192 EXPECT_EQ(tab
, browser()->tab_strip_model()->GetActiveWebContents());
194 CheckShownPageIsNotInterstitial(tab
);
197 // Navigates to a blocked URL in a new tab. We expect the tab to be closed
198 // automatically on pressing the "back" button on the interstitial.
199 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest
, OpenBlockedURLInNewTab
) {
200 TabStripModel
* tab_strip
= browser()->tab_strip_model();
201 WebContents
* prev_tab
= tab_strip
->GetActiveWebContents();
203 // Open blocked URL in a new tab.
204 GURL
test_url("http://www.example.com/files/simple.html");
205 ui_test_utils::NavigateToURLWithDisposition(
206 browser(), test_url
, NEW_FOREGROUND_TAB
,
207 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
209 // Check that we got the interstitial.
210 WebContents
* tab
= tab_strip
->GetActiveWebContents();
211 CheckShownPageIsInterstitial(tab
);
213 // On pressing the "back" button, the new tab should be closed, and we should
214 // get back to the previous active tab.
215 MockTabStripModelObserver
observer(tab_strip
);
216 base::RunLoop run_loop
;
217 EXPECT_CALL(observer
,
218 TabClosingAt(tab_strip
, tab
, tab_strip
->active_index()))
219 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
222 EXPECT_EQ(prev_tab
, tab_strip
->GetActiveWebContents());
225 // Tests whether a visit attempt adds a special history entry.
226 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest
,
227 HistoryVisitRecorded
) {
228 GURL
allowed_url("http://www.example.com/files/simple.html");
230 scoped_refptr
<SupervisedUserURLFilter
> filter
=
231 supervised_user_service_
->GetURLFilterForUIThread();
233 // Set the host as allowed.
234 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
235 dict
->SetBooleanWithoutPathExpansion(allowed_url
.host(), true);
236 SupervisedUserSettingsService
* supervised_user_settings_service
=
237 SupervisedUserSettingsServiceFactory::GetForProfile(
238 browser()->profile());
239 supervised_user_settings_service
->SetLocalSetting(
240 supervised_users::kContentPackManualBehaviorHosts
, dict
.Pass());
241 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
242 filter
->GetFilteringBehaviorForURL(allowed_url
));
243 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
244 filter
->GetFilteringBehaviorForURL(allowed_url
.GetWithEmptyPath()));
246 ui_test_utils::NavigateToURL(browser(), allowed_url
);
248 // Navigate to it and check that we don't get an interstitial.
249 WebContents
* tab
= browser()->tab_strip_model()->GetActiveWebContents();
250 CheckShownPageIsNotInterstitial(tab
);
252 // Navigate to a blocked page and go back on the interstitial.
253 GURL
blocked_url("http://www.new-example.com/files/simple.html");
254 ui_test_utils::NavigateToURL(browser(), blocked_url
);
256 tab
= browser()->tab_strip_model()->GetActiveWebContents();
258 CheckShownPageIsInterstitial(tab
);
261 // Check that we went back to the first URL and that the manual behaviors
263 EXPECT_EQ(allowed_url
.spec(), tab
->GetURL().spec());
264 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
265 filter
->GetFilteringBehaviorForURL(allowed_url
.GetWithEmptyPath()));
266 EXPECT_EQ(SupervisedUserURLFilter::BLOCK
,
267 filter
->GetFilteringBehaviorForURL(blocked_url
.GetWithEmptyPath()));
269 // Query the history entry.
270 history::HistoryService
* history_service
=
271 HistoryServiceFactory::GetForProfile(browser()->profile(),
272 ServiceAccessType::EXPLICIT_ACCESS
);
273 history::QueryOptions options
;
274 history::QueryResults results
;
275 QueryHistory(history_service
, "", options
, &results
);
277 // Check that the entries have the correct blocked_visit value.
278 ASSERT_EQ(2u, results
.size());
279 EXPECT_EQ(blocked_url
.spec(), results
[0].url().spec());
280 EXPECT_TRUE(results
[0].blocked_visit());
281 EXPECT_EQ(allowed_url
.spec(), results
[1].url().spec());
282 EXPECT_FALSE(results
[1].blocked_visit());
285 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest
, Unblock
) {
286 GURL
test_url("http://www.example.com/files/simple.html");
287 ui_test_utils::NavigateToURL(browser(), test_url
);
289 WebContents
* web_contents
=
290 browser()->tab_strip_model()->GetActiveWebContents();
292 CheckShownPageIsInterstitial(web_contents
);
294 content::WindowedNotificationObserver
observer(
295 content::NOTIFICATION_LOAD_STOP
,
296 content::NotificationService::AllSources());
298 // Set the host as allowed.
299 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
300 dict
->SetBooleanWithoutPathExpansion(test_url
.host(), true);
301 SupervisedUserSettingsService
* supervised_user_settings_service
=
302 SupervisedUserSettingsServiceFactory::GetForProfile(
303 browser()->profile());
304 supervised_user_settings_service
->SetLocalSetting(
305 supervised_users::kContentPackManualBehaviorHosts
, dict
.Pass());
307 scoped_refptr
<SupervisedUserURLFilter
> filter
=
308 supervised_user_service_
->GetURLFilterForUIThread();
309 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
310 filter
->GetFilteringBehaviorForURL(test_url
.GetWithEmptyPath()));
313 EXPECT_EQ(test_url
, web_contents
->GetURL());