1// Copyright (c) 2012 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 "chrome/browser/net/chrome_network_delegate.h"
6
7#include "base/memory/ref_counted.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop/message_loop.h"
10#include "base/prefs/pref_member.h"
11#include "chrome/browser/content_settings/cookie_settings.h"
12#include "chrome/common/pref_names.h"
13#include "chrome/common/url_constants.h"
14#include "chrome/test/base/testing_pref_service_syncable.h"
15#include "chrome/test/base/testing_profile.h"
16#include "content/public/test/test_browser_thread_bundle.h"
17#include "net/base/completion_callback.h"
18#include "net/base/request_priority.h"
19#include "net/url_request/url_request.h"
20#include "net/url_request/url_request_test_util.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23#if defined(ENABLE_EXTENSIONS)
24#include "chrome/browser/extensions/event_router_forwarder.h"
25#endif
26
27#if defined(ENABLE_EXTENSIONS)
28class ChromeNetworkDelegateTest : public testing::Test {
29 protected:
30  ChromeNetworkDelegateTest()
31      : forwarder_(new extensions::EventRouterForwarder()) {
32  }
33
34  virtual void SetUp() OVERRIDE {
35    never_throttle_requests_original_value_ =
36        ChromeNetworkDelegate::g_never_throttle_requests_;
37    ChromeNetworkDelegate::g_never_throttle_requests_ = false;
38  }
39
40  virtual void TearDown() OVERRIDE {
41    ChromeNetworkDelegate::g_never_throttle_requests_ =
42        never_throttle_requests_original_value_;
43  }
44
45  scoped_ptr<ChromeNetworkDelegate> CreateNetworkDelegate() {
46    return make_scoped_ptr(
47        new ChromeNetworkDelegate(forwarder_.get(), &pref_member_));
48  }
49
50  // Implementation moved here for access to private bits.
51  void NeverThrottleLogicImpl() {
52    scoped_ptr<ChromeNetworkDelegate> delegate(CreateNetworkDelegate());
53
54    net::TestURLRequestContext context;
55    scoped_ptr<net::URLRequest> extension_request(context.CreateRequest(
56        GURL("http://example.com/"), net::DEFAULT_PRIORITY, NULL, NULL));
57    extension_request->set_first_party_for_cookies(
58        GURL("chrome-extension://abcdef/bingo.html"));
59    scoped_ptr<net::URLRequest> web_page_request(context.CreateRequest(
60        GURL("http://example.com/"), net::DEFAULT_PRIORITY, NULL, NULL));
61    web_page_request->set_first_party_for_cookies(
62        GURL("http://example.com/helloworld.html"));
63
64    ASSERT_TRUE(delegate->OnCanThrottleRequest(*extension_request));
65    ASSERT_FALSE(delegate->OnCanThrottleRequest(*web_page_request));
66
67    delegate->NeverThrottleRequests();
68    ASSERT_TRUE(ChromeNetworkDelegate::g_never_throttle_requests_);
69    ASSERT_FALSE(delegate->OnCanThrottleRequest(*extension_request));
70    ASSERT_FALSE(delegate->OnCanThrottleRequest(*web_page_request));
71
72    // Verify that the flag applies to later instances of the
73    // ChromeNetworkDelegate.
74    //
75    // We test the side effects of the flag rather than just the flag
76    // itself (which we did above) to help ensure that a changed
77    // implementation would show the same behavior, i.e. all instances
78    // of ChromeNetworkDelegate after the flag is set obey the flag.
79    scoped_ptr<ChromeNetworkDelegate> second_delegate(CreateNetworkDelegate());
80    ASSERT_FALSE(delegate->OnCanThrottleRequest(*extension_request));
81    ASSERT_FALSE(delegate->OnCanThrottleRequest(*web_page_request));
82  }
83
84 private:
85  bool never_throttle_requests_original_value_;
86  base::MessageLoopForIO message_loop_;
87
88  scoped_refptr<extensions::EventRouterForwarder> forwarder_;
89  BooleanPrefMember pref_member_;
90};
91
92TEST_F(ChromeNetworkDelegateTest, NeverThrottleLogic) {
93  NeverThrottleLogicImpl();
94}
95#endif  // defined(ENABLE_EXTENSIONS)
96
97class ChromeNetworkDelegateSafeSearchTest : public testing::Test {
98 public:
99  ChromeNetworkDelegateSafeSearchTest()
100      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
101#if defined(ENABLE_EXTENSIONS)
102    forwarder_ = new extensions::EventRouterForwarder();
103#endif
104  }
105
106  virtual void SetUp() OVERRIDE {
107    ChromeNetworkDelegate::InitializePrefsOnUIThread(
108        &enable_referrers_, NULL, &force_google_safe_search_,
109        profile_.GetTestingPrefService());
110  }
111
112 protected:
113  scoped_ptr<net::NetworkDelegate> CreateNetworkDelegate() {
114    scoped_ptr<ChromeNetworkDelegate> network_delegate(
115        new ChromeNetworkDelegate(forwarder(), &enable_referrers_));
116    network_delegate->set_force_google_safe_search(&force_google_safe_search_);
117    return network_delegate.PassAs<net::NetworkDelegate>();
118  }
119
120  void SetSafeSearch(bool value) {
121    force_google_safe_search_.SetValue(value);
122  }
123
124  void SetDelegate(net::NetworkDelegate* delegate) {
125    network_delegate_ = delegate;
126    context_.set_network_delegate(network_delegate_);
127  }
128
129  // Does a request using the |url_string| URL and verifies that the expected
130  // string is equal to the query part (between ? and #) of the final url of
131  // that request.
132  void CheckAddedParameters(const std::string& url_string,
133                            const std::string& expected_query_parameters) {
134    // Show the URL in the trace so we know where we failed.
135    SCOPED_TRACE(url_string);
136
137    scoped_ptr<net::URLRequest> request(context_.CreateRequest(
138        GURL(url_string), net::DEFAULT_PRIORITY, &delegate_, NULL));
139
140    request->Start();
141    base::MessageLoop::current()->RunUntilIdle();
142
143    EXPECT_EQ(expected_query_parameters, request->url().query());
144  }
145
146 private:
147  extensions::EventRouterForwarder* forwarder() {
148#if defined(ENABLE_EXTENSIONS)
149    return forwarder_.get();
150#else
151    return NULL;
152#endif
153  }
154
155  content::TestBrowserThreadBundle thread_bundle_;
156#if defined(ENABLE_EXTENSIONS)
157  scoped_refptr<extensions::EventRouterForwarder> forwarder_;
158#endif
159  TestingProfile profile_;
160  BooleanPrefMember enable_referrers_;
161  BooleanPrefMember force_google_safe_search_;
162  scoped_ptr<net::URLRequest> request_;
163  net::TestURLRequestContext context_;
164  net::NetworkDelegate* network_delegate_;
165  net::TestDelegate delegate_;
166};
167
168TEST_F(ChromeNetworkDelegateSafeSearchTest, SafeSearchOn) {
169  // Tests with SafeSearch on, request parameters should be rewritten.
170  const std::string kSafeParameter = chrome::kSafeSearchSafeParameter;
171  const std::string kSsuiParameter = chrome::kSafeSearchSsuiParameter;
172  const std::string kBothParameters = kSafeParameter + "&" + kSsuiParameter;
173  SetSafeSearch(true);
174  scoped_ptr<net::NetworkDelegate> delegate(CreateNetworkDelegate());
175  SetDelegate(delegate.get());
176
177  // Test the home page.
178  CheckAddedParameters("http://google.com/", kBothParameters);
179
180  // Test the search home page.
181  CheckAddedParameters("http://google.com/webhp",
182                       kBothParameters);
183
184  // Test different valid search pages with parameters.
185  CheckAddedParameters("http://google.com/search?q=google",
186                       "q=google&" + kBothParameters);
187
188  CheckAddedParameters("http://google.com/?q=google",
189                       "q=google&" + kBothParameters);
190
191  CheckAddedParameters("http://google.com/webhp?q=google",
192                       "q=google&" + kBothParameters);
193
194  // Test the valid pages with safe set to off.
195  CheckAddedParameters("http://google.com/search?q=google&safe=off",
196                       "q=google&" + kBothParameters);
197
198  CheckAddedParameters("http://google.com/?q=google&safe=off",
199                       "q=google&" + kBothParameters);
200
201  CheckAddedParameters("http://google.com/webhp?q=google&safe=off",
202                       "q=google&" + kBothParameters);
203
204  CheckAddedParameters("http://google.com/webhp?q=google&%73afe=off",
205                       "q=google&%73afe=off&" + kBothParameters);
206
207  // Test the home page, different TLDs.
208  CheckAddedParameters("http://google.de/", kBothParameters);
209  CheckAddedParameters("http://google.ro/", kBothParameters);
210  CheckAddedParameters("http://google.nl/", kBothParameters);
211
212  // Test the search home page, different TLD.
213  CheckAddedParameters("http://google.de/webhp", kBothParameters);
214
215  // Test the search page with parameters, different TLD.
216  CheckAddedParameters("http://google.de/search?q=google",
217                       "q=google&" + kBothParameters);
218
219  // Test the home page with parameters, different TLD.
220  CheckAddedParameters("http://google.de/?q=google",
221                       "q=google&" + kBothParameters);
222
223  // Test the search page with the parameters set.
224  CheckAddedParameters("http://google.de/?q=google&" + kBothParameters,
225                       "q=google&" + kBothParameters);
226
227  // Test some possibly tricky combinations.
228  CheckAddedParameters("http://google.com/?q=goog&" + kSafeParameter +
229                       "&ssui=one",
230                       "q=goog&" + kBothParameters);
231
232  CheckAddedParameters("http://google.de/?q=goog&unsafe=active&" +
233                       kSsuiParameter,
234                       "q=goog&unsafe=active&" + kBothParameters);
235
236  CheckAddedParameters("http://google.de/?q=goog&safe=off&ssui=off",
237                       "q=goog&" + kBothParameters);
238
239  // Test various combinations where we should not add anything.
240  CheckAddedParameters("http://google.com/?q=goog&" + kSsuiParameter + "&" +
241                       kSafeParameter,
242                       "q=goog&" + kBothParameters);
243
244  CheckAddedParameters("http://google.com/?" + kSsuiParameter + "&q=goog&" +
245                       kSafeParameter,
246                       "q=goog&" + kBothParameters);
247
248  CheckAddedParameters("http://google.com/?" + kSsuiParameter + "&" +
249                       kSafeParameter + "&q=goog",
250                       "q=goog&" + kBothParameters);
251
252  // Test that another website is not affected, without parameters.
253  CheckAddedParameters("http://google.com/finance", std::string());
254
255  // Test that another website is not affected, with parameters.
256  CheckAddedParameters("http://google.com/finance?q=goog", "q=goog");
257
258  // Test that another website is not affected with redirects, with parameters.
259  CheckAddedParameters("http://finance.google.com/?q=goog", "q=goog");
260
261  // Test with percent-encoded data (%26 is &)
262  CheckAddedParameters("http://google.com/?q=%26%26%26&" + kSsuiParameter +
263                       "&" + kSafeParameter + "&param=%26%26%26",
264                       "q=%26%26%26&param=%26%26%26&" + kBothParameters);
265}
266
267TEST_F(ChromeNetworkDelegateSafeSearchTest, SafeSearchOff) {
268  // Tests with SafeSearch settings off, delegate should not alter requests.
269  SetSafeSearch(false);
270  scoped_ptr<net::NetworkDelegate> delegate(CreateNetworkDelegate());
271  SetDelegate(delegate.get());
272
273  // Test the home page.
274  CheckAddedParameters("http://google.com/", std::string());
275
276  // Test the search home page.
277  CheckAddedParameters("http://google.com/webhp", std::string());
278
279  // Test the home page with parameters.
280  CheckAddedParameters("http://google.com/search?q=google",
281                       "q=google");
282
283  // Test the search page with parameters.
284  CheckAddedParameters("http://google.com/?q=google",
285                       "q=google");
286
287  // Test the search webhp page with parameters.
288  CheckAddedParameters("http://google.com/webhp?q=google",
289                       "q=google");
290
291  // Test the home page with parameters and safe set to off.
292  CheckAddedParameters("http://google.com/search?q=google&safe=off",
293                       "q=google&safe=off");
294
295  // Test the home page with parameters and safe set to active.
296  CheckAddedParameters("http://google.com/search?q=google&safe=active",
297                       "q=google&safe=active");
298}
299
300// Privacy Mode disables Channel Id if cookies are blocked (cr223191)
301class ChromeNetworkDelegatePrivacyModeTest : public testing::Test {
302 public:
303  ChromeNetworkDelegatePrivacyModeTest()
304      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
305#if defined(ENABLE_EXTENSIONS)
306        forwarder_(new extensions::EventRouterForwarder()),
307#endif
308        cookie_settings_(CookieSettings::Factory::GetForProfile(&profile_)
309                             .get()),
310        kBlockedSite("http://ads.thirdparty.com"),
311        kAllowedSite("http://good.allays.com"),
312        kFirstPartySite("http://cool.things.com"),
313        kBlockedFirstPartySite("http://no.thirdparties.com") {}
314
315  virtual void SetUp() OVERRIDE {
316    ChromeNetworkDelegate::InitializePrefsOnUIThread(
317        &enable_referrers_, NULL, NULL,
318        profile_.GetTestingPrefService());
319  }
320
321 protected:
322  scoped_ptr<ChromeNetworkDelegate> CreateNetworkDelegate() {
323    scoped_ptr<ChromeNetworkDelegate> network_delegate(
324        new ChromeNetworkDelegate(forwarder(), &enable_referrers_));
325    network_delegate->set_cookie_settings(cookie_settings_);
326    return network_delegate.Pass();
327  }
328
329  void SetDelegate(net::NetworkDelegate* delegate) {
330    network_delegate_ = delegate;
331    context_.set_network_delegate(network_delegate_);
332  }
333
334 protected:
335  extensions::EventRouterForwarder* forwarder() {
336#if defined(ENABLE_EXTENSIONS)
337    return forwarder_.get();
338#else
339    return NULL;
340#endif
341  }
342
343  content::TestBrowserThreadBundle thread_bundle_;
344#if defined(ENABLE_EXTENSIONS)
345  scoped_refptr<extensions::EventRouterForwarder> forwarder_;
346#endif
347  TestingProfile profile_;
348  CookieSettings* cookie_settings_;
349  BooleanPrefMember enable_referrers_;
350  scoped_ptr<net::URLRequest> request_;
351  net::TestURLRequestContext context_;
352  net::NetworkDelegate* network_delegate_;
353
354  const GURL kBlockedSite;
355  const GURL kAllowedSite;
356  const GURL kEmptyFirstPartySite;
357  const GURL kFirstPartySite;
358  const GURL kBlockedFirstPartySite;
359};
360
361TEST_F(ChromeNetworkDelegatePrivacyModeTest, DisablePrivacyIfCookiesAllowed) {
362  scoped_ptr<ChromeNetworkDelegate> delegate(CreateNetworkDelegate());
363  SetDelegate(delegate.get());
364
365  EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
366                                                       kEmptyFirstPartySite));
367}
368
369
370TEST_F(ChromeNetworkDelegatePrivacyModeTest, EnablePrivacyIfCookiesBlocked) {
371  scoped_ptr<ChromeNetworkDelegate> delegate(CreateNetworkDelegate());
372  SetDelegate(delegate.get());
373
374  EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kBlockedSite,
375                                                       kEmptyFirstPartySite));
376
377  cookie_settings_->SetCookieSetting(
378      ContentSettingsPattern::FromURL(kBlockedSite),
379      ContentSettingsPattern::Wildcard(),
380      CONTENT_SETTING_BLOCK);
381  EXPECT_TRUE(network_delegate_->CanEnablePrivacyMode(kBlockedSite,
382                                                      kEmptyFirstPartySite));
383}
384
385TEST_F(ChromeNetworkDelegatePrivacyModeTest, EnablePrivacyIfThirdPartyBlocked) {
386  scoped_ptr<ChromeNetworkDelegate> delegate(CreateNetworkDelegate());
387  SetDelegate(delegate.get());
388
389  EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
390                                                       kFirstPartySite));
391
392  profile_.GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true);
393  EXPECT_TRUE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
394                                                      kFirstPartySite));
395  profile_.GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, false);
396  EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
397                                                       kFirstPartySite));
398}
399
400TEST_F(ChromeNetworkDelegatePrivacyModeTest,
401       DisablePrivacyIfOnlyFirstPartyBlocked) {
402  scoped_ptr<ChromeNetworkDelegate> delegate(CreateNetworkDelegate());
403  SetDelegate(delegate.get());
404
405  EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
406                                                       kBlockedFirstPartySite));
407
408  cookie_settings_->SetCookieSetting(
409      ContentSettingsPattern::FromURL(kBlockedFirstPartySite),
410      ContentSettingsPattern::Wildcard(),
411      CONTENT_SETTING_BLOCK);
412  // Privacy mode is disabled as kAllowedSite is still getting cookies
413  EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
414                                                       kBlockedFirstPartySite));
415}
416
417