File: identifiability_study_helper.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (231 lines) | stat: -rw-r--r-- 7,279 bytes parent folder | download | duplicates (4)
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Copyright 2020 The Chromium Authors
// 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_MODULES_CANVAS_CANVAS2D_IDENTIFIABILITY_STUDY_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_IDENTIFIABILITY_STUDY_HELPER_H_

#include <stdint.h>

#include <array>
#include <initializer_list>

#include "base/compiler_specific.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/forward.h"  // IWYU pragma: keep (blink::Visitor)
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"

// https://github.com/include-what-you-use/include-what-you-use/issues/1546
// IWYU pragma: no_forward_declare WTF::internal::__thisIsHereToForceASemicolonAfterThisMacro

// IWYU pragma: no_include "third_party/blink/renderer/platform/heap/visitor.h"

namespace blink {

// Text operations supported on different canvas types; the intent is to use
// these values (and any input supplied to these operations) to build a running
// hash that reprensents the sequence of text operations performed on the
// canvas. A hash of all other canvas operations is maintained by hashing the
// serialized PaintOps produced by the canvas in CanvasResourceProvider.
//
// If a canvas method to exfiltrate the canvas buffer is called by a script
// (getData(), etc.), this hash will be uploaded to UKM along with a hash of the
// canvas buffer data.
//
// **Don't renumber after the privacy budget study has started to ensure
// consistency.**
enum class CanvasOps {
  // CanvasPath operations.
  kClosePath = 0,
  kMoveTo,
  kLineTo,
  kQuadradicCurveTo,
  kBezierCurveTo,
  kArcTo,
  kArc,
  kEllipse,
  kRect,
  // Path2D operations.
  kAddPath,
  // Canvas2DRecorderContext methods.
  kSetStrokeStyle,
  kSetFillStyle,
  kSetLineWidth,
  kSetLineCap,
  kSetLineJoin,
  kSetMiterLimit,
  kSetLineDash,
  kSetLineDashOffset,
  kSetShadowOffsetX,
  kSetShadowOffsetY,
  kSetShadowBlur,
  kSetShadowColor,
  kSetGlobalAlpha,
  kSetGlobalCompositeOpertion,
  kSetFilter,
  kSave,
  kRestore,
  kScale,
  kRotate,
  kTranslate,
  kTransform,
  kResetTransform,
  kBeginPath,
  kFill,
  kFill__Path,
  kStroke,
  kStroke__Path,
  kClip,
  kClip__Path,
  kClearRect,
  kFillRect,
  kStrokeRect,
  kDrawImage,
  kCreateLinearGradient,
  kCreateRadialGradient,
  kCreatePattern,
  kPutImageData,
  kSetImageSmoothingEnabled,
  kSetImageSmoothingQuality,
  kSetTextAlign,
  kSetTextBaseline,
  kReset,
  // CanvasRenderingContext2D / OffscreenCanvasRenderingContext2D methods.
  kSetFont,
  kFillText,
  kStrokeText,
  kDrawFocusIfNeeded,  // CanvasRenderingContext2D only.
  // CanvasGradient methods.
  kAddColorStop,
};

// A helper class to simplify maintaining the current text digest for the canvas
// context. An operation count is also maintained to limit the performance
// impact of the study.
class IdentifiabilityStudyHelper final {
  DISALLOW_NEW();

 public:
  // UpdateBuilder() should be called iff ShouldUpdateBuilder() is true, to
  // avoid unnecessary copies of parameters and hashing when GetToken() won't be
  // called.
  ALWAYS_INLINE bool ShouldUpdateBuilder() {
    if (!is_canvas_type_allowed_) [[likely]] {
      return false;
    }
    if (!execution_context_ ||
        execution_context_->IsInRequestAnimationFrame() ||
        operation_count_ >= max_operations_) {
      encountered_skipped_ops_ = true;
      return false;
    }
    return true;
  }

  // Do *not* call this method if ShouldUpdateBuilder() is false -- updates
  // the internal digest based on the series of digestable parameters.
  template <typename... Ts>
  void UpdateBuilder(Ts... tokens) {
    AddTokens({tokens...});
    operation_count_++;
  }

  // Returns an IdentifiableToken representing the internal computed digest.
  IdentifiableToken GetToken() const {
    if (position_ == 0) {
      return chaining_value_;
    }
    return DigestPartialData();
  }

  [[nodiscard]] bool encountered_skipped_ops() const {
    return encountered_skipped_ops_;
  }

  [[nodiscard]] bool encountered_sensitive_ops() const {
    return encountered_sensitive_ops_;
  }

  [[nodiscard]] bool encountered_partially_digested_image() const {
    return encountered_partially_digested_image_;
  }

  void set_encountered_skipped_ops() { encountered_skipped_ops_ = true; }

  void set_encountered_sensitive_ops() { encountered_sensitive_ops_ = true; }

  void set_encountered_partially_digested_image() {
    encountered_partially_digested_image_ = true;
  }

  void SetExecutionContext(ExecutionContext* context) {
    execution_context_ = context;
  }

  ExecutionContext* execution_context() const {
    return execution_context_.Get();
  }

  // For testing, allows scoped changing the max number of operations for all
  // IdentifiabilityStudyHelper instances.
  class ScopedMaxOperationsSetter {
   public:
    explicit ScopedMaxOperationsSetter(int new_value)
        : old_max_operations_(IdentifiabilityStudyHelper::max_operations_) {
      IdentifiabilityStudyHelper::max_operations_ = new_value;
    }
    ~ScopedMaxOperationsSetter() {
      IdentifiabilityStudyHelper::max_operations_ = old_max_operations_;
    }

   private:
    const int old_max_operations_;
  };

  void Trace(Visitor* visitor) const;

 private:
  // Note that primitives are implicitly converted to IdentifiableTokens.
  void MODULES_EXPORT
  AddTokens(std::initializer_list<IdentifiableToken> tokens);

  uint64_t MODULES_EXPORT DigestPartialData() const;

  const bool is_canvas_type_allowed_ =
      IdentifiabilityStudySettings::Get()->ShouldSampleType(
          blink::IdentifiableSurface::Type::kCanvasReadback);

  Member<ExecutionContext> execution_context_;

  static MODULES_EXPORT int max_operations_;

  int operation_count_ = 0;

  // If true, at least one op was skipped completely, for performance reasons.
  bool encountered_skipped_ops_ = false;

  // If true, encountered at least one "sensitive" operation -- for instance,
  // strings may contain PII, so we only use a 16-bit digest for such strings.
  //
  // This must be set manually by calling set_encountered_sensitive_ops().
  bool encountered_sensitive_ops_ = false;

  // If true, at least one op was partially-digested -- for instance, images
  // drawn to the canvas have their width, height, etc. digested, but not the
  // image contents, for performance and complexity reasons.
  bool encountered_partially_digested_image_ = false;

  std::array<int64_t, 8> partial_;
  wtf_size_t position_ = 0;
  uint64_t chaining_value_ = IdentifiableTokenBuilder::kChainingValueSeed;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_IDENTIFIABILITY_STUDY_HELPER_H_