prediction_common.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/permissions/prediction_service/prediction_common.h"
  5. #include <cmath>
  6. #include "base/notreached.h"
  7. #include "base/values.h"
  8. #include "build/build_config.h"
  9. #include "build/chromeos_buildflags.h"
  10. namespace permissions {
  11. float GetRoundedRatio(int numerator, int denominator) {
  12. if (denominator == 0)
  13. return 0;
  14. return roundf(numerator / kRoundToMultiplesOf / denominator) *
  15. kRoundToMultiplesOf;
  16. }
  17. int GetRoundedRatioForUkm(int numerator, int denominator) {
  18. return GetRoundedRatio(numerator, denominator) * 100;
  19. }
  20. int BucketizeValue(int count) {
  21. for (const int bucket : kCountBuckets) {
  22. if (count >= bucket)
  23. return bucket;
  24. }
  25. return 0;
  26. }
  27. ClientFeatures_Platform GetCurrentPlatformProto() {
  28. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
  29. BUILDFLAG(IS_MAC)
  30. return permissions::ClientFeatures_Platform_PLATFORM_DESKTOP;
  31. #elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
  32. return permissions::ClientFeatures_Platform_PLATFORM_MOBILE;
  33. #else
  34. return permissions::ClientFeatures_Platform_PLATFORM_UNSPECIFIED;
  35. #endif
  36. }
  37. ClientFeatures_PlatformEnum GetCurrentPlatformEnumProto() {
  38. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
  39. BUILDFLAG(IS_MAC)
  40. return permissions::ClientFeatures_PlatformEnum_PLATFORM_DESKTOP_V2;
  41. #elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
  42. return permissions::ClientFeatures_PlatformEnum_PLATFORM_MOBILE_V2;
  43. #else
  44. return permissions::ClientFeatures_PlatformEnum_PLATFORM_UNSPECIFIED_V2;
  45. #endif
  46. }
  47. ClientFeatures_Gesture ConvertToProtoGesture(
  48. const permissions::PermissionRequestGestureType type) {
  49. switch (type) {
  50. case permissions::PermissionRequestGestureType::GESTURE:
  51. return permissions::ClientFeatures_Gesture_GESTURE;
  52. case permissions::PermissionRequestGestureType::NO_GESTURE:
  53. return permissions::ClientFeatures_Gesture_NO_GESTURE;
  54. case permissions::PermissionRequestGestureType::UNKNOWN:
  55. return permissions::ClientFeatures_Gesture_GESTURE_UNSPECIFIED;
  56. case permissions::PermissionRequestGestureType::NUM:
  57. break;
  58. }
  59. NOTREACHED();
  60. return permissions::ClientFeatures_Gesture_GESTURE_UNSPECIFIED;
  61. }
  62. ClientFeatures_GestureEnum ConvertToProtoGestureEnum(
  63. const permissions::PermissionRequestGestureType type) {
  64. switch (type) {
  65. case permissions::PermissionRequestGestureType::GESTURE:
  66. return permissions::ClientFeatures_GestureEnum_GESTURE_V2;
  67. case permissions::PermissionRequestGestureType::NO_GESTURE:
  68. case permissions::PermissionRequestGestureType::UNKNOWN:
  69. return permissions::ClientFeatures_GestureEnum_GESTURE_UNSPECIFIED_V2;
  70. case permissions::PermissionRequestGestureType::NUM:
  71. break;
  72. }
  73. NOTREACHED();
  74. return permissions::ClientFeatures_GestureEnum_GESTURE_UNSPECIFIED_V2;
  75. }
  76. void FillInStatsFeatures(const PredictionRequestFeatures::ActionCounts& counts,
  77. StatsFeatures* features) {
  78. int total_counts = counts.total();
  79. // Round to only 2 decimal places to help prevent fingerprinting.
  80. features->set_avg_deny_rate(GetRoundedRatio(counts.denies, total_counts));
  81. features->set_avg_dismiss_rate(
  82. GetRoundedRatio(counts.dismissals, total_counts));
  83. features->set_avg_grant_rate(GetRoundedRatio(counts.grants, total_counts));
  84. features->set_avg_ignore_rate(GetRoundedRatio(counts.ignores, total_counts));
  85. features->set_prompts_count(BucketizeValue(total_counts));
  86. }
  87. std::unique_ptr<GeneratePredictionsRequest> GetPredictionRequestProto(
  88. const PredictionRequestFeatures& entity) {
  89. auto proto_request = std::make_unique<GeneratePredictionsRequest>();
  90. ClientFeatures* client_features = proto_request->mutable_client_features();
  91. client_features->set_platform(GetCurrentPlatformProto());
  92. client_features->set_gesture(ConvertToProtoGesture(entity.gesture));
  93. client_features->set_platform_enum(GetCurrentPlatformEnumProto());
  94. client_features->set_gesture_enum(ConvertToProtoGestureEnum(entity.gesture));
  95. FillInStatsFeatures(entity.all_permission_counts,
  96. client_features->mutable_client_stats());
  97. PermissionFeatures* permission_features =
  98. proto_request->mutable_permission_features()->Add();
  99. FillInStatsFeatures(entity.requested_permission_counts,
  100. permission_features->mutable_permission_stats());
  101. switch (entity.type) {
  102. case RequestType::kNotifications:
  103. permission_features->mutable_notification_permission()->Clear();
  104. break;
  105. case RequestType::kGeolocation:
  106. permission_features->mutable_geolocation_permission()->Clear();
  107. break;
  108. default:
  109. NOTREACHED()
  110. << "CPSS only supports notifications and geolocation at the moment.";
  111. }
  112. return proto_request;
  113. }
  114. } // namespace permissions