• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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/common/cancelable_request.h"
11 #include "chrome/browser/history/history_service_factory.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/supervised_user/supervised_user_constants.h"
15 #include "chrome/browser/supervised_user/supervised_user_interstitial.h"
16 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
17 #include "chrome/browser/supervised_user/supervised_user_service.h"
18 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
19 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
20 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_navigator.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/test/base/in_process_browser_test.h"
28 #include "chrome/test/base/ui_test_utils.h"
29 #include "components/infobars/core/confirm_infobar_delegate.h"
30 #include "components/infobars/core/infobar.h"
31 #include "components/pref_registry/pref_registry_syncable.h"
32 #include "content/public/browser/interstitial_page.h"
33 #include "content/public/browser/navigation_controller.h"
34 #include "content/public/browser/navigation_entry.h"
35 #include "content/public/browser/notification_service.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_observer.h"
38 #include "content/public/test/browser_test_utils.h"
39 #include "grit/generated_resources.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "ui/base/l10n/l10n_util.h"
42 
43 using content::InterstitialPage;
44 using content::NavigationController;
45 using content::NavigationEntry;
46 using content::WebContents;
47 
48 namespace {
49 
50 // Tests the filter mode in which all sites are blocked by default.
51 class SupervisedUserBlockModeTest : public InProcessBrowserTest {
52  public:
53   // Indicates whether the interstitial should proceed or not.
54   enum InterstitialAction {
55     INTERSTITIAL_PROCEED,
56     INTERSTITIAL_DONTPROCEED,
57   };
58 
SupervisedUserBlockModeTest()59   SupervisedUserBlockModeTest() : supervised_user_service_(NULL) {}
~SupervisedUserBlockModeTest()60   virtual ~SupervisedUserBlockModeTest() {}
61 
CheckShownPageIsInterstitial(WebContents * tab)62   void CheckShownPageIsInterstitial(WebContents* tab) {
63     CheckShownPage(tab, content::PAGE_TYPE_INTERSTITIAL);
64   }
65 
CheckShownPageIsNotInterstitial(WebContents * tab)66   void CheckShownPageIsNotInterstitial(WebContents* tab) {
67     CheckShownPage(tab, content::PAGE_TYPE_NORMAL);
68   }
69 
70   // Checks to see if the type of the current page is |page_type|.
CheckShownPage(WebContents * tab,content::PageType page_type)71   void CheckShownPage(WebContents* tab, content::PageType page_type) {
72     ASSERT_FALSE(tab->IsCrashed());
73     NavigationEntry* entry = tab->GetController().GetActiveEntry();
74     ASSERT_TRUE(entry);
75     ASSERT_EQ(page_type, entry->GetPageType());
76   }
77 
SendAccessRequest(WebContents * tab)78   void SendAccessRequest(WebContents* tab) {
79     InterstitialPage* interstitial_page = tab->GetInterstitialPage();
80     ASSERT_TRUE(interstitial_page);
81 
82     // Get the SupervisedUserInterstitial delegate.
83     content::InterstitialPageDelegate* delegate =
84         interstitial_page->GetDelegateForTesting();
85 
86     // Simulate the click on the "request" button.
87     delegate->CommandReceived("\"request\"");
88   }
89 
GoBack(WebContents * tab)90   void GoBack(WebContents* tab) {
91     InterstitialPage* interstitial_page = tab->GetInterstitialPage();
92     ASSERT_TRUE(interstitial_page);
93 
94     // Get the SupervisedUserInterstitial delegate.
95     content::InterstitialPageDelegate* delegate =
96         interstitial_page->GetDelegateForTesting();
97 
98     // Simulate the click on the "back" button.
99     delegate->CommandReceived("\"back\"");
100   }
101 
102  protected:
SetUpOnMainThread()103   virtual void SetUpOnMainThread() OVERRIDE {
104     // Set up the SupervisedUserNavigationObserver manually since the profile
105     // was not supervised when the browser was created.
106     content::WebContents* web_contents =
107         browser()->tab_strip_model()->GetActiveWebContents();
108     SupervisedUserNavigationObserver::CreateForWebContents(web_contents);
109 
110     Profile* profile = browser()->profile();
111     supervised_user_service_ =
112         SupervisedUserServiceFactory::GetForProfile(profile);
113     SupervisedUserSettingsService* supervised_user_settings_service =
114         SupervisedUserSettingsServiceFactory::GetForProfile(profile);
115     supervised_user_settings_service->SetLocalSettingForTesting(
116         supervised_users::kContentPackDefaultFilteringBehavior,
117         scoped_ptr<base::Value>(
118             new base::FundamentalValue(SupervisedUserURLFilter::BLOCK)));
119   }
120 
SetUpCommandLine(CommandLine * command_line)121   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
122     // Enable the test server and remap all URLs to it.
123     ASSERT_TRUE(test_server()->Start());
124     std::string host_port = test_server()->host_port_pair().ToString();
125     command_line->AppendSwitchASCII(switches::kHostResolverRules,
126         "MAP *.example.com " + host_port + "," +
127         "MAP *.new-example.com " + host_port + "," +
128         "MAP *.a.com " + host_port);
129 
130     command_line->AppendSwitchASCII(switches::kSupervisedUserId, "asdf");
131   }
132 
133   // Acts like a synchronous call to history's QueryHistory. Modified from
134   // history_querying_unittest.cc.
QueryHistory(HistoryService * history_service,const std::string & text_query,const history::QueryOptions & options,history::QueryResults * results)135   void QueryHistory(HistoryService* history_service,
136                     const std::string& text_query,
137                     const history::QueryOptions& options,
138                     history::QueryResults* results) {
139     CancelableRequestConsumer history_request_consumer;
140     base::RunLoop run_loop;
141     history_service->QueryHistory(
142         base::UTF8ToUTF16(text_query),
143         options,
144         &history_request_consumer,
145         base::Bind(&SupervisedUserBlockModeTest::QueryHistoryComplete,
146                    base::Unretained(this),
147                    results,
148                    &run_loop));
149     run_loop.Run();  // Will go until ...Complete calls Quit.
150   }
151 
QueryHistoryComplete(history::QueryResults * new_results,base::RunLoop * run_loop,HistoryService::Handle,history::QueryResults * results)152   void QueryHistoryComplete(history::QueryResults* new_results,
153                             base::RunLoop* run_loop,
154                             HistoryService::Handle /* handle */,
155                             history::QueryResults* results) {
156     results->Swap(new_results);
157     run_loop->Quit();  // Will return out to QueryHistory.
158   }
159 
160   SupervisedUserService* supervised_user_service_;
161 };
162 
163 class MockTabStripModelObserver : public TabStripModelObserver {
164  public:
MockTabStripModelObserver(TabStripModel * tab_strip)165   explicit MockTabStripModelObserver(TabStripModel* tab_strip)
166       : tab_strip_(tab_strip) {
167     tab_strip_->AddObserver(this);
168   }
169 
~MockTabStripModelObserver()170   ~MockTabStripModelObserver() {
171     tab_strip_->RemoveObserver(this);
172   }
173 
174   MOCK_METHOD3(TabClosingAt, void(TabStripModel*, content::WebContents*, int));
175 
176  private:
177   TabStripModel* tab_strip_;
178 };
179 
180 // Navigates to a blocked URL.
IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest,SendAccessRequestOnBlockedURL)181 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest,
182                        SendAccessRequestOnBlockedURL) {
183   GURL test_url("http://www.example.com/files/simple.html");
184   ui_test_utils::NavigateToURL(browser(), test_url);
185 
186   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
187 
188   CheckShownPageIsInterstitial(tab);
189 
190   SendAccessRequest(tab);
191 
192   // TODO(sergiu): Properly check that the access request was sent here.
193 
194   GoBack(tab);
195 
196   // Make sure that the tab is still there.
197   EXPECT_EQ(tab, browser()->tab_strip_model()->GetActiveWebContents());
198 
199   CheckShownPageIsNotInterstitial(tab);
200 }
201 
202 // Navigates to a blocked URL in a new tab. We expect the tab to be closed
203 // automatically on pressing the "back" button on the interstitial.
IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest,OpenBlockedURLInNewTab)204 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest, OpenBlockedURLInNewTab) {
205   TabStripModel* tab_strip = browser()->tab_strip_model();
206   WebContents* prev_tab = tab_strip->GetActiveWebContents();
207 
208   // Open blocked URL in a new tab.
209   GURL test_url("http://www.example.com/files/simple.html");
210   ui_test_utils::NavigateToURLWithDisposition(
211       browser(), test_url, NEW_FOREGROUND_TAB,
212       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
213 
214   // Check that we got the interstitial.
215   WebContents* tab = tab_strip->GetActiveWebContents();
216   CheckShownPageIsInterstitial(tab);
217 
218   // On pressing the "back" button, the new tab should be closed, and we should
219   // get back to the previous active tab.
220   MockTabStripModelObserver observer(tab_strip);
221   EXPECT_CALL(observer,
222               TabClosingAt(tab_strip, tab, tab_strip->active_index()));
223   GoBack(tab);
224   EXPECT_EQ(prev_tab, tab_strip->GetActiveWebContents());
225 }
226 
227 // Tests whether a visit attempt adds a special history entry.
IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest,HistoryVisitRecorded)228 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest,
229                        HistoryVisitRecorded) {
230   GURL allowed_url("http://www.example.com/files/simple.html");
231 
232   // Set the host as allowed.
233   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
234   dict->SetBooleanWithoutPathExpansion(allowed_url.host(), true);
235   SupervisedUserSettingsService* supervised_user_settings_service =
236       SupervisedUserSettingsServiceFactory::GetForProfile(
237           browser()->profile());
238   supervised_user_settings_service->SetLocalSettingForTesting(
239       supervised_users::kContentPackManualBehaviorHosts,
240       dict.PassAs<base::Value>());
241   EXPECT_EQ(
242       SupervisedUserService::MANUAL_ALLOW,
243       supervised_user_service_->GetManualBehaviorForHost(allowed_url.host()));
244 
245   ui_test_utils::NavigateToURL(browser(), allowed_url);
246 
247   // Navigate to it and check that we don't get an interstitial.
248   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
249   CheckShownPageIsNotInterstitial(tab);
250 
251   // Navigate to a blocked page and go back on the interstitial.
252   GURL blocked_url("http://www.new-example.com/files/simple.html");
253   ui_test_utils::NavigateToURL(browser(), blocked_url);
254 
255   tab = browser()->tab_strip_model()->GetActiveWebContents();
256 
257   CheckShownPageIsInterstitial(tab);
258   GoBack(tab);
259 
260   // Check that we went back to the first URL and that the manual behaviors
261   // have not changed.
262   EXPECT_EQ(allowed_url.spec(), tab->GetURL().spec());
263   EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW,
264             supervised_user_service_->GetManualBehaviorForHost(
265                 "www.example.com"));
266   EXPECT_EQ(
267       SupervisedUserService::MANUAL_NONE,
268       supervised_user_service_->GetManualBehaviorForHost(
269           "www.new-example.com"));
270 
271   // Query the history entry.
272   HistoryService* history_service = HistoryServiceFactory::GetForProfile(
273       browser()->profile(), Profile::EXPLICIT_ACCESS);
274   history::QueryOptions options;
275   history::QueryResults results;
276   QueryHistory(history_service, "", options, &results);
277 
278   // Check that the entries have the correct blocked_visit value.
279   ASSERT_EQ(2u, results.size());
280   EXPECT_EQ(blocked_url.spec(), results[0].url().spec());
281   EXPECT_TRUE(results[0].blocked_visit());
282   EXPECT_EQ(allowed_url.spec(), results[1].url().spec());
283   EXPECT_FALSE(results[1].blocked_visit());
284 }
285 
IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest,Unblock)286 IN_PROC_BROWSER_TEST_F(SupervisedUserBlockModeTest, Unblock) {
287   GURL test_url("http://www.example.com/files/simple.html");
288   ui_test_utils::NavigateToURL(browser(), test_url);
289 
290   WebContents* web_contents =
291       browser()->tab_strip_model()->GetActiveWebContents();
292 
293   CheckShownPageIsInterstitial(web_contents);
294 
295   content::WindowedNotificationObserver observer(
296       content::NOTIFICATION_LOAD_STOP,
297       content::NotificationService::AllSources());
298 
299   // Set the host as allowed.
300   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
301   dict->SetBooleanWithoutPathExpansion(test_url.host(), true);
302   SupervisedUserSettingsService* supervised_user_settings_service =
303       SupervisedUserSettingsServiceFactory::GetForProfile(
304           browser()->profile());
305   supervised_user_settings_service->SetLocalSettingForTesting(
306       supervised_users::kContentPackManualBehaviorHosts,
307       dict.PassAs<base::Value>());
308   EXPECT_EQ(
309       SupervisedUserService::MANUAL_ALLOW,
310       supervised_user_service_->GetManualBehaviorForHost(test_url.host()));
311 
312   observer.Wait();
313   EXPECT_EQ(test_url, web_contents->GetURL());
314 }
315 
316 }  // namespace
317