// Copyright 2017 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. #ifndef COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_ #define COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_ #include #include #include "base/containers/flat_set.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/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" #if BUILDFLAG(ENABLE_TAGGED_PDF) #include "ui/accessibility/ax_tree_update_forward.h" #endif 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, 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; #if BUILDFLAG(ENABLE_TAGGED_PDF) void SetAccessibilityTree(int document_cookie, const ui::AXTreeUpdate& accessibility_tree); #endif // 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 DoCompositePageToPdf( int cookie, content::RenderFrameHost* render_frame_host, const mojom::DidPrintContentParams& content, mojom::PrintCompositor::CompositePageToPdfCallback callback); // Notifies compositor to collect individual pages into a document // when processing the individual pages for preview. void DoPrepareForDocumentToPdf( int document_cookie, content::RenderFrameHost* render_frame_host, mojom::PrintCompositor::PrepareForDocumentToPdfCallback 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. void DoCompleteDocumentToPdf( int document_cookie, uint32_t pages_count, mojom::PrintCompositor::CompleteDocumentToPdfCallback callback); // Used for compositing the entire document for print preview or actual // printing. void DoCompositeDocumentToPdf( int cookie, content::RenderFrameHost* render_frame_host, const mojom::DidPrintContentParams& content, mojom::PrintCompositor::CompositeDocumentToPdfCallback 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; // Callback functions for getting the replies. static void OnDidCompositePageToPdf( mojom::PrintCompositor::CompositePageToPdfCallback callback, mojom::PrintCompositor::Status status, base::ReadOnlySharedMemoryRegion region); void OnDidCompositeDocumentToPdf( int document_cookie, mojom::PrintCompositor::CompositeDocumentToPdfCallback callback, mojom::PrintCompositor::Status status, base::ReadOnlySharedMemoryRegion region); static void OnDidPrepareForDocumentToPdf( mojom::PrintCompositor::PrepareForDocumentToPdfCallback callback, mojom::PrintCompositor::Status status); void OnDidCompleteDocumentToPdf( int document_cookie, mojom::PrintCompositor::CompleteDocumentToPdfCallback callback, mojom::PrintCompositor::Status status, base::ReadOnlySharedMemoryRegion region); void OnDidPrintFrameContent(int render_process_id, int render_frame_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); // 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& GetPrintRenderFrame( content::RenderFrameHost* rfh); // Stores the message pipe endpoint for making remote calls to the compositor. mojo::Remote 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. content::RenderFrameHost* initiator_frame_ = nullptr; // Stores the pending subframes for the composited document. base::flat_set pending_subframes_; // Stores the printed subframes for the composited document. base::flat_set printed_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> print_render_frames_; base::WeakPtrFactory weak_ptr_factory_{this}; WEB_CONTENTS_USER_DATA_KEY_DECL(); }; } // namespace printing #endif // COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_