blob: 57cfd563f87504dbd7b20266e26f3fef114b75fa [file] [log] [blame]
// 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 "content/common/service_worker/service_worker_loader_helpers.h"
#include "base/strings/stringprintf.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_features.h"
#include "content/public/common/resource_request.h"
#include "content/public/common/resource_response.h"
#include "net/http/http_util.h"
namespace content {
// static
std::unique_ptr<ServiceWorkerFetchRequest>
ServiceWorkerLoaderHelpers::CreateFetchRequest(const ResourceRequest& request) {
auto new_request = std::make_unique<ServiceWorkerFetchRequest>();
new_request->mode = request.fetch_request_mode;
new_request->is_main_resource_load =
ServiceWorkerUtils::IsMainResourceType(request.resource_type);
new_request->request_context_type = request.fetch_request_context_type;
new_request->frame_type = request.fetch_frame_type;
new_request->url = request.url;
new_request->method = request.method;
// |blob_uuid| and |blob_size| aren't used in MojoBlobs, so just clear them.
// The caller is responsible for setting the MojoBlob field |blob| if needed.
DCHECK(features::IsMojoBlobsEnabled());
new_request->blob_uuid.clear();
new_request->blob_size = 0;
new_request->credentials_mode = request.fetch_credentials_mode;
new_request->cache_mode =
ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(request.load_flags);
new_request->redirect_mode = request.fetch_redirect_mode;
new_request->is_reload = ui::PageTransitionCoreTypeIs(
request.transition_type, ui::PAGE_TRANSITION_RELOAD);
new_request->referrer =
Referrer(GURL(request.referrer), request.referrer_policy);
new_request->fetch_type = ServiceWorkerFetchType::FETCH;
return new_request;
}
// static
void ServiceWorkerLoaderHelpers::SaveResponseHeaders(
const int status_code,
const std::string& status_text,
const ServiceWorkerHeaderMap& headers,
ResourceResponseHead* out_head) {
// Build a string instead of using HttpResponseHeaders::AddHeader on
// each header, since AddHeader has O(n^2) performance.
std::string buf(base::StringPrintf("HTTP/1.1 %d %s\r\n", status_code,
status_text.c_str()));
for (const auto& item : headers) {
buf.append(item.first);
buf.append(": ");
buf.append(item.second);
buf.append("\r\n");
}
buf.append("\r\n");
out_head->headers = new net::HttpResponseHeaders(
net::HttpUtil::AssembleRawHeaders(buf.c_str(), buf.size()));
if (out_head->mime_type.empty()) {
std::string mime_type;
out_head->headers->GetMimeType(&mime_type);
if (mime_type.empty())
mime_type = "text/plain";
out_head->mime_type = mime_type;
}
}
// static
void ServiceWorkerLoaderHelpers::SaveResponseInfo(
const ServiceWorkerResponse& response,
ResourceResponseHead* out_head) {
out_head->was_fetched_via_service_worker = true;
out_head->was_fetched_via_foreign_fetch = false;
out_head->was_fallback_required_by_service_worker = false;
out_head->url_list_via_service_worker = response.url_list;
out_head->response_type_via_service_worker = response.response_type;
out_head->is_in_cache_storage = response.is_in_cache_storage;
out_head->cache_storage_cache_name = response.cache_storage_cache_name;
out_head->cors_exposed_header_names = response.cors_exposed_header_names;
out_head->did_service_worker_navigation_preload = false;
}
// static
base::Optional<net::RedirectInfo>
ServiceWorkerLoaderHelpers::ComputeRedirectInfo(
const ResourceRequest& original_request,
const ResourceResponseHead& response_head,
bool token_binding_negotiated) {
std::string new_location;
if (!response_head.headers->IsRedirect(&new_location))
return base::nullopt;
std::string referrer_string;
net::URLRequest::ReferrerPolicy referrer_policy;
Referrer::ComputeReferrerInfo(
&referrer_string, &referrer_policy,
Referrer(original_request.referrer, original_request.referrer_policy));
// If the request is a MAIN_FRAME request, the first-party URL gets
// updated on redirects.
const net::URLRequest::FirstPartyURLPolicy first_party_url_policy =
original_request.resource_type == RESOURCE_TYPE_MAIN_FRAME
? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT
: net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
return net::RedirectInfo::ComputeRedirectInfo(
original_request.method, original_request.url,
original_request.site_for_cookies, first_party_url_policy,
referrer_policy, referrer_string, response_head.headers.get(),
response_head.headers->response_code(),
original_request.url.Resolve(new_location), token_binding_negotiated);
}
} // namespace content