chromium/content/browser/loader/object_navigation_fallback_body_loader.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_LOADER_OBJECT_NAVIGATION_FALLBACK_BODY_LOADER_H_
#define CONTENT_BROWSER_LOADER_OBJECT_NAVIGATION_FALLBACK_BODY_LOADER_H_

#include <memory>
#include <optional>
#include <string>

#include "base/functional/callback.h"
#include "base/memory/raw_ref.h"
#include "content/public/browser/navigation_handle_user_data.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"

namespace content {

class NavigationRequest;

// Helper to read body of an <object> navigation that failed with an HTTP error.
// Per https://whatwg.org/C/iframe-embed-object.html#the-object-element, the
// browser should fire an error event and then execute the fallback steps.
//
// What the standard does not specify, but all browser seem to implement, is
// that the failed navigation should *also* add a resource timing entry.
// Unfortunately, this proves to be a bit interesting to implement using the
// existing codepaths:
//
// - Navigation code would like to enforce the invariant that asking a cross-RFH
//   navigation to commit always results in a committed navigation. This is
//   critical for fixing bugs like https://crbug.com/83834 correctly. Thus, the
//   failed navigation cannot simply be sent to the renderer to commit (because
//   it's not supposed to actually result in a committed navigation). This means
//   that all the existing plumbing for generating the resource timing info from
//   loading a navigation body cannot be reused.
// - The response body cannot simply be sent to the renderer with the <object>
//   element, as this could lead to CORS violations. It's unsafe to simply send
//   the response head of any redirect responess + the final redirect as well.
//
// This leads to a rather unsatisfactory implementation that requires
// duplicating significant amounts of the resource timing code in the browser.
// It would be nice to do better somehow in the future...
class ObjectNavigationFallbackBodyLoader
    : public NavigationHandleUserData<ObjectNavigationFallbackBodyLoader>,
      public network::mojom::URLLoaderClient,
      public mojo::DataPipeDrainer::Client {};

}  // namespace content

#endif  // CONTENT_BROWSER_LOADER_OBJECT_NAVIGATION_FALLBACK_BODY_LOADER_H_