| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/network/loader_util.h" |
| |
| #include <string> |
| |
| #include "base/command_line.h" |
| #include "base/strings/stringprintf.h" |
| #include "net/base/load_flags.h" |
| #include "net/base/mime_sniffer.h" |
| #include "net/http/http_raw_request_headers.h" |
| #include "net/http/http_util.h" |
| #include "net/url_request/url_request.h" |
| #include "services/network/public/cpp/http_raw_request_response_info.h" |
| #include "services/network/public/cpp/network_switches.h" |
| #include "services/network/public/cpp/resource_response.h" |
| #include "url/gurl.h" |
| |
| namespace network { |
| |
| const char kAcceptHeader[] = "Accept"; |
| const char kFrameAcceptHeader[] = |
| "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp," |
| "image/apng,*/*;q=0.8"; |
| const char kDefaultAcceptHeader[] = "*/*"; |
| |
| bool ShouldSniffContent(net::URLRequest* url_request, |
| ResourceResponse* response) { |
| const std::string& mime_type = response->head.mime_type; |
| |
| std::string content_type_options; |
| url_request->GetResponseHeaderByName("x-content-type-options", |
| &content_type_options); |
| |
| bool sniffing_blocked = |
| base::LowerCaseEqualsASCII(content_type_options, "nosniff"); |
| bool we_would_like_to_sniff = |
| net::ShouldSniffMimeType(url_request->url(), mime_type); |
| |
| if (!sniffing_blocked && we_would_like_to_sniff) { |
| // We're going to look at the data before deciding what the content type |
| // is. That means we need to delay sending the response started IPC. |
| VLOG(1) << "To buffer: " << url_request->url().spec(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| scoped_refptr<HttpRawRequestResponseInfo> BuildRawRequestResponseInfo( |
| const net::URLRequest& request, |
| const net::HttpRawRequestHeaders& raw_request_headers, |
| const net::HttpResponseHeaders* raw_response_headers) { |
| scoped_refptr<HttpRawRequestResponseInfo> info = |
| new HttpRawRequestResponseInfo(); |
| |
| const net::HttpResponseInfo& response_info = request.response_info(); |
| // Unparsed headers only make sense if they were sent as text, i.e. HTTP 1.x. |
| bool report_headers_text = |
| !response_info.DidUseQuic() && !response_info.was_fetched_via_spdy; |
| |
| for (const auto& pair : raw_request_headers.headers()) |
| info->request_headers.push_back(pair); |
| std::string request_line = raw_request_headers.request_line(); |
| if (report_headers_text && !request_line.empty()) { |
| std::string text = std::move(request_line); |
| for (const auto& pair : raw_request_headers.headers()) { |
| if (!pair.second.empty()) { |
| base::StringAppendF(&text, "%s: %s\r\n", pair.first.c_str(), |
| pair.second.c_str()); |
| } else { |
| base::StringAppendF(&text, "%s:\r\n", pair.first.c_str()); |
| } |
| } |
| info->request_headers_text = std::move(text); |
| } |
| |
| if (!raw_response_headers) |
| raw_response_headers = request.response_headers(); |
| if (raw_response_headers) { |
| info->http_status_code = raw_response_headers->response_code(); |
| info->http_status_text = raw_response_headers->GetStatusText(); |
| |
| std::string name; |
| std::string value; |
| for (size_t it = 0; |
| raw_response_headers->EnumerateHeaderLines(&it, &name, &value);) { |
| info->response_headers.push_back(std::make_pair(name, value)); |
| } |
| if (report_headers_text) { |
| info->response_headers_text = |
| net::HttpUtil::ConvertHeadersBackToHTTPResponse( |
| raw_response_headers->raw_headers()); |
| } |
| } |
| return info; |
| } |
| |
| std::string ComputeReferrer(const GURL& referrer) { |
| if (!referrer.is_valid() || base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kNoReferrers)) { |
| return std::string(); |
| } |
| |
| return referrer.spec(); |
| } |
| |
| } // namespace network |