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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc
index 57388aaed81d6c3ad32f7421455e84acb653a35b..818b46b898a68a07446061b674332fc1d054a335 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc
@@ -12,6 +12,7 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
+#include "base/test/scoped_command_line.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/cloud/policy_header_service_factory.h"
#include "chrome/browser/profiles/profile.h"
@@ -25,18 +26,31 @@
#include "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "components/policy/core/common/cloud/policy_header_service.h"
#include "components/policy/core/common/policy_switches.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/core/common/signin_pref_names.h"
+#include "components/signin/core/common/signin_switches.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test_utils.h"
+#include "net/base/io_buffer.h"
#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_filter.h"
+#include "net/url_request/url_request_interceptor.h"
+#include "net/url_request/url_request_job.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
using content::ResourceType;
+using testing::HasSubstr;
+using testing::Not;
namespace {
static const char kTestPolicyHeader[] = "test_header";
@@ -251,3 +265,223 @@ IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
}
}
+
+namespace {
+
+// A mock URLRequestJob to that allows to inject specific response headers
+// and a specific response body to a network request.
+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.
+ public:
+ // Callback function on the UI thread to report a (URL, request headers)
+ // pair. Indicating that the |request headers| will be sent for the |URL|.
+ using ReportResponseHeadersOnUI =
+ base::Callback<void(const std::string&, const std::string&)>;
+
+ MirrorMockURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& response_headers,
+ const std::string& response_body,
+ ReportResponseHeadersOnUI report_on_ui)
+ : net::URLRequestJob(request, network_delegate),
+ response_headers_(response_headers),
+ response_body_(response_body),
+ response_body_offset_(0),
+ report_on_ui_(report_on_ui),
+ weak_factory_(this) {}
+
+ void Start() override {
+ // Report the observed request headers on the UI thread.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(report_on_ui_, request_->url().spec(),
+ request_->extra_request_headers().ToString()));
+
+ // Start reading asynchronously so that all error reporting and data
+ // callbacks happen as they would for network requests.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&MirrorMockURLRequestJob::StartAsync,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ int ReadRawData(net::IOBuffer* buf, int buf_size) override {
+ size_t bytes_read =
+ std::min(static_cast<size_t>(buf_size),
+ response_body_.length() - response_body_offset_);
+ memcpy(buf->data(), response_body_.c_str() + response_body_offset_,
+ bytes_read);
+ response_body_offset_ += bytes_read;
+ return bytes_read;
+ }
+
+ int GetResponseCode() const override {
+ net::HttpResponseInfo info;
+ GetResponseInfoConst(&info);
+ return info.headers->response_code();
+ }
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ // Forward to private const version.
+ GetResponseInfoConst(info);
+ }
+
+ protected:
+ void StartAsync() {
+ if (!request_)
+ return;
+ set_expected_content_size(response_body_.length());
+ NotifyHeadersComplete();
+ }
+
+ // Private const version.
+ void GetResponseInfoConst(net::HttpResponseInfo* info) const {
+ // Send back mock headers.
+ std::string raw_headers;
+ raw_headers.append(response_headers_);
+ if (!response_body_.empty()) {
+ raw_headers.append(base::StringPrintf(
+ "Content-Length: %d\n", static_cast<int>(response_body_.length())));
+ }
+ info->headers =
+ new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+ raw_headers.c_str(), static_cast<int>(raw_headers.length())));
+ }
+
+ const std::string response_headers_; // All headers but 'Content-Length'.
+ const std::string response_body_;
+ size_t response_body_offset_;
+ const ReportResponseHeadersOnUI report_on_ui_;
+ base::WeakPtrFactory<MirrorMockURLRequestJob> weak_factory_;
+};
+
+// A URLRequestInterceptor to inject MirrorMockURLRequestJobs.
+class MirrorMockJobInterceptor : public net::URLRequestInterceptor {
+ public:
+ using ReportResponseHeadersOnUI =
+ MirrorMockURLRequestJob::ReportResponseHeadersOnUI;
+
+ MirrorMockJobInterceptor(const std::string& response_headers,
+ const std::string& response_body,
+ ReportResponseHeadersOnUI report_on_ui)
+ : response_headers_(response_headers),
+ response_body_(response_body),
+ report_on_ui_(report_on_ui){}
+ ~MirrorMockJobInterceptor() override = default;
+
+ // URLRequestInterceptor implementation
+ net::URLRequestJob* MaybeInterceptRequest(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return new MirrorMockURLRequestJob(request, network_delegate,
+ response_headers_, response_body_,
+ report_on_ui_);
+ }
+
+ static void Register(const GURL& url,
+ const std::string& response_headers,
+ const std::string& response_body,
+ ReportResponseHeadersOnUI report_on_ui) {
+ EXPECT_TRUE(
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
+ url.scheme(), url.host(),
+ base::WrapUnique(new MirrorMockJobInterceptor(
+ response_headers, response_body, report_on_ui)));
+ }
+
+ static void Unregister(const GURL& url) {
+ EXPECT_TRUE(
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(url.scheme(),
+ url.host());
+ }
+
+ private:
+ std::string response_headers_;
+ std::string response_body_;
+ ReportResponseHeadersOnUI report_on_ui_;
+
+ DISALLOW_COPY_AND_ASSIGN(MirrorMockJobInterceptor);
+};
+
+void ReportRequestHeaders(std::map<std::string, std::string>* request_headers,
+ const std::string& url,
+ const std::string& headers) {
+ (*request_headers)[url] = headers;
+}
+
+void EmptyClosure() {}
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
+ MirrorRequestHeader) {
+ // Verify that X-Chrome-Connected is appended on Google domains if account
+ // consistency is enabled, but also that it is stripped in case a request
+ // is redirected to a non-google domain.
+ // This is a regression test for crbug.com/588492.
+
+ // Enable account consistency so that mirror actually sets the
+ // X-Chrome-Connected header in requests to Google.
+ base::test::ScopedCommandLine command_line;
+ command_line.GetProcessCommandLine()->AppendSwitch(
+ switches::kEnableAccountConsistency);
+
+ browser()->profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+ "user@gmail.com");
+ browser()->profile()->GetPrefs()->SetString(
+ prefs::kGoogleServicesUserAccountId, "account_id");
+
+ GURL google_com("http://www.google.com/");
+ GURL redirected_com("http://www.redirected.com/");
+
+ // The HTTP Request headers (i.e. the ones that are managed on the URLRequest
+ // layer, not on the URLRequestJob layer) sent from the browser are collected
+ // in this map. The keys are URLs the values the request headers.
+ std::map<std::string, std::string> request_headers;
+ MirrorMockURLRequestJob::ReportResponseHeadersOnUI report_request_headers =
+ base::Bind(&ReportRequestHeaders, &request_headers);
+
+ // Register MockJobInterceptors that redirect from google.com to
+ // redirected.com and serve static content on redirected.com.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&MirrorMockJobInterceptor::Register, google_com,
+ "HTTP/1.1 301 Moved Permanently\n"
+ "Location: http://www.redirected.com/\n",
+ std::string(), report_request_headers));
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&MirrorMockJobInterceptor::Register, redirected_com,
+ "HTTP/1.1 200 OK\n"
+ "Content-type: text/plain\n",
+ "success", report_request_headers));
+
+ // Perform a navigation to google.com to observe the request headers.
+ ui_test_utils::NavigateToURL(browser(), google_com);
+
+ // Cleanup before verifying the observed headers.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&MirrorMockJobInterceptor::Unregister, redirected_com));
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&MirrorMockJobInterceptor::Unregister, google_com));
+
+ // Ensure that the response headers have been reported to the UI thread
+ // and unregistration has been processed on the IO thread.
+ base::RunLoop run_loop;
+ content::BrowserThread::PostTaskAndReply(content::BrowserThread::IO,
+ FROM_HERE,
+ // Flush IO thread...
+ base::Bind(&EmptyClosure),
+ // ... and UI thread.
+ run_loop.QuitClosure());
+ run_loop.Run();
+
+ ASSERT_EQ(1u, request_headers.count(google_com.spec()));
+ EXPECT_THAT(request_headers[google_com.spec()],
+ HasSubstr("X-Chrome-Connected"));
+ ASSERT_EQ(1u, request_headers.count(redirected_com.spec()));
+ EXPECT_THAT(request_headers[redirected_com.spec()],
+ Not(HasSubstr("X-Chrome-Connected")));
+}

Powered by Google App Engine
This is Rietveld 408576698