blob: 8ca4292a3fb33a636084d6b229028309e63ba3b1 [file] [log] [blame]
// Copyright 2020 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/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_file.h"
#include "content/browser/loader/single_request_url_loader_factory.h"
#include "content/browser/web_package/web_bundle_reader.h"
#include "content/browser/web_package/web_bundle_redirect_url_loader.h"
#include "content/browser/web_package/web_bundle_source.h"
#include "content/browser/web_package/web_bundle_url_loader_factory.h"
#include "content/browser/web_package/web_bundle_utils.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace content {
// A class to inherit NavigationLoaderInterceptor for a navigation within a
// Web Bundle file.
// For example:
// A user opened "file:///tmp/a.wbn", and InterceptorForFile redirected to
// "file:///tmp/a.wbn?https://example.com/a.html" and "a.html" in "a.wbn" was
// loaded. And the user clicked a link to "https://example.com/b.html" from
// "a.html".
// In this case, this interceptor intecepts the navigation request to "b.html",
// and redirect the navigation request to
// "file:///tmp/a.wbn?https://example.com/b.html" and creates a URLLoader using
// the WebBundleURLLoaderFactory to load the response of "b.html" in
// "a.wbn".
WebBundleInterceptorForTrackedNavigationFromFile::
WebBundleInterceptorForTrackedNavigationFromFile(
scoped_refptr<WebBundleReader> reader,
WebBundleDoneCallback done_callback,
int frame_tree_node_id)
: url_loader_factory_(
std::make_unique<WebBundleURLLoaderFactory>(std::move(reader),
frame_tree_node_id)),
done_callback_(std::move(done_callback)) {}
WebBundleInterceptorForTrackedNavigationFromFile::
~WebBundleInterceptorForTrackedNavigationFromFile() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
// NavigationLoaderInterceptor implementation
void WebBundleInterceptorForTrackedNavigationFromFile::MaybeCreateLoader(
const network::ResourceRequest& resource_request,
BrowserContext* browser_context,
LoaderCallback callback,
FallbackCallback fallback_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(callback).Run(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(base::BindOnce(
&WebBundleInterceptorForTrackedNavigationFromFile::CreateURLLoader,
weak_factory_.GetWeakPtr())));
}
bool WebBundleInterceptorForTrackedNavigationFromFile::
ShouldBypassRedirectChecks() {
return true;
}
void WebBundleInterceptorForTrackedNavigationFromFile::CreateURLLoader(
const network::ResourceRequest& resource_request,
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!is_redirected_) {
DCHECK(url_loader_factory_->reader()->HasEntry(resource_request.url));
is_redirected_ = true;
original_request_url_ = resource_request.url;
GURL web_bundle_url = url_loader_factory_->reader()->source().url();
const GURL new_url = web_bundle_utils::GetSynthesizedUrlForWebBundle(
web_bundle_url, original_request_url_);
auto redirect_loader =
std::make_unique<WebBundleRedirectURLLoader>(std::move(client));
redirect_loader->OnReadyToRedirect(resource_request, new_url);
mojo::MakeSelfOwnedReceiver(
std::move(redirect_loader),
mojo::PendingReceiver<network::mojom::URLLoader>(std::move(receiver)));
return;
}
network::ResourceRequest new_resource_request = resource_request;
new_resource_request.url = original_request_url_;
url_loader_factory_->CreateLoaderAndStart(
std::move(receiver), /*routing_id=*/0, /*request_id=*/0, /*options=*/0,
new_resource_request, std::move(client),
net::MutableNetworkTrafficAnnotationTag(
web_bundle_utils::kTrafficAnnotation));
std::move(done_callback_)
.Run(original_request_url_, std::move(url_loader_factory_));
}
} // namespace content