Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc

Issue 2258483002: X-Chrome-Connected is stripped when it should not be in headers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: X-Chrome-Connected header is not removed if not originated from Google. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate. h" 5 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate. h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
11 #include <vector>
11 12
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/path_service.h"
16 #include "base/stl_util.h"
14 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "base/test/scoped_command_line.h"
15 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/policy/cloud/policy_header_service_factory.h" 20 #include "chrome/browser/policy/cloud/policy_header_service_factory.h"
17 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/renderer_host/chrome_navigation_data.h" 22 #include "chrome/browser/renderer_host/chrome_navigation_data.h"
19 #include "chrome/browser/ui/browser.h" 23 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h" 24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/common/chrome_paths.h"
21 #include "chrome/test/base/in_process_browser_test.h" 26 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h" 27 #include "chrome/test/base/ui_test_utils.h"
23 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data .h" 28 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data .h"
24 #include "components/policy/core/common/cloud/cloud_policy_constants.h" 29 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
25 #include "components/policy/core/common/cloud/policy_header_io_helper.h" 30 #include "components/policy/core/common/cloud/policy_header_io_helper.h"
26 #include "components/policy/core/common/cloud/policy_header_service.h" 31 #include "components/policy/core/common/cloud/policy_header_service.h"
27 #include "components/policy/core/common/policy_switches.h" 32 #include "components/policy/core/common/policy_switches.h"
33 #include "components/prefs/pref_service.h"
34 #include "components/signin/core/browser/signin_header_helper.h"
35 #include "components/signin/core/common/signin_pref_names.h"
36 #include "components/signin/core/common/signin_switches.h"
28 #include "content/public/browser/navigation_data.h" 37 #include "content/public/browser/navigation_data.h"
29 #include "content/public/browser/navigation_handle.h" 38 #include "content/public/browser/navigation_handle.h"
30 #include "content/public/browser/resource_dispatcher_host.h" 39 #include "content/public/browser/resource_dispatcher_host.h"
40 #include "content/public/browser/resource_dispatcher_host_delegate.h"
31 #include "content/public/browser/web_contents_observer.h" 41 #include "content/public/browser/web_contents_observer.h"
32 #include "content/public/test/browser_test_utils.h" 42 #include "content/public/test/browser_test_utils.h"
33 #include "net/http/http_request_headers.h" 43 #include "net/http/http_request_headers.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h" 44 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "net/test/embedded_test_server/http_request.h" 45 #include "net/test/embedded_test_server/http_request.h"
36 #include "net/test/embedded_test_server/http_response.h" 46 #include "net/test/embedded_test_server/http_response.h"
47 #include "net/test/url_request/url_request_mock_http_job.h"
37 #include "net/url_request/url_request.h" 48 #include "net/url_request/url_request.h"
49 #include "net/url_request/url_request_filter.h"
50 #include "testing/gmock/include/gmock/gmock-matchers.h"
38 51
39 using content::ResourceType; 52 using content::ResourceType;
53 using testing::HasSubstr;
54 using testing::Not;
40 55
41 namespace { 56 namespace {
42 static const char kTestPolicyHeader[] = "test_header"; 57 static const char kTestPolicyHeader[] = "test_header";
43 static const char kServerRedirectUrl[] = "/server-redirect"; 58 static const char kServerRedirectUrl[] = "/server-redirect";
44 59
45 std::unique_ptr<net::test_server::HttpResponse> HandleTestRequest( 60 std::unique_ptr<net::test_server::HttpResponse> HandleTestRequest(
46 const net::test_server::HttpRequest& request) { 61 const net::test_server::HttpRequest& request) {
47 if (base::StartsWith(request.relative_url, kServerRedirectUrl, 62 if (base::StartsWith(request.relative_url, kServerRedirectUrl,
48 base::CompareCase::SENSITIVE)) { 63 base::CompareCase::SENSITIVE)) {
49 // Extract the target URL and redirect there. 64 // Extract the target URL and redirect there.
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 ui_test_utils::NavigateToURL( 259 ui_test_utils::NavigateToURL(
245 browser(), embedded_test_server()->GetURL("/google/google.html")); 260 browser(), embedded_test_server()->GetURL("/google/google.html"));
246 } 261 }
247 SetShouldAddDataReductionProxyData(true); 262 SetShouldAddDataReductionProxyData(true);
248 { 263 {
249 DidFinishNavigationObserver nav_observer( 264 DidFinishNavigationObserver nav_observer(
250 browser()->tab_strip_model()->GetActiveWebContents(), true); 265 browser()->tab_strip_model()->GetActiveWebContents(), true);
251 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url()); 266 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
252 } 267 }
253 } 268 }
269
270 namespace {
271
272 // A URLRequestMockHTTPJob to that reports HTTP request headers of outgoing
273 // requests.
274 class MirrorMockURLRequestJob : public net::URLRequestMockHTTPJob {
275 public:
276 // Callback function on the UI thread to report a (URL, request headers)
277 // pair. Indicating that the |request headers| will be sent for the |URL|.
278 using ReportResponseHeadersOnUI =
279 base::Callback<void(const std::string&, const std::string&)>;
280
281 MirrorMockURLRequestJob(net::URLRequest* request,
282 net::NetworkDelegate* network_delegate,
283 const base::FilePath& file_path,
284 const scoped_refptr<base::TaskRunner>& task_runner,
285 ReportResponseHeadersOnUI report_on_ui)
286 : net::URLRequestMockHTTPJob(request,
287 network_delegate,
288 file_path,
289 task_runner),
290 report_on_ui_(report_on_ui) {}
291
292 void Start() override {
293 // Report the observed request headers on the UI thread.
294 content::BrowserThread::PostTask(
295 content::BrowserThread::UI, FROM_HERE,
296 base::Bind(report_on_ui_, request_->url().spec(),
297 request_->extra_request_headers().ToString()));
298
299 URLRequestMockHTTPJob::Start();
300 }
301
302 protected:
303 const ReportResponseHeadersOnUI report_on_ui_;
304
305 private:
306 DISALLOW_COPY_AND_ASSIGN(MirrorMockURLRequestJob);
307 };
mmenke 2016/08/30 19:12:26 Do the google checks care about port? It doesn't
mmenke 2016/08/30 19:23:39 Actually, probably best to ignore this suggestion
Ramin Halavati 2016/09/01 10:41:44 Acknowledged.
Ramin Halavati 2016/09/01 10:41:44 Acknowledged.
308
309 // A URLRequestInterceptor to inject MirrorMockURLRequestJobs.
310 class MirrorMockJobInterceptor : public net::URLRequestInterceptor {
311 public:
312 using ReportResponseHeadersOnUI =
313 MirrorMockURLRequestJob::ReportResponseHeadersOnUI;
314
315 MirrorMockJobInterceptor(const base::FilePath& root_http,
316 ReportResponseHeadersOnUI report_on_ui)
317 : root_http_(root_http), report_on_ui_(report_on_ui) {}
318 ~MirrorMockJobInterceptor() override = default;
319
320 // URLRequestInterceptor implementation
321 net::URLRequestJob* MaybeInterceptRequest(
322 net::URLRequest* request,
323 net::NetworkDelegate* network_delegate) const override {
324 return new MirrorMockURLRequestJob(
325 request, network_delegate, root_http_,
326 content::BrowserThread::GetBlockingPool()
327 ->GetTaskRunnerWithShutdownBehavior(
328 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN),
329 report_on_ui_);
330 }
331
332 static void Register(const GURL& url,
333 const base::FilePath& root_http,
334 ReportResponseHeadersOnUI report_on_ui) {
335 EXPECT_TRUE(
336 content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
337 base::FilePath file_path(root_http);
338 file_path =
339 file_path.AppendASCII(url.scheme() + "." + url.host() + ".html");
340 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
341 url.scheme(), url.host(), base::WrapUnique(new MirrorMockJobInterceptor(
342 file_path, report_on_ui)));
343 }
344
345 static void Unregister(const GURL& url) {
346 EXPECT_TRUE(
347 content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
348 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(url.scheme(),
349 url.host());
350 }
351
352 private:
353 const base::FilePath root_http_;
354 ReportResponseHeadersOnUI report_on_ui_;
355
356 DISALLOW_COPY_AND_ASSIGN(MirrorMockJobInterceptor);
357 };
358
359 void ReportRequestHeaders(std::map<std::string, std::string>* request_headers,
360 const std::string& url,
361 const std::string& headers) {
362 (*request_headers)[url] = headers;
363 }
364
365 void EmptyClosure() {}
366
367 } // namespace
368
369 class HeaderTestDispatcherHostDelegate
370 : public ChromeResourceDispatcherHostDelegate {
371 public:
372 explicit HeaderTestDispatcherHostDelegate(const GURL& watch_url)
373 : watch_url_(watch_url) {}
374 ~HeaderTestDispatcherHostDelegate() override {}
375
376 void RequestBeginning(
377 net::URLRequest* request,
378 content::ResourceContext* resource_context,
379 content::AppCacheService* appcache_service,
380 ResourceType resource_type,
381 ScopedVector<content::ResourceThrottle>* throttles) override {
382 ChromeResourceDispatcherHostDelegate::RequestBeginning(
383 request, resource_context, appcache_service, resource_type, throttles);
384 if (request->url() == watch_url_) {
385 request->SetExtraRequestHeaderByName(signin::kChromeConnectedHeader,
386 "User Data", false);
mmenke 2016/08/30 19:12:26 Why are we appending this? Shouldn't the RDH do t
Ramin Halavati 2016/09/01 10:41:44 We added a new test in the last CL in which a webs
387 }
388 }
389
390 private:
391 const GURL watch_url_;
392 DISALLOW_COPY_AND_ASSIGN(HeaderTestDispatcherHostDelegate);
393 };
394
395 // Verify the following items:
396 // 1- X-Chrome-Connected is appended on Google domains if account
397 // consistency is enabled and access is secure.
398 // 2- The header is stripped in case a request is redirected from a Gooogle
399 // domain to non-google domain.
400 // 3- The header is NOT stripped in case it is added directly by the page
401 // and not because it was on a secure Google domain.
402 // This is a regression test for crbug.com/588492.
403 IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
404 MirrorRequestHeader) {
405 // Enable account consistency so that mirror actually sets the
406 // X-Chrome-Connected header in requests to Google.
407 base::test::ScopedCommandLine command_line;
408 command_line.GetProcessCommandLine()->AppendSwitch(
409 switches::kEnableAccountConsistency);
410
411 browser()->profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
412 "user@gmail.com");
413 browser()->profile()->GetPrefs()->SetString(
414 prefs::kGoogleServicesUserAccountId, "account_id");
415
416 // Set URLS:
417 // The one that needs X-Chrome-Header injection:
418 GURL http_header_adder_com("http://www.header_adder.com");
419 // The ones that should have the X-Chrome-Header:
420 std::vector<GURL> urls_with_header = {
421 http_header_adder_com, GURL("https://www.google.com"),
422 GURL("http://www.redirected_from_header_adder.com")};
423 // All others:
424 std::vector<GURL> all_urls = {GURL("http://www.google.com"),
425 GURL("https://www.redirected.com"),
426 GURL("http://www.redirected.com")};
427 // Merge:
428 all_urls.insert(all_urls.end(), urls_with_header.begin(),
429 urls_with_header.end());
mmenke 2016/08/30 19:12:26 This seems like it would be much cleaner as single
Ramin Halavati 2016/09/01 10:41:44 Done.
430
431 // Change the delegate to the one that adds the header for
432 // http_header_adder_com.
433 HeaderTestDispatcherHostDelegate dispatcher_host_delegate(
434 http_header_adder_com);
435 content::ResourceDispatcherHost::Get()->SetDelegate(
436 &dispatcher_host_delegate);
437
438 // The HTTP Request headers (i.e. the ones that are managed on the URLRequest
439 // layer, not on the URLRequestJob layer) sent from the browser are collected
440 // in this map. The keys are URLs the values the request headers.
441 std::map<std::string, std::string> request_headers;
442 MirrorMockURLRequestJob::ReportResponseHeadersOnUI report_request_headers =
443 base::Bind(&ReportRequestHeaders, &request_headers);
444
445 base::FilePath root_http;
446 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
447 root_http = root_http.AppendASCII("mirror_request_header");
448
449 for (const GURL& url : all_urls) {
450 content::BrowserThread::PostTask(
451 content::BrowserThread::IO, FROM_HERE,
452 base::Bind(&MirrorMockJobInterceptor::Register, url, root_http,
453 report_request_headers));
454 }
455
456 // Perform a navigation to all none-redirected urls to observe
457 // the request headers.
458 for (const GURL& url : all_urls) {
459 if (url.host().find("redirect") == -1)
460 ui_test_utils::NavigateToURL(browser(), url);
461 }
mmenke 2016/08/30 19:12:26 I'm unable to figure out how we visit these URLs.
Ramin Halavati 2016/09/01 10:41:44 We have 3 starting URLs here and each one redirect
462
463 // Cleanup before verifying the observed headers.
464 for (const GURL& url : all_urls) {
465 content::BrowserThread::PostTask(
466 content::BrowserThread::IO, FROM_HERE,
467 base::Bind(&MirrorMockJobInterceptor::Unregister, url));
468 }
469
470 // Ensure that the response headers have been reported to the UI thread
471 // and unregistration has been processed on the IO thread.
472 base::RunLoop run_loop;
473 content::BrowserThread::PostTaskAndReply(content::BrowserThread::IO,
474 FROM_HERE,
475 // Flush IO thread...
476 base::Bind(&EmptyClosure),
477 // ... and UI thread.
478 run_loop.QuitClosure());
479 run_loop.Run();
480
481 content::ResourceDispatcherHost::Get()->SetDelegate(nullptr);
482
483 // Check if header exists and X-Chrome-Connected is correctly provided.
484 for (const GURL url : all_urls) {
485 ASSERT_EQ(1u, request_headers.count(url.spec()));
486 if (base::ContainsValue(urls_with_header, url))
487 EXPECT_THAT(request_headers[url.spec()],
488 HasSubstr(signin::kChromeConnectedHeader));
489 else
490 EXPECT_THAT(request_headers[url.spec()],
491 Not(HasSubstr(signin::kChromeConnectedHeader)));
492 }
493 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698