summaryrefslogtreecommitdiff
path: root/chromium/components/printing/browser/print_composite_client.h
blob: 40ff2d3c44e624dd61e44e02497a001667f133f7 (plain)
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
// 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 <map>
#include <memory>

#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<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;

#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<PrintCompositeClient>;
  // 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<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.
  content::RenderFrameHost* initiator_frame_ = nullptr;

  // Stores the pending subframes for the composited document.
  base::flat_set<content::RenderFrameHost*> pending_subframes_;

  // Stores the printed subframes for the composited document.
  base::flat_set<content::RenderFrameHost*> 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<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_