blob: 9ef3ba43498bfe22ef41b128c7489c1378ed1760 [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.
#include "third_party/blink/renderer/modules/mediastream/identifiability_metrics.h"
#include "base/callback.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
#include "third_party/blink/renderer/bindings/modules/v8/boolean_or_constrain_boolean_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/boolean_or_double_or_constrain_double_range.h"
#include "third_party/blink/renderer/bindings/modules/v8/boolean_or_media_track_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/double_or_constrain_double_range.h"
#include "third_party/blink/renderer/bindings/modules/v8/long_or_constrain_long_range.h"
#include "third_party/blink/renderer/bindings/modules/v8/point_2d_sequence_or_constrain_point_2d_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/string_or_string_sequence_or_constrain_dom_string_parameters.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_constraints.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_track_constraint_set.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
namespace blink {
namespace {
template <typename T>
void Visit(IdentifiableTokenBuilder& builder, const T* range) {
if (!range)
return;
builder.AddToken(range->hasExact() ? range->exact() : IdentifiableToken());
builder.AddToken(range->hasIdeal() ? range->ideal() : IdentifiableToken());
builder.AddToken(range->hasMax() ? range->max() : IdentifiableToken());
builder.AddToken(range->hasMin() ? range->min() : IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const DoubleOrConstrainDoubleRange& d) {
if (d.IsDouble()) {
builder.AddToken(d.GetAsDouble());
return;
}
if (d.IsConstrainDoubleRange()) {
Visit(builder, d.GetAsConstrainDoubleRange());
return;
}
DCHECK(d.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const LongOrConstrainLongRange& l) {
if (l.IsLong()) {
builder.AddToken(l.GetAsLong());
return;
}
if (l.IsConstrainLongRange()) {
Visit(builder, l.GetAsConstrainLongRange());
return;
}
DCHECK(l.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder, const StringOrStringSequence& s) {
if (s.IsString()) {
builder.AddToken(IdentifiabilityBenignStringToken(s.GetAsString()));
return;
}
if (s.IsStringSequence()) {
for (const String& str : s.GetAsStringSequence()) {
builder.AddToken(IdentifiabilityBenignStringToken(str));
}
return;
}
DCHECK(s.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const StringOrStringSequenceOrConstrainDOMStringParameters& s) {
if (s.IsString()) {
builder.AddToken(IdentifiabilityBenignStringToken(s.GetAsString()));
return;
}
if (s.IsStringSequence()) {
for (const String& str : s.GetAsStringSequence()) {
builder.AddToken(IdentifiabilityBenignStringToken(str));
}
return;
}
if (s.IsConstrainDOMStringParameters()) {
const ConstrainDOMStringParameters* params =
s.GetAsConstrainDOMStringParameters();
if (params->hasExact()) {
Visit(builder, params->exact());
} else {
builder.AddToken(IdentifiableToken());
}
if (params->hasIdeal()) {
Visit(builder, params->ideal());
} else {
builder.AddToken(IdentifiableToken());
}
return;
}
DCHECK(s.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const BooleanOrConstrainBooleanParameters& b) {
if (b.IsBoolean()) {
builder.AddToken(b.GetAsBoolean());
return;
}
if (b.IsConstrainBooleanParameters()) {
const ConstrainBooleanParameters* params =
b.GetAsConstrainBooleanParameters();
builder.AddToken(params->hasExact() ? params->exact()
: IdentifiableToken());
builder.AddToken(params->hasIdeal() ? params->ideal()
: IdentifiableToken());
return;
}
DCHECK(b.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const BooleanOrDoubleOrConstrainDoubleRange& x) {
if (x.IsBoolean()) {
builder.AddToken(x.GetAsBoolean());
return;
}
if (x.IsConstrainDoubleRange()) {
Visit(builder, x.GetAsConstrainDoubleRange());
return;
}
if (x.IsDouble()) {
builder.AddToken(x.GetAsDouble());
return;
}
DCHECK(x.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const HeapVector<Member<Point2D>>& points) {
for (const auto& point : points) {
builder.AddToken(point->hasX() ? point->x() : IdentifiableToken());
builder.AddToken(point->hasY() ? point->y() : IdentifiableToken());
}
}
void Visit(IdentifiableTokenBuilder& builder,
const Point2DSequenceOrConstrainPoint2DParameters& x) {
if (x.IsPoint2DSequence()) {
Visit(builder, x.GetAsPoint2DSequence());
return;
}
if (x.IsConstrainPoint2DParameters()) {
const ConstrainPoint2DParameters* params =
x.GetAsConstrainPoint2DParameters();
if (params->hasExact()) {
Visit(builder, params->exact());
} else {
builder.AddToken(IdentifiableToken());
}
if (params->hasIdeal()) {
Visit(builder, params->ideal());
} else {
builder.AddToken(IdentifiableToken());
}
return;
}
DCHECK(x.IsNull());
builder.AddToken(IdentifiableToken());
}
void Visit(IdentifiableTokenBuilder& builder,
const MediaTrackConstraintSet& set) {
Visit(builder, set.width());
Visit(builder, set.height());
Visit(builder, set.aspectRatio());
Visit(builder, set.frameRate());
Visit(builder, set.facingMode());
Visit(builder, set.sampleRate());
Visit(builder, set.sampleSize());
Visit(builder, set.echoCancellation());
Visit(builder, set.autoGainControl());
Visit(builder, set.latency());
Visit(builder, set.channelCount());
Visit(builder, set.videoKind());
Visit(builder, set.whiteBalanceMode());
Visit(builder, set.exposureMode());
Visit(builder, set.focusMode());
Visit(builder, set.pointsOfInterest());
Visit(builder, set.exposureCompensation());
Visit(builder, set.exposureTime());
Visit(builder, set.colorTemperature());
Visit(builder, set.iso());
Visit(builder, set.brightness());
Visit(builder, set.contrast());
Visit(builder, set.saturation());
Visit(builder, set.sharpness());
Visit(builder, set.focusDistance());
Visit(builder, set.pan());
Visit(builder, set.tilt());
Visit(builder, set.zoom());
Visit(builder, set.torch());
}
void Visit(IdentifiableTokenBuilder& builder,
const BooleanOrMediaTrackConstraints& constraint) {
if (constraint.IsBoolean()) {
builder.AddToken(constraint.GetAsBoolean());
return;
}
if (constraint.IsMediaTrackConstraints()) {
const MediaTrackConstraints* constraints =
constraint.GetAsMediaTrackConstraints();
if (constraints) {
if (constraints->hasAdvanced()) {
for (const auto& advanced : constraints->advanced()) {
Visit(builder, *advanced);
}
return;
}
}
}
builder.AddToken(IdentifiableToken());
}
} // namespace
IdentifiableToken TokenFromConstraints(
const MediaStreamConstraints* constraints) {
IdentifiableTokenBuilder builder;
if (constraints) {
Visit(builder, constraints->audio());
Visit(builder, constraints->video());
} else {
builder.AddToken(IdentifiableToken());
}
return builder.GetToken();
}
void RecordIdentifiabilityMetric(const IdentifiableSurface& surface,
ExecutionContext* context,
IdentifiableToken token) {
if (surface.IsValid() && context &&
IdentifiabilityStudySettings::Get()->ShouldSample(surface)) {
IdentifiabilityMetricBuilder(context->UkmSourceID())
.Set(surface, token)
.Record(context->UkmRecorder());
}
}
} // namespace blink