blob: 9326ce6d38eeb4b6240413bacf9311889153e871 [file] [log] [blame]
// 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_