blob: 263e2cf0911fde71669b3d3a7227b61bfa6e7b14 [file] [log] [blame]
// Copyright 2017 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 "android_webview/browser/aw_field_trial_creator.h"
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "android_webview/browser/aw_metrics_service_client.h"
#include "android_webview/browser/aw_variations_seed_bridge.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/path_service.h"
#include "base/strings/string_split.h"
#include "base/time/time.h"
#include "cc/base/switches.h"
#include "components/prefs/in_memory_pref_store.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "components/variations/entropy_provider.h"
#include "components/variations/pref_names.h"
#include "components/variations/seed_response.h"
#include "components/variations/service/safe_seed_manager.h"
#include "components/variations/service/variations_service.h"
namespace android_webview {
namespace {
// TODO(kmilka): Update to work properly in environments both with and without
// UMA enabled.
std::unique_ptr<const base::FieldTrial::EntropyProvider>
CreateLowEntropyProvider(const std::string& client_id) {
return std::unique_ptr<const base::FieldTrial::EntropyProvider>(
// Since variations are only enabled for users opted in to UMA, it is
// acceptable to use the SHA1EntropyProvider for randomization.
new variations::SHA1EntropyProvider(client_id));
}
// This experiment is for testing and doesn't control any features. Log it so QA
// can check whether variations is working.
// TODO(crbug/841623): Remove this after launch.
void LogTestExperiment() {
static const char* const test_name = "First-WebView-Experiment";
base::FieldTrial* test_trial = base::FieldTrialList::Find(test_name);
if (test_trial) {
LOG(INFO) << test_name << " found, group=" << test_trial->group_name();
} else {
LOG(INFO) << test_name << " not found";
}
}
} // anonymous namespace
AwFieldTrialCreator::AwFieldTrialCreator()
: aw_field_trials_(std::make_unique<AwFieldTrials>()) {}
AwFieldTrialCreator::~AwFieldTrialCreator() {}
void AwFieldTrialCreator::SetUpFieldTrials() {
DoSetUpFieldTrials();
// If DoSetUpFieldTrials failed, it might have skipped creating
// FeatureList. If so, create a FeatureList without field trials.
if (!base::FeatureList::GetInstance()) {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
auto feature_list = std::make_unique<base::FeatureList>();
feature_list->InitializeFromCommandLine(
command_line->GetSwitchValueASCII(switches::kEnableFeatures),
command_line->GetSwitchValueASCII(switches::kDisableFeatures));
base::FeatureList::SetInstance(std::move(feature_list));
}
}
void AwFieldTrialCreator::DoSetUpFieldTrials() {
// If the client ID isn't available yet, don't delay startup by creating it.
// Instead, variations will be disabled for this run.
std::string client_id;
if (!AwMetricsServiceClient::GetPreloadedClientId(&client_id))
return;
DCHECK(!field_trial_list_);
field_trial_list_ = std::make_unique<base::FieldTrialList>(
CreateLowEntropyProvider(client_id));
variations::UIStringOverrider ui_string_overrider;
client_ = std::make_unique<AwVariationsServiceClient>();
variations_field_trial_creator_ =
std::make_unique<variations::VariationsFieldTrialCreator>(
GetLocalState(), client_.get(), ui_string_overrider,
GetAndClearJavaSeed());
variations_field_trial_creator_->OverrideVariationsPlatform(
variations::Study::PLATFORM_ANDROID_WEBVIEW);
// Unused by WebView, but required by
// VariationsFieldTrialCreator::SetupFieldTrials().
// TODO(isherman): We might want a more genuine SafeSeedManager:
// https://crbug.com/801771
std::set<std::string> unforceable_field_trials;
variations::SafeSeedManager ignored_safe_seed_manager(true, GetLocalState());
// Populates the FieldTrialList singleton via the static member functions.
variations_field_trial_creator_->SetupFieldTrials(
cc::switches::kEnableGpuBenchmarking, switches::kEnableFeatures,
switches::kDisableFeatures, unforceable_field_trials,
std::vector<std::string>(), CreateLowEntropyProvider(client_id),
std::make_unique<base::FeatureList>(), aw_field_trials_.get(),
&ignored_safe_seed_manager);
LogTestExperiment();
}
PrefService* AwFieldTrialCreator::GetLocalState() {
if (!local_state_) {
scoped_refptr<PrefRegistrySimple> pref_registry =
base::MakeRefCounted<PrefRegistrySimple>();
variations::VariationsService::RegisterPrefs(pref_registry.get());
PrefServiceFactory factory;
factory.set_user_prefs(base::MakeRefCounted<InMemoryPrefStore>());
local_state_ = factory.Create(pref_registry.get());
}
return local_state_.get();
}
} // namespace android_webview