hints_component_util.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright 2018 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/optimization_guide/core/hints_component_util.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/files/file.h"
  8. #include "base/files/file_util.h"
  9. #include "base/logging.h"
  10. #include "base/metrics/histogram_functions.h"
  11. #include "base/metrics/histogram_macros.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "components/optimization_guide/core/bloom_filter.h"
  14. #include "components/optimization_guide/core/hints_component_info.h"
  15. #include "components/optimization_guide/core/hints_processing_util.h"
  16. #include "components/optimization_guide/core/optimization_filter.h"
  17. #include "components/optimization_guide/core/optimization_guide_features.h"
  18. namespace optimization_guide {
  19. namespace {
  20. const char kProcessHintsComponentResultHistogramString[] =
  21. "OptimizationGuide.ProcessHintsResult";
  22. // Populates |out_result| with |result| if |out_result| is provided.
  23. void PopulateProcessHintsComponentResultIfSet(
  24. ProcessHintsComponentResult result,
  25. ProcessHintsComponentResult* out_result) {
  26. if (out_result)
  27. *out_result = result;
  28. }
  29. // Populates |out_status| with |status| if |out_status| is provided.
  30. void PopulateOptimizationFilterStatusIfSet(
  31. OptimizationFilterStatus status,
  32. OptimizationFilterStatus* out_status) {
  33. if (out_status)
  34. *out_status = status;
  35. }
  36. // Attempts to construct a valid bloom filter from the given
  37. // |optimization_filter|. If given, |out_status| will be populated with the
  38. // status of the operation. If a valid bloom filter cannot be constructed,
  39. // nullptr is returned.
  40. std::unique_ptr<BloomFilter> ProcessBloomFilter(
  41. const proto::OptimizationFilter& optimization_filter,
  42. OptimizationFilterStatus* out_status) {
  43. const auto& bloom_filter_proto = optimization_filter.bloom_filter();
  44. DCHECK_GT(bloom_filter_proto.num_hash_functions(), 0u);
  45. DCHECK_GT(bloom_filter_proto.num_bits(), 0u);
  46. DCHECK(bloom_filter_proto.has_data());
  47. if (!bloom_filter_proto.has_data() || bloom_filter_proto.num_bits() <= 0 ||
  48. bloom_filter_proto.num_bits() > bloom_filter_proto.data().size() * 8) {
  49. DLOG(ERROR) << "Bloom filter config issue";
  50. PopulateOptimizationFilterStatusIfSet(
  51. OptimizationFilterStatus::kFailedServerFilterBadConfig, out_status);
  52. return nullptr;
  53. }
  54. if (static_cast<int>(bloom_filter_proto.num_bits()) >
  55. features::MaxServerBloomFilterByteSize() * 8) {
  56. DLOG(ERROR) << "Bloom filter data exceeds maximum size of "
  57. << optimization_guide::features::MaxServerBloomFilterByteSize()
  58. << " bytes";
  59. PopulateOptimizationFilterStatusIfSet(
  60. OptimizationFilterStatus::kFailedServerFilterTooBig, out_status);
  61. return nullptr;
  62. }
  63. std::unique_ptr<BloomFilter> bloom_filter = std::make_unique<BloomFilter>(
  64. bloom_filter_proto.num_hash_functions(), bloom_filter_proto.num_bits(),
  65. bloom_filter_proto.data());
  66. PopulateOptimizationFilterStatusIfSet(
  67. OptimizationFilterStatus::kCreatedServerFilter, out_status);
  68. return bloom_filter;
  69. }
  70. // Attempts to construct a valid RegexpList from the given
  71. // |regexps_list|. If given, |out_status| will be populated with the
  72. // status of the operation. If a valid RegexpList cannot be constructed, nullptr
  73. // is returned.
  74. std::unique_ptr<RegexpList> ProcessRegexps(
  75. const google::protobuf::RepeatedPtrField<std::string>& regexps_list,
  76. OptimizationFilterStatus* out_status) {
  77. std::unique_ptr<RegexpList> regexps = std::make_unique<RegexpList>();
  78. for (int i = 0; i < regexps_list.size(); ++i) {
  79. regexps->emplace_back(std::make_unique<re2::RE2>(regexps_list.at(i)));
  80. if (!regexps->at(i)->ok()) {
  81. PopulateOptimizationFilterStatusIfSet(
  82. OptimizationFilterStatus::kInvalidRegexp, out_status);
  83. return nullptr;
  84. }
  85. }
  86. PopulateOptimizationFilterStatusIfSet(
  87. OptimizationFilterStatus::kCreatedServerFilter, out_status);
  88. return regexps;
  89. }
  90. } // namespace
  91. const char kComponentHintsUpdatedResultHistogramString[] =
  92. "OptimizationGuide.UpdateComponentHints.Result";
  93. void RecordProcessHintsComponentResult(ProcessHintsComponentResult result) {
  94. UMA_HISTOGRAM_ENUMERATION(kProcessHintsComponentResultHistogramString,
  95. result);
  96. }
  97. std::unique_ptr<proto::Configuration> ProcessHintsComponent(
  98. const HintsComponentInfo& component_info,
  99. ProcessHintsComponentResult* out_result) {
  100. if (!component_info.version.IsValid() || component_info.path.empty()) {
  101. PopulateProcessHintsComponentResultIfSet(
  102. ProcessHintsComponentResult::kFailedInvalidParameters, out_result);
  103. return nullptr;
  104. }
  105. std::string binary_pb;
  106. if (!base::ReadFileToString(component_info.path, &binary_pb)) {
  107. PopulateProcessHintsComponentResultIfSet(
  108. ProcessHintsComponentResult::kFailedReadingFile, out_result);
  109. return nullptr;
  110. }
  111. std::unique_ptr<proto::Configuration> proto_configuration =
  112. std::make_unique<proto::Configuration>();
  113. if (!proto_configuration->ParseFromString(binary_pb)) {
  114. PopulateProcessHintsComponentResultIfSet(
  115. ProcessHintsComponentResult::kFailedInvalidConfiguration, out_result);
  116. return nullptr;
  117. }
  118. PopulateProcessHintsComponentResultIfSet(
  119. ProcessHintsComponentResult::kSuccess, out_result);
  120. return proto_configuration;
  121. }
  122. void RecordOptimizationFilterStatus(proto::OptimizationType optimization_type,
  123. OptimizationFilterStatus status) {
  124. base::UmaHistogramExactLinear(
  125. base::StringPrintf(
  126. "OptimizationGuide.OptimizationFilterStatus.%s",
  127. GetStringNameForOptimizationType(optimization_type).c_str()),
  128. static_cast<int>(status),
  129. static_cast<int>(OptimizationFilterStatus::kMaxValue));
  130. }
  131. std::unique_ptr<OptimizationFilter> ProcessOptimizationFilter(
  132. const proto::OptimizationFilter& optimization_filter,
  133. OptimizationFilterStatus* out_status) {
  134. std::unique_ptr<BloomFilter> bloom_filter;
  135. if (optimization_filter.has_bloom_filter()) {
  136. bloom_filter = ProcessBloomFilter(optimization_filter, out_status);
  137. if (!bloom_filter)
  138. return nullptr;
  139. }
  140. std::unique_ptr<RegexpList> regexps;
  141. if (optimization_filter.regexps_size() > 0) {
  142. regexps = ProcessRegexps(optimization_filter.regexps(), out_status);
  143. if (!regexps)
  144. return nullptr;
  145. }
  146. std::unique_ptr<RegexpList> exclusion_regexps;
  147. if (optimization_filter.exclusion_regexps_size() > 0) {
  148. exclusion_regexps =
  149. ProcessRegexps(optimization_filter.exclusion_regexps(), out_status);
  150. if (!exclusion_regexps)
  151. return nullptr;
  152. }
  153. return std::make_unique<OptimizationFilter>(
  154. std::move(bloom_filter), std::move(regexps), std::move(exclusion_regexps),
  155. optimization_filter.skip_host_suffix_checking());
  156. }
  157. } // namespace optimization_guide