supervised_user_browsertest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/prefs/pref_service.h"
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/values.h"
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h"
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/browser/common/cancelable_request.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_constants.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_interstitial.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/supervised_user/supervised_user_service.h"
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/ui/browser.h"
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/common/pref_names.h"
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/infobars/core/confirm_infobar_delegate.h"
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/infobars/core/infobar.h"
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/interstitial_page.h"
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/notification_service.h"
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/web_contents.h"
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "grit/generated_resources.h"
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::InterstitialPage;
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::NavigationController;
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::NavigationEntry;
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using content::WebContents;
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
48namespace {
49
50// Tests the filter mode in which all sites are blocked by default.
51class 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
59  SupervisedUserBlockModeTest() : supervised_user_service_(NULL) {}
60  virtual ~SupervisedUserBlockModeTest() {}
61
62  void CheckShownPageIsInterstitial(WebContents* tab) {
63    CheckShownPage(tab, content::PAGE_TYPE_INTERSTITIAL);
64  }
65
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|.
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
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
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:
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
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.
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
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
163class MockTabStripModelObserver : public TabStripModelObserver {
164 public:
165  explicit MockTabStripModelObserver(TabStripModel* tab_strip)
166      : tab_strip_(tab_strip) {
167    tab_strip_->AddObserver(this);
168  }
169
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.
181IN_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.
204IN_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.
228IN_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
286IN_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