// 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_