| // 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_SERVICE_PDF_COMPOSITOR_IMPL_H_ |
| #define COMPONENTS_PRINTING_SERVICE_PDF_COMPOSITOR_IMPL_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/containers/flat_set.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/memory/shared_memory.h" |
| #include "base/optional.h" |
| #include "components/printing/service/public/cpp/pdf_service_mojo_types.h" |
| #include "components/printing/service/public/interfaces/pdf_compositor.mojom.h" |
| #include "mojo/public/cpp/system/buffer.h" |
| #include "services/service_manager/public/cpp/service_context_ref.h" |
| #include "third_party/skia/include/core/SkPicture.h" |
| #include "third_party/skia/include/core/SkRefCnt.h" |
| |
| namespace printing { |
| |
| class PdfCompositorImpl : public mojom::PdfCompositor { |
| public: |
| PdfCompositorImpl( |
| const std::string& creator, |
| std::unique_ptr<service_manager::ServiceContextRef> service_ref); |
| ~PdfCompositorImpl() override; |
| |
| // mojom::PdfCompositor |
| void AddSubframeContent( |
| uint64_t frame_guid, |
| mojo::ScopedSharedBufferHandle serialized_content, |
| const ContentToFrameMap& subframe_content_map) override; |
| void CompositePageToPdf( |
| uint64_t frame_guid, |
| uint32_t page_num, |
| mojo::ScopedSharedBufferHandle serialized_content, |
| const ContentToFrameMap& subframe_content_map, |
| mojom::PdfCompositor::CompositePageToPdfCallback callback) override; |
| void CompositeDocumentToPdf( |
| uint64_t frame_guid, |
| mojo::ScopedSharedBufferHandle serialized_content, |
| const ContentToFrameMap& subframe_content_map, |
| mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) override; |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(PdfCompositorImplTest, IsReadyToComposite); |
| FRIEND_TEST_ALL_PREFIXES(PdfCompositorImplTest, MultiLayerDependency); |
| FRIEND_TEST_ALL_PREFIXES(PdfCompositorImplTest, DependencyLoop); |
| |
| // The map needed during content deserialization. It stores the mapping |
| // between content id and its actual content. |
| using DeserializationContext = base::flat_map<uint32_t, sk_sp<SkPicture>>; |
| |
| // This is the uniform underlying type for both |
| // mojom::PdfCompositor::CompositePageToPdfCallback and |
| // mojom::PdfCompositor::CompositeDocumentToPdfCallback. |
| using CompositeToPdfCallback = |
| base::OnceCallback<void(PdfCompositor::Status, |
| mojo::ScopedSharedBufferHandle)>; |
| |
| // Other than content, it also stores the mapping for all the subframe content |
| // to the frames they refer to, and status during frame composition. |
| struct FrameInfo { |
| FrameInfo(std::unique_ptr<base::SharedMemory> content, |
| const ContentToFrameMap& map); |
| ~FrameInfo(); |
| |
| // Serialized SkPicture content of this frame. |
| std::unique_ptr<base::SharedMemory> serialized_content; |
| |
| // Frame content after composition with subframe content. |
| sk_sp<SkPicture> content; |
| |
| // Subframe content id and its corresponding frame guid. |
| ContentToFrameMap subframe_content_map; |
| |
| // The following fields are used for storing composition status. |
| // Set to true when this frame's |serialized_content| is composed with |
| // subframe content and the final result is stored in |content|. |
| bool composited = false; |
| }; |
| |
| // Stores the mapping between frame's global unique ids and their |
| // corresponding frame information. |
| using FrameMap = base::flat_map<uint64_t, std::unique_ptr<FrameInfo>>; |
| |
| // Stores the page or document's request information. |
| struct RequestInfo { |
| RequestInfo(uint64_t frame_guid, |
| base::Optional<uint32_t> page_num, |
| const base::flat_set<uint64_t>& pending_subframes, |
| CompositeToPdfCallback callback); |
| ~RequestInfo(); |
| |
| uint64_t frame_guid; |
| base::Optional<uint32_t> page_number; |
| |
| // All pending frame ids whose content is not available but needed |
| // for composition. |
| base::flat_set<uint64_t> pending_subframes; |
| |
| CompositeToPdfCallback callback; |
| }; |
| |
| // Check whether the frame with a list of subframe content is ready to |
| // composite. If not, return all unavailable frames' ids in |
| // |pending_subframes|. |
| bool IsReadyToComposite(uint64_t frame_guid, |
| const ContentToFrameMap& subframe_content_map, |
| base::flat_set<uint64_t>* pending_subframes); |
| |
| // Recursive check all the frames |frame_guid| depends on and put those |
| // not ready in |pending_subframes|. |
| void CheckFramesForReadiness(uint64_t frame_guid, |
| const ContentToFrameMap& subframe_content_map, |
| base::flat_set<uint64_t>* pending_subframes, |
| base::flat_set<uint64_t>* visited); |
| |
| // The internal implementation for handling page and documentation composition |
| // requests. |
| void HandleCompositionRequest( |
| uint64_t frame_guid, |
| base::Optional<uint32_t> page_num, |
| mojo::ScopedSharedBufferHandle serialized_content, |
| const ContentToFrameMap& subframe_content_ids, |
| CompositeToPdfCallback callback); |
| |
| // The core function for content composition and conversion to a pdf file. |
| mojom::PdfCompositor::Status CompositeToPdf( |
| uint64_t frame_guid, |
| base::Optional<uint32_t> page_num, |
| std::unique_ptr<base::SharedMemory> shared_mem, |
| const ContentToFrameMap& subframe_content_map, |
| mojo::ScopedSharedBufferHandle* handle); |
| |
| // Composite the content of a subframe. |
| sk_sp<SkPicture> CompositeSubframe(uint64_t frame_guid); |
| |
| bool CheckForPendingFrame(uint64_t frame_guid, |
| base::flat_set<uint64_t> visited_frames); |
| |
| DeserializationContext GetDeserializationContext( |
| const ContentToFrameMap& subframe_content_map); |
| |
| void FullfillRequest(uint64_t frame_guid, |
| base::Optional<uint32_t> page_num, |
| std::unique_ptr<base::SharedMemory> serialized_content, |
| const ContentToFrameMap& subframe_content_map, |
| CompositeToPdfCallback callback); |
| |
| const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; |
| const std::string creator_; |
| |
| // Keep track of all frames' information indexed by frame id. |
| FrameMap frame_info_map_; |
| |
| std::unique_ptr<RequestInfo> request_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PdfCompositorImpl); |
| }; |
| |
| } // namespace printing |
| |
| #endif // COMPONENTS_PRINTING_SERVICE_PDF_COMPOSITOR_IMPL_H_ |