blob: ff7af6102ad78a0808c758d289bda6b052f3f95c [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/media_capabilities/media_capabilities_identifiability_metrics.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_surface.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_key_system_track_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_capabilities_decoding_info.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_capabilities_key_system_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_decoding_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_key_system_access.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_key_system_configuration.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_key_system_media_capability.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_configuration.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 media_capabilities_identifiability_metrics {
namespace {
bool IsDecodingInfoTypeAllowed() {
return IdentifiabilityStudySettings::Get()->IsTypeAllowed(
IdentifiableSurface::Type::kMediaCapabilities_DecodingInfo);
}
bool ShouldSampleDecodingInfoType() {
return IdentifiabilityStudySettings::Get()->ShouldSample(
IdentifiableSurface::Type::kMediaCapabilities_DecodingInfo);
}
void RecordDecodingIdentifiabilityMetric(ExecutionContext* context,
IdentifiableToken input_token,
IdentifiableToken output_token) {
DCHECK(IsDecodingInfoTypeAllowed());
IdentifiabilityMetricBuilder(context->UkmSourceID())
.Set(IdentifiableSurface::FromTypeAndToken(
IdentifiableSurface::Type::kMediaCapabilities_DecodingInfo,
input_token),
output_token)
.Record(context->UkmRecorder());
}
// The various ComputeToken methods create digests of each of the objects,
// returning the special empty value when an input is nullptr.
IdentifiableToken ComputeToken(const VideoConfiguration* configuration) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!configuration)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder
.AddToken(IdentifiabilityBenignStringToken(configuration->contentType()))
.AddToken(
IdentifiabilityBenignStringToken(configuration->hdrMetadataType()))
.AddToken(IdentifiabilityBenignStringToken(configuration->colorGamut()))
.AddToken(
IdentifiabilityBenignStringToken(configuration->transferFunction()));
// While the strings above will be null if not present, we need to check
// the presence of numerical types explicitly.
builder.AddValue(configuration->hasWidth())
.AddValue(configuration->hasHeight())
.AddValue(configuration->hasBitrate())
.AddValue(configuration->hasFramerate());
if (configuration->hasWidth())
builder.AddValue(configuration->width());
if (configuration->hasHeight())
builder.AddValue(configuration->height());
if (configuration->hasBitrate())
builder.AddValue(configuration->bitrate());
if (configuration->hasFramerate())
builder.AddValue(configuration->framerate());
return builder.GetToken();
}
IdentifiableToken ComputeToken(const AudioConfiguration* configuration) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!configuration)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder
.AddToken(IdentifiabilityBenignStringToken(configuration->contentType()))
.AddToken(IdentifiabilityBenignStringToken(configuration->channels()));
// While the strings above will be null if not present, we need to check
// the presence of numerical types explicitly.
builder.AddValue(configuration->hasBitrate())
.AddValue(configuration->hasSamplerate());
if (configuration->hasBitrate())
builder.AddValue(configuration->bitrate());
if (configuration->hasSamplerate())
builder.AddValue(configuration->samplerate());
return builder.GetToken();
}
IdentifiableToken ComputeToken(
const KeySystemTrackConfiguration* configuration) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!configuration)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddToken(
IdentifiabilityBenignStringToken(configuration->robustness()));
return builder.GetToken();
}
IdentifiableToken ComputeToken(
const MediaKeySystemMediaCapability* capability) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!capability)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddToken(IdentifiabilityBenignStringToken(capability->contentType()))
.AddToken(IdentifiabilityBenignStringToken(capability->robustness()))
.AddToken(
IdentifiabilityBenignStringToken(capability->encryptionScheme()));
return builder.GetToken();
}
IdentifiableToken ComputeToken(
const MediaKeySystemConfiguration* configuration) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!configuration)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddToken(IdentifiabilityBenignStringToken(configuration->label()))
.AddValue(configuration->hasInitDataTypes())
.AddValue(configuration->hasAudioCapabilities())
.AddValue(configuration->hasVideoCapabilities())
.AddToken(IdentifiabilityBenignStringToken(
configuration->distinctiveIdentifier()))
.AddToken(
IdentifiabilityBenignStringToken(configuration->persistentState()))
.AddValue(configuration->hasSessionTypes());
if (configuration->hasInitDataTypes()) {
builder.AddToken(
IdentifiabilityBenignStringVectorToken(configuration->initDataTypes()));
}
if (configuration->hasAudioCapabilities()) {
const HeapVector<Member<MediaKeySystemMediaCapability>>&
audio_capabilities = configuration->audioCapabilities();
builder.AddValue(audio_capabilities.size());
for (const auto& elem : audio_capabilities)
builder.AddToken(ComputeToken(elem.Get()));
}
if (configuration->hasVideoCapabilities()) {
const HeapVector<Member<MediaKeySystemMediaCapability>>&
video_capabilities = configuration->videoCapabilities();
builder.AddValue(video_capabilities.size());
for (const auto& elem : video_capabilities)
builder.AddToken(ComputeToken(elem.Get()));
}
if (configuration->hasSessionTypes()) {
builder.AddToken(
IdentifiabilityBenignStringVectorToken(configuration->sessionTypes()));
}
return builder.GetToken();
}
IdentifiableToken ComputeToken(const MediaKeySystemAccess* access) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!access)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddToken(IdentifiabilityBenignStringToken(access->keySystem()))
.AddToken(ComputeToken(access->getConfiguration()));
return builder.GetToken();
}
IdentifiableToken ComputeToken(
const MediaCapabilitiesKeySystemConfiguration* configuration) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!configuration)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddToken(IdentifiabilityBenignStringToken(configuration->keySystem()))
.AddToken(IdentifiabilityBenignStringToken(configuration->initDataType()))
.AddToken(IdentifiabilityBenignStringToken(
configuration->distinctiveIdentifier()))
.AddValue(configuration->hasSessionTypes())
.AddToken(ComputeToken(configuration->audio()))
.AddToken(ComputeToken(configuration->video()));
if (configuration->hasSessionTypes()) {
builder.AddToken(
IdentifiabilityBenignStringVectorToken(configuration->sessionTypes()));
}
return builder.GetToken();
}
IdentifiableToken ComputeToken(
const MediaDecodingConfiguration* configuration) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!configuration)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddToken(IdentifiabilityBenignStringToken(configuration->type()))
.AddToken(ComputeToken(configuration->keySystemConfiguration()))
.AddToken(ComputeToken(configuration->video()))
.AddToken(ComputeToken(configuration->audio()));
return builder.GetToken();
}
IdentifiableToken ComputeToken(const MediaCapabilitiesDecodingInfo* info) {
DCHECK(IsDecodingInfoTypeAllowed());
if (!info)
return IdentifiableToken();
IdentifiableTokenBuilder builder;
builder.AddValue(info->supported())
.AddValue(info->smooth())
.AddValue(info->powerEfficient())
.AddToken(ComputeToken(info->keySystemAccess()));
return builder.GetToken();
}
} // namespace
void ReportDecodingInfoResult(ExecutionContext* context,
const MediaDecodingConfiguration* input,
const MediaCapabilitiesDecodingInfo* output) {
if (!IsDecodingInfoTypeAllowed() || !ShouldSampleDecodingInfoType())
return;
RecordDecodingIdentifiabilityMetric(context, ComputeToken(input),
ComputeToken(output));
}
void ReportDecodingInfoResult(ExecutionContext* context,
base::Optional<IdentifiableToken> input_token,
const MediaCapabilitiesDecodingInfo* output) {
DCHECK_EQ(IsDecodingInfoTypeAllowed(), input_token.has_value());
if (!input_token.has_value() || !ShouldSampleDecodingInfoType())
return;
RecordDecodingIdentifiabilityMetric(context, input_token.value(),
IdentifiableToken());
}
base::Optional<IdentifiableToken> ComputeDecodingInfoInputToken(
const MediaDecodingConfiguration* input) {
if (!IsDecodingInfoTypeAllowed() || !ShouldSampleDecodingInfoType())
return base::nullopt;
return ComputeToken(input);
}
} // namespace media_capabilities_identifiability_metrics
} // namespace blink