1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PDF_TEST_PDF_VIEWER_STREAM_MANAGER_H_
#define CHROME_BROWSER_PDF_TEST_PDF_VIEWER_STREAM_MANAGER_H_
#include "base/containers/flat_set.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/pdf/pdf_viewer_stream_manager.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/web_contents_user_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class NavigationHandle;
class RenderFrameHost;
class WebContents;
} // namespace content
namespace pdf {
class TestPdfViewerStreamManager : public PdfViewerStreamManager {
public:
// Prefer using this over the constructor so that this instance is used for
// PDF loads.
static TestPdfViewerStreamManager* CreateForWebContents(
content::WebContents* web_contents);
explicit TestPdfViewerStreamManager(content::WebContents* contents);
TestPdfViewerStreamManager(const TestPdfViewerStreamManager&) = delete;
TestPdfViewerStreamManager& operator=(const TestPdfViewerStreamManager&) =
delete;
~TestPdfViewerStreamManager() override;
// WebContentsObserver overrides.
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
// PdfViewerStreamManager overrides.
void NavigateToPdfExtensionUrl(
content::FrameTreeNodeId extension_host_frame_tree_node_id,
StreamInfo* stream_info,
content::SiteInstance* site_instance,
content::GlobalRenderFrameHostId global_id) override;
// Delays the PDF extension from navigating to the PDF extension URL. There
// are two navigations for the PDF extension frame: a navigation to
// about:blank and a navigation to the PDF extension URL. This delays the
// latter navigation.
void DelayNextPdfExtensionNavigation();
// Waits until the PDF extension frame finishes its first navigation to
// about:blank, but not the navigation to the PDF extension URL. The test will
// hang if `embedder_host` is not navigating to a PDF.
void WaitUntilPdfExtensionNavigationStarted(
content::RenderFrameHost* embedder_host);
// Resumes the PDF extension frame navigation to the PDF extension URL. Must
// be used in conjunction with `DelayNextPdfExtensionNavigation()` and
// `WaitUntilPdfExtensionNavigationStarted()`.
void ResumePdfExtensionNavigation(content::RenderFrameHost* embedder_host);
// Waits until the PDF has finished loading. Returns true if the PDF loads
// successfully, false otherwise. The test will hang if `embedder_host` is not
// a PDF, or if the PDF frames never finish navigating.
[[nodiscard]] testing::AssertionResult WaitUntilPdfLoaded(
content::RenderFrameHost* embedder_host);
// Same as `WaitUntilPdfLoaded()`, but allows additional subframes under the
// PDF embedder host. There are some special cases where the PDF embedder may
// have additional subframes. See crbug.com/40671023.
[[nodiscard]] testing::AssertionResult WaitUntilPdfLoadedAllowMultipleFrames(
content::RenderFrameHost* embedder_host);
// Same as `WaitUntilPdfLoaded()`, but the first child of the primary main
// frame should be the embedder. This is a common case where an HTML page only
// embeds a single PDF.
[[nodiscard]] testing::AssertionResult WaitUntilPdfLoadedInFirstChild();
private:
// Gathers all the necessary navigation params and navigates to the PDF
// extension URL. `global_id` should be the ID for the intermediate
// about:blank host.
void GetParamsAndNavigateToPdfExtensionUrl(
content::GlobalRenderFrameHostId global_id);
// Waits for all PDF frames in a single PDF load to finish navigating.
void WaitUntilPdfNavigationFinished(content::RenderFrameHost* embedder_host);
// Indicates whether to delay the next PDF extension navigation to the PDF
// extension URL.
bool delay_next_pdf_extension_load_ = false;
// Used only if `WaitUntilPdfExtensionNavigationStarted()` was used. Resumes
// the PDF load.
base::OnceClosure on_first_pdf_extension_navigation_finished_;
// Used only if `ResumePdfExtensionNavigation()` was used. Resumes the PDF
// extension load.
base::OnceClosure on_resume_pdf_extension_navigation_;
// Used once the PDF finished loading. Resumes the test.
base::OnceClosure on_pdf_loaded_;
// Needed to avoid use-after-free in callbacks.
base::WeakPtrFactory<TestPdfViewerStreamManager> weak_factory_{this};
};
// While a `TestPdfViewerStreamManagerFactory` instance exists, it will
// automatically set itself as the global factory override. All PDF navigations
// will automatically use a `TestPdfViewerStreamManager` instance created from
// this factory.
class TestPdfViewerStreamManagerFactory
: public PdfViewerStreamManager::Factory {
public:
TestPdfViewerStreamManagerFactory();
TestPdfViewerStreamManagerFactory(const TestPdfViewerStreamManagerFactory&) =
delete;
TestPdfViewerStreamManagerFactory& operator=(
const TestPdfViewerStreamManagerFactory&) = delete;
~TestPdfViewerStreamManagerFactory() override;
// Return value is always non-nullptr. A `TestPdfViewerStreamManager` for
// `contents` must have been created by `this`, or else a crash occurs.
TestPdfViewerStreamManager* GetTestPdfViewerStreamManager(
content::WebContents* contents);
// PdfViewerStreamManager::Factory overrides.
// Use `CreatePdfViewerStreamManager()` directly to create a test PDF stream
// manager if the test does not block during navigation. If the test does
// block during navigation, then the test PDF stream manager instance should
// already be created automatically on navigation.
void CreatePdfViewerStreamManager(content::WebContents* contents) override;
private:
// Tracks managers this factory has created. It's safe to track raw pointers,
// since the pointers are only for comparison and aren't dereferenced.
base::flat_set<raw_ptr<PdfViewerStreamManager, CtnExperimental>> managers_;
};
} // namespace pdf
#endif // CHROME_BROWSER_PDF_TEST_PDF_VIEWER_STREAM_MANAGER_H_
|