tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

field_trials.cc (3577B)


      1 /*
      2 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "api/field_trials.h"
     12 
     13 #include <memory>
     14 #include <string>
     15 #include <utility>
     16 
     17 #include "absl/base/nullability.h"
     18 #include "absl/memory/memory.h"
     19 #include "absl/strings/string_view.h"
     20 #include "api/field_trials_registry.h"
     21 #include "rtc_base/checks.h"
     22 #include "rtc_base/containers/flat_map.h"
     23 
     24 namespace webrtc {
     25 namespace {
     26 
     27 absl::string_view NextKeyOrValue(absl::string_view& s) {
     28  absl::string_view::size_type separator_pos = s.find('/');
     29  if (separator_pos == absl::string_view::npos) {
     30    // Missing separator '/' after field trial key or value.
     31    return "";
     32  }
     33  absl::string_view result = s.substr(0, separator_pos);
     34  s.remove_prefix(separator_pos + 1);
     35  return result;
     36 }
     37 
     38 bool Parse(absl::string_view s,
     39           flat_map<std::string, std::string>& key_value_map) {
     40  while (!s.empty()) {
     41    absl::string_view key = NextKeyOrValue(s);
     42    absl::string_view value = NextKeyOrValue(s);
     43    if (key.empty() || value.empty()) {
     44      return false;
     45    }
     46 
     47    auto it = key_value_map.emplace(key, value).first;
     48    if (it->second != value) {
     49      // Duplicate trials with different values is not fine.
     50      return false;
     51    }
     52  }
     53  return true;
     54 }
     55 
     56 }  // namespace
     57 
     58 absl_nullable std::unique_ptr<FieldTrials> FieldTrials::Create(
     59    absl::string_view s) {
     60  flat_map<std::string, std::string> key_value_map;
     61  if (!Parse(s, key_value_map)) {
     62    return nullptr;
     63  }
     64  // Using `new` to access a private constructor.
     65  return absl::WrapUnique(new FieldTrials(std::move(key_value_map)));
     66 }
     67 
     68 FieldTrials::FieldTrials(absl::string_view s) {
     69  RTC_CHECK(Parse(s, key_value_map_));
     70 }
     71 
     72 FieldTrials::FieldTrials(const FieldTrials& other)
     73    : FieldTrialsRegistry(other) {
     74  key_value_map_ = other.key_value_map_;
     75 }
     76 
     77 FieldTrials::FieldTrials(FieldTrials&& other) : FieldTrialsRegistry(other) {
     78  key_value_map_ = std::move(other.key_value_map_);
     79 }
     80 
     81 FieldTrials& FieldTrials::operator=(const FieldTrials& other) {
     82  if (this != &other) {
     83    AssertGetValueNotCalled();
     84    FieldTrialsRegistry::operator=(other);
     85    key_value_map_ = other.key_value_map_;
     86  }
     87  return *this;
     88 }
     89 
     90 FieldTrials& FieldTrials::operator=(FieldTrials&& other) {
     91  if (this != &other) {
     92    AssertGetValueNotCalled();
     93    FieldTrialsRegistry::operator=(other);
     94    key_value_map_ = std::move(other.key_value_map_);
     95  }
     96  return *this;
     97 }
     98 
     99 void FieldTrials::Merge(const FieldTrials& other) {
    100  AssertGetValueNotCalled();
    101  for (const auto& [trial, group] : other.key_value_map_) {
    102    key_value_map_.insert_or_assign(trial, group);
    103  }
    104 }
    105 
    106 void FieldTrials::Set(absl::string_view trial, absl::string_view group) {
    107  AssertGetValueNotCalled();
    108  RTC_CHECK(!trial.empty());
    109  RTC_CHECK_EQ(trial.find('/'), absl::string_view::npos);
    110  RTC_CHECK_EQ(group.find('/'), absl::string_view::npos);
    111  if (group.empty()) {
    112    key_value_map_.erase(trial);
    113  } else {
    114    key_value_map_.insert_or_assign(trial, group);
    115  }
    116 }
    117 
    118 std::string FieldTrials::GetValue(absl::string_view key) const {
    119 #if RTC_DCHECK_IS_ON
    120  get_value_called_ = true;
    121 #endif
    122  auto it = key_value_map_.find(key);
    123  if (it != key_value_map_.end()) {
    124    return it->second;
    125  }
    126 
    127  return "";
    128 }
    129 
    130 }  // namespace webrtc