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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_
#define COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_
#include <map>
#include <memory>
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/printing/common/print.mojom.h"
#include "components/services/print_compositor/public/mojom/print_compositor.mojom.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "printing/buildflags/buildflags.h"
#include "printing/mojom/print.mojom.h"
#include "ui/accessibility/ax_tree_update_forward.h"
namespace printing {
// Class to manage print requests and their communication with print compositor
// service. Each composite request have a separate interface pointer to connect
// with remote service. The request and its subframe printing results are
// tracked by its document cookie and print page number.
class PrintCompositeClient
: public content::WebContentsUserData<PrintCompositeClient>,
public content::WebContentsObserver {
public:
explicit PrintCompositeClient(content::WebContents* web_contents);
PrintCompositeClient(const PrintCompositeClient&) = delete;
PrintCompositeClient& operator=(const PrintCompositeClient&) = delete;
~PrintCompositeClient() override;
// content::WebContentsObserver
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void SetAccessibilityTree(int document_cookie,
const ui::AXTreeUpdate& accessibility_tree);
// Instructs the specified subframe to print.
void PrintCrossProcessSubframe(const gfx::Rect& rect,
int document_cookie,
content::RenderFrameHost* subframe_host);
// Printing single pages is only used by print preview for early return of
// rendered results. In this case, the pages share the content with printed
// document. The document can be collected from the individual pages,
// avoiding the need to also send the entire document again as a large blob.
// This is for compositing such a single preview page.
void CompositePage(int cookie,
content::RenderFrameHost* render_frame_host,
const mojom::DidPrintContentParams& content,
mojom::PrintCompositor::CompositePageCallback callback);
// Notifies compositor to collect individual pages into a document
// when processing the individual pages for preview. The `document_type`
// specified determines the format of the document passed back in the
// `callback` from `FinishDocumentComposition()`.
void PrepareToCompositeDocument(
int document_cookie,
content::RenderFrameHost* render_frame_host,
mojom::PrintCompositor::DocumentType document_type,
mojom::PrintCompositor::PrepareToCompositeDocumentCallback callback);
// Notifies compositor of the total number of pages being concurrently
// collected into the document, allowing for completion of the composition
// when all pages have been received. The format of the provided document
// is of the `document_type` specified in `PrepareToCompositeDocument()`.
void FinishDocumentComposition(
int document_cookie,
uint32_t pages_count,
mojom::PrintCompositor::FinishDocumentCompositionCallback callback);
// Used for compositing the entire document for print preview or actual
// printing.
void CompositeDocument(
int cookie,
content::RenderFrameHost* render_frame_host,
const mojom::DidPrintContentParams& content,
const ui::AXTreeUpdate& accessibility_tree,
mojom::GenerateDocumentOutline generate_document_outline,
mojom::PrintCompositor::DocumentType document_type,
mojom::PrintCompositor::CompositeDocumentCallback callback);
// Get the concurrent composition status for a document. Identifies if the
// full document will be compiled from the individual pages; if not then a
// separate document object will need to be provided.
bool GetIsDocumentConcurrentlyComposited(int cookie) const;
void SetUserAgent(const std::string& user_agent) { user_agent_ = user_agent; }
private:
friend class content::WebContentsUserData<PrintCompositeClient>;
FRIEND_TEST_ALL_PREFIXES(PrintBrowserTest,
PrintSubframeContentBeforeCompositeClientCreation);
// Callback functions for getting the replies.
static void OnDidCompositePage(
mojom::PrintCompositor::CompositePageCallback callback,
mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region);
void OnDidCompositeDocument(
int document_cookie,
mojom::PrintCompositor::CompositeDocumentCallback callback,
mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region);
static void OnDidPrepareToCompositeDocument(
mojom::PrintCompositor::PrepareToCompositeDocumentCallback callback,
mojom::PrintCompositor::Status status);
void OnDidFinishDocumentComposition(
int document_cookie,
mojom::PrintCompositor::FinishDocumentCompositionCallback callback,
mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region);
void OnDidPrintFrameContent(content::GlobalRenderFrameHostId rfh_id,
int document_cookie,
mojom::DidPrintContentParamsPtr params);
// Creates a new composite request for a given document |cookie|. Since
// printed pages always share content with its document, they share the same
// composite request. Launches the compositor in a separate process.
// If a composite request already exists, it is removed.
// Returns the created composite request.
mojom::PrintCompositor* CreateCompositeRequest(
int cookie,
content::RenderFrameHost* initiator_frame,
mojom::PrintCompositor::DocumentType document_type);
// Remove the existing composite request.
void RemoveCompositeRequest(int cookie);
// Checks if the |document_cookie| is not 0 and matches |document_cookie_|.
bool IsDocumentCookieValid(int document_cookie) const;
// Get the composite request of a document. |cookie| must be valid and equal
// to |document_cookie_|.
mojom::PrintCompositor* GetCompositeRequest(int cookie) const;
// Helper method to fetch the PrintRenderFrame remote interface pointer
// associated with a given subframe.
const mojo::AssociatedRemote<mojom::PrintRenderFrame>& GetPrintRenderFrame(
content::RenderFrameHost* rfh);
// Stores the message pipe endpoint for making remote calls to the compositor.
mojo::Remote<mojom::PrintCompositor> compositor_;
// Stores the unique sequential cookie of the document being composited.
// Holds 0 if no document is being composited.
int document_cookie_ = 0;
// Stores whether the document is concurrently compositing using individual
// pages, so that no separate composite request with full-document blob is
// required.
bool is_doc_concurrently_composited_ = false;
// Stores the the frame that initiated the composite request;
// Holds nullptr if no document is being composited.
raw_ptr<content::RenderFrameHost> initiator_frame_ = nullptr;
// Stores the pending subframes for the composited document.
base::flat_set<raw_ptr<content::RenderFrameHost, CtnExperimental>>
pending_subframes_;
// Stores the printed subframes for the composited document.
base::flat_set<raw_ptr<content::RenderFrameHost, CtnExperimental>>
printed_subframes_;
struct RequestedSubFrame {
RequestedSubFrame(content::GlobalRenderFrameHostId rfh_id,
int document_cookie,
mojom::DidPrintContentParamsPtr params,
bool is_live);
~RequestedSubFrame();
RequestedSubFrame(const RequestedSubFrame&) = delete;
RequestedSubFrame& operator=(const RequestedSubFrame&) = delete;
content::GlobalRenderFrameHostId rfh_id_;
int document_cookie_;
mojom::DidPrintContentParamsPtr params_;
bool is_live_;
};
base::flat_set<std::unique_ptr<RequestedSubFrame>> requested_subframes_;
std::string user_agent_;
// Stores a PrintRenderFrame associated remote with the RenderFrameHost used
// to bind it. The PrintRenderFrame is used to transmit mojo interface method
// calls to the associated receiver.
std::map<content::RenderFrameHost*,
mojo::AssociatedRemote<mojom::PrintRenderFrame>>
print_render_frames_;
base::WeakPtrFactory<PrintCompositeClient> weak_ptr_factory_{this};
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
} // namespace printing
#endif // COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_
|