| // Copyright 2020 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IDENTIFIABILITY_PAINT_OP_DIGEST_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IDENTIFIABILITY_PAINT_OP_DIGEST_H_ |
| |
| #include <memory> |
| |
| #include "cc/paint/draw_image.h" |
| #include "cc/paint/image_provider.h" |
| #include "cc/paint/paint_cache.h" |
| #include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h" |
| #include "third_party/blink/renderer/platform/geometry/int_size.h" |
| #include "third_party/blink/renderer/platform/platform_export.h" |
| #include "third_party/skia/include/utils/SkNoDrawCanvas.h" |
| |
| namespace blink { |
| |
| // Manages digest calculation of operations performed on an HTML canvas using |
| // the serialization of PaintOps generated by those operations. |
| class PLATFORM_EXPORT IdentifiabilityPaintOpDigest { |
| public: |
| // Constructs based on the size of the CanvasResourceProvider. |
| explicit IdentifiabilityPaintOpDigest(IntSize size); |
| // For-testing constructor that allows setting a custom |max_digest_ops_|. |
| IdentifiabilityPaintOpDigest(IntSize size, int max_digest_ops); |
| ~IdentifiabilityPaintOpDigest(); |
| |
| // When passed as |num_ops_to_visit| to MaybeUpdateDigest(), every |
| // non-skipped PaintOp in the buffer contributes to digest calculation. |
| static constexpr size_t kInfiniteOps = -1; |
| |
| // Maybe update the digest, if the user is participating in the study, and we |
| // haven't exceeded the operation count. |
| // |
| // Only processes |num_ops_to_visit| PaintOps, which includes the first |
| // |prefix_skip_count| PaintOps that are skipped. The prefix and suffixes that |
| // aren't processed are internal rendering details, and don't correspond to |
| // operations performed on the canvas context. |
| void MaybeUpdateDigest(const sk_sp<const cc::PaintRecord>& paint_record, |
| size_t num_ops_to_visit); |
| |
| // Sets the number of operations to skip in the next PaintRecord passed to |
| // MaybeUpdateDigest(). |
| void SetPrefixSkipCount(size_t prefix_skip_count) { |
| prefix_skip_count_ = prefix_skip_count; |
| } |
| |
| // The IdentifiabilityToken (digest), based on the PaintOps observed. |
| IdentifiableToken GetToken() const { return builder_.GetToken(); } |
| |
| bool encountered_partially_digested_image() const { |
| return encountered_partially_digested_image_; |
| } |
| |
| bool encountered_skipped_ops() const { return encountered_skipped_ops_; } |
| |
| private: |
| class IdentifiabilityImageProvider : public cc::ImageProvider { |
| public: |
| explicit IdentifiabilityImageProvider(IdentifiabilityPaintOpDigest* outer) |
| : outer_(outer) {} |
| |
| ScopedResult GetRasterContent(const cc::DrawImage& draw_image) override; |
| |
| private: |
| IdentifiabilityPaintOpDigest* const outer_; |
| }; |
| |
| // The maximum number of ops to digest during the lifetime of this |
| // IdentifiabilityPaintOpDigest object. |
| const int max_digest_ops_; |
| |
| // Potentially updated every MaybeUpdateDigest() call. |
| IdentifiableTokenBuilder builder_; |
| |
| // The number of PaintOps that have contributed to the current digest -- used |
| // to stop updating the digest after a threshold number of operations to avoid |
| // hurting performance. |
| int total_ops_digested_ = 0; |
| |
| // How many PaintOps to skip, as set by SetPrefixSkipCount(). |
| size_t prefix_skip_count_ = 0; |
| |
| // Resources needed for PaintOp serialization. |
| |
| // Size of the corresponding CanvasResourceProvider. |
| IntSize size_; |
| |
| // Fake identifiability image provider; can be used to compute image digests. |
| IdentifiabilityImageProvider image_provider_{this}; |
| |
| // Real paint cache with Put() disabled. |
| cc::ClientPaintCache paint_cache_; |
| |
| // Fake canvas needed for null checks. |
| SkNoDrawCanvas nodraw_canvas_; |
| |
| // Used for PaintOp::Serialize() -- several options are not needed, since we |
| // just need to compute a digest. |
| cc::PaintOp::SerializeOptions serialize_options_; |
| |
| // If true, at least one DrawImage[Rect]Op was partially digested -- the whole |
| // image wasn't digested for performance reasons. |
| bool encountered_partially_digested_image_ = false; |
| |
| // If true, at least one op was skipped completely, for performance reasons. |
| // |
| // DrawTextBlobOps don't flip this flag to true, as they are handled |
| // separately in the 2D canavs context object (to capture font fallback |
| // fingerprinting). Also, prefix and suffix ops skipped don't flip this flag |
| // to true. |
| bool encountered_skipped_ops_ = false; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IDENTIFIABILITY_PAINT_OP_DIGEST_H_ |