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

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: Created 4 years, 4 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 11
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/test/scoped_command_line.h"
15 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/policy/cloud/policy_header_service_factory.h" 17 #include "chrome/browser/policy/cloud/policy_header_service_factory.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/renderer_host/chrome_navigation_data.h" 19 #include "chrome/browser/renderer_host/chrome_navigation_data.h"
19 #include "chrome/browser/ui/browser.h" 20 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h" 21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/test/base/in_process_browser_test.h" 22 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h" 23 #include "chrome/test/base/ui_test_utils.h"
23 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data .h" 24 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data .h"
24 #include "components/policy/core/common/cloud/cloud_policy_constants.h" 25 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
25 #include "components/policy/core/common/cloud/policy_header_io_helper.h" 26 #include "components/policy/core/common/cloud/policy_header_io_helper.h"
26 #include "components/policy/core/common/cloud/policy_header_service.h" 27 #include "components/policy/core/common/cloud/policy_header_service.h"
27 #include "components/policy/core/common/policy_switches.h" 28 #include "components/policy/core/common/policy_switches.h"
29 #include "components/prefs/pref_service.h"
30 #include "components/signin/core/common/signin_pref_names.h"
31 #include "components/signin/core/common/signin_switches.h"
28 #include "content/public/browser/navigation_data.h" 32 #include "content/public/browser/navigation_data.h"
29 #include "content/public/browser/navigation_handle.h" 33 #include "content/public/browser/navigation_handle.h"
30 #include "content/public/browser/resource_dispatcher_host.h" 34 #include "content/public/browser/resource_dispatcher_host.h"
31 #include "content/public/browser/web_contents_observer.h" 35 #include "content/public/browser/web_contents_observer.h"
32 #include "content/public/test/browser_test_utils.h" 36 #include "content/public/test/browser_test_utils.h"
37 #include "net/base/io_buffer.h"
33 #include "net/http/http_request_headers.h" 38 #include "net/http/http_request_headers.h"
39 #include "net/http/http_response_headers.h"
40 #include "net/http/http_util.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h" 41 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "net/test/embedded_test_server/http_request.h" 42 #include "net/test/embedded_test_server/http_request.h"
36 #include "net/test/embedded_test_server/http_response.h" 43 #include "net/test/embedded_test_server/http_response.h"
37 #include "net/url_request/url_request.h" 44 #include "net/url_request/url_request.h"
45 #include "net/url_request/url_request_filter.h"
46 #include "net/url_request/url_request_interceptor.h"
47 #include "net/url_request/url_request_job.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
38 50
39 using content::ResourceType; 51 using content::ResourceType;
52 using testing::HasSubstr;
53 using testing::Not;
40 54
41 namespace { 55 namespace {
42 static const char kTestPolicyHeader[] = "test_header"; 56 static const char kTestPolicyHeader[] = "test_header";
43 static const char kServerRedirectUrl[] = "/server-redirect"; 57 static const char kServerRedirectUrl[] = "/server-redirect";
44 58
45 std::unique_ptr<net::test_server::HttpResponse> HandleTestRequest( 59 std::unique_ptr<net::test_server::HttpResponse> HandleTestRequest(
46 const net::test_server::HttpRequest& request) { 60 const net::test_server::HttpRequest& request) {
47 if (base::StartsWith(request.relative_url, kServerRedirectUrl, 61 if (base::StartsWith(request.relative_url, kServerRedirectUrl,
48 base::CompareCase::SENSITIVE)) { 62 base::CompareCase::SENSITIVE)) {
49 // Extract the target URL and redirect there. 63 // Extract the target URL and redirect there.
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 ui_test_utils::NavigateToURL( 258 ui_test_utils::NavigateToURL(
245 browser(), embedded_test_server()->GetURL("/google/google.html")); 259 browser(), embedded_test_server()->GetURL("/google/google.html"));
246 } 260 }
247 SetShouldAddDataReductionProxyData(true); 261 SetShouldAddDataReductionProxyData(true);
248 { 262 {
249 DidFinishNavigationObserver nav_observer( 263 DidFinishNavigationObserver nav_observer(
250 browser()->tab_strip_model()->GetActiveWebContents(), true); 264 browser()->tab_strip_model()->GetActiveWebContents(), true);
251 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url()); 265 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
252 } 266 }
253 } 267 }
268
269 namespace {
270
271 // A mock URLRequestJob to that allows to inject specific response headers
272 // and a specific response body to a network request.
273 class MirrorMockURLRequestJob : public net::URLRequestJob {
sky 2016/08/18 19:29:50 Can you use some of the test support classes in ne
Ramin Halavati 2016/08/26 17:04:31 Done.
274 public:
275 // Callback function on the UI thread to report a (URL, request headers)
276 // pair. Indicating that the |request headers| will be sent for the |URL|.
277 using ReportResponseHeadersOnUI =
278 base::Callback<void(const std::string&, const std::string&)>;
279
280 MirrorMockURLRequestJob(net::URLRequest* request,
281 net::NetworkDelegate* network_delegate,
282 const std::string& response_headers,
283 const std::string& response_body,
284 ReportResponseHeadersOnUI report_on_ui)
285 : net::URLRequestJob(request, network_delegate),
286 response_headers_(response_headers),
287 response_body_(response_body),
288 response_body_offset_(0),
289 report_on_ui_(report_on_ui),
290 weak_factory_(this) {}
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 // Start reading asynchronously so that all error reporting and data
300 // callbacks happen as they would for network requests.
301 base::ThreadTaskRunnerHandle::Get()->PostTask(
302 FROM_HERE, base::Bind(&MirrorMockURLRequestJob::StartAsync,
303 weak_factory_.GetWeakPtr()));
304 }
305
306 int ReadRawData(net::IOBuffer* buf, int buf_size) override {
307 size_t bytes_read =
308 std::min(static_cast<size_t>(buf_size),
309 response_body_.length() - response_body_offset_);
310 memcpy(buf->data(), response_body_.c_str() + response_body_offset_,
311 bytes_read);
312 response_body_offset_ += bytes_read;
313 return bytes_read;
314 }
315
316 int GetResponseCode() const override {
317 net::HttpResponseInfo info;
318 GetResponseInfoConst(&info);
319 return info.headers->response_code();
320 }
321
322 void GetResponseInfo(net::HttpResponseInfo* info) override {
323 // Forward to private const version.
324 GetResponseInfoConst(info);
325 }
326
327 protected:
328 void StartAsync() {
329 if (!request_)
330 return;
331 set_expected_content_size(response_body_.length());
332 NotifyHeadersComplete();
333 }
334
335 // Private const version.
336 void GetResponseInfoConst(net::HttpResponseInfo* info) const {
337 // Send back mock headers.
338 std::string raw_headers;
339 raw_headers.append(response_headers_);
340 if (!response_body_.empty()) {
341 raw_headers.append(base::StringPrintf(
342 "Content-Length: %d\n", static_cast<int>(response_body_.length())));
343 }
344 info->headers =
345 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
346 raw_headers.c_str(), static_cast<int>(raw_headers.length())));
347 }
348
349 const std::string response_headers_; // All headers but 'Content-Length'.
350 const std::string response_body_;
351 size_t response_body_offset_;
352 const ReportResponseHeadersOnUI report_on_ui_;
353 base::WeakPtrFactory<MirrorMockURLRequestJob> weak_factory_;
354 };
355
356 // A URLRequestInterceptor to inject MirrorMockURLRequestJobs.
357 class MirrorMockJobInterceptor : public net::URLRequestInterceptor {
358 public:
359 using ReportResponseHeadersOnUI =
360 MirrorMockURLRequestJob::ReportResponseHeadersOnUI;
361
362 MirrorMockJobInterceptor(const std::string& response_headers,
363 const std::string& response_body,
364 ReportResponseHeadersOnUI report_on_ui)
365 : response_headers_(response_headers),
366 response_body_(response_body),
367 report_on_ui_(report_on_ui){}
368 ~MirrorMockJobInterceptor() override = default;
369
370 // URLRequestInterceptor implementation
371 net::URLRequestJob* MaybeInterceptRequest(
372 net::URLRequest* request,
373 net::NetworkDelegate* network_delegate) const override {
374 return new MirrorMockURLRequestJob(request, network_delegate,
375 response_headers_, response_body_,
376 report_on_ui_);
377 }
378
379 static void Register(const GURL& url,
380 const std::string& response_headers,
381 const std::string& response_body,
382 ReportResponseHeadersOnUI report_on_ui) {
383 EXPECT_TRUE(
384 content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
385 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
386 url.scheme(), url.host(),
387 base::WrapUnique(new MirrorMockJobInterceptor(
388 response_headers, response_body, report_on_ui)));
389 }
390
391 static void Unregister(const GURL& url) {
392 EXPECT_TRUE(
393 content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
394 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(url.scheme(),
395 url.host());
396 }
397
398 private:
399 std::string response_headers_;
400 std::string response_body_;
401 ReportResponseHeadersOnUI report_on_ui_;
402
403 DISALLOW_COPY_AND_ASSIGN(MirrorMockJobInterceptor);
404 };
405
406 void ReportRequestHeaders(std::map<std::string, std::string>* request_headers,
407 const std::string& url,
408 const std::string& headers) {
409 (*request_headers)[url] = headers;
410 }
411
412 void EmptyClosure() {}
413
414 } // namespace
415
416 IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
417 MirrorRequestHeader) {
418 // Verify that X-Chrome-Connected is appended on Google domains if account
419 // consistency is enabled, but also that it is stripped in case a request
420 // is redirected to a non-google domain.
421 // This is a regression test for crbug.com/588492.
422
423 // Enable account consistency so that mirror actually sets the
424 // X-Chrome-Connected header in requests to Google.
425 base::test::ScopedCommandLine command_line;
426 command_line.GetProcessCommandLine()->AppendSwitch(
427 switches::kEnableAccountConsistency);
428
429 browser()->profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
430 "user@gmail.com");
431 browser()->profile()->GetPrefs()->SetString(
432 prefs::kGoogleServicesUserAccountId, "account_id");
433
434 GURL google_com("http://www.google.com/");
435 GURL redirected_com("http://www.redirected.com/");
436
437 // The HTTP Request headers (i.e. the ones that are managed on the URLRequest
438 // layer, not on the URLRequestJob layer) sent from the browser are collected
439 // in this map. The keys are URLs the values the request headers.
440 std::map<std::string, std::string> request_headers;
441 MirrorMockURLRequestJob::ReportResponseHeadersOnUI report_request_headers =
442 base::Bind(&ReportRequestHeaders, &request_headers);
443
444 // Register MockJobInterceptors that redirect from google.com to
445 // redirected.com and serve static content on redirected.com.
446 content::BrowserThread::PostTask(
447 content::BrowserThread::IO, FROM_HERE,
448 base::Bind(&MirrorMockJobInterceptor::Register, google_com,
449 "HTTP/1.1 301 Moved Permanently\n"
450 "Location: http://www.redirected.com/\n",
451 std::string(), report_request_headers));
452 content::BrowserThread::PostTask(
453 content::BrowserThread::IO, FROM_HERE,
454 base::Bind(&MirrorMockJobInterceptor::Register, redirected_com,
455 "HTTP/1.1 200 OK\n"
456 "Content-type: text/plain\n",
457 "success", report_request_headers));
458
459 // Perform a navigation to google.com to observe the request headers.
460 ui_test_utils::NavigateToURL(browser(), google_com);
461
462 // Cleanup before verifying the observed headers.
463 content::BrowserThread::PostTask(
464 content::BrowserThread::IO, FROM_HERE,
465 base::Bind(&MirrorMockJobInterceptor::Unregister, redirected_com));
466 content::BrowserThread::PostTask(
467 content::BrowserThread::IO, FROM_HERE,
468 base::Bind(&MirrorMockJobInterceptor::Unregister, google_com));
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 ASSERT_EQ(1u, request_headers.count(google_com.spec()));
482 EXPECT_THAT(request_headers[google_com.spec()],
483 HasSubstr("X-Chrome-Connected"));
484 ASSERT_EQ(1u, request_headers.count(redirected_com.spec()));
485 EXPECT_THAT(request_headers[redirected_com.spec()],
486 Not(HasSubstr("X-Chrome-Connected")));
487 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698