Commit 789fc54d authored by Kyle Milka's avatar Kyle Milka Committed by Commit Bot
Browse files

Set up field trials within WebView

This is part 6 of 6 for FieldTrial refactoring for WebView

Part 1: https://chromium-review.googlesource.com/c/562098/
Part 2: https://chromium-review.googlesource.com/c/561920
Part 3: https://chromium-review.googlesource.com/c/561922/
Part 4: https://chromium-review.googlesource.com/c/561980/
Part 5: https://chromium-review.googlesource.com/c/562417/
Part 6: https://chromium-review.googlesource.com/c/562021/

This CL makes use of previous refactoring work to actually
set up field trials within WebView. The AwFieldTrialCreator class is
now used by AwBrowserMainParts to create the set of active experiments
within WebView.

BUG=678288

Change-Id: Id76b98e5adb432ca3fa7ea4cffd7c0296f160e82
Reviewed-on: https://chromium-review.googlesource.com/562021


Commit-Queue: Kyle Milka <kmilka@google.com>
Reviewed-by: default avatarPaul Miller <paulmiller@chromium.org>
Reviewed-by: default avatarTima Vaisburd <timav@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarAlexei Svitkine (very slow) <asvitkine@chromium.org>
Cr-Commit-Position: refs/heads/master@{#494175}
parent 5e4f231c
......@@ -464,6 +464,8 @@ source_set("common") {
"browser/aw_devtools_server.h",
"browser/aw_download_manager_delegate.cc",
"browser/aw_download_manager_delegate.h",
"browser/aw_field_trial_creator.cc",
"browser/aw_field_trial_creator.h",
"browser/aw_form_database.cc",
"browser/aw_form_database_service.cc",
"browser/aw_form_database_service.h",
......@@ -521,6 +523,8 @@ source_set("common") {
"browser/aw_ssl_host_state_delegate.h",
"browser/aw_url_checker_delegate_impl.cc",
"browser/aw_url_checker_delegate_impl.h",
"browser/aw_variations_service_client.cc",
"browser/aw_variations_service_client.h",
"browser/aw_web_contents_delegate.cc",
"browser/aw_web_contents_delegate.h",
"browser/aw_web_contents_view_delegate.cc",
......@@ -707,6 +711,7 @@ source_set("common") {
"//components/supervised_user_error_page",
"//components/supervised_user_error_page:gin",
"//components/url_matcher",
"//components/variations/service",
"//components/version_info",
"//components/visitedlink/browser",
"//components/visitedlink/renderer",
......
......@@ -28,6 +28,7 @@ include_rules = [
"+components/spellcheck/common",
"+components/url_formatter",
"+components/user_prefs",
"+components/variations",
"+components/visitedlink/browser",
"+components/viz/common",
"+components/viz/service/display",
......
......@@ -150,7 +150,7 @@ int AwBrowserMainParts::PreCreateThreads() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebViewVariations)) {
AwMetricsServiceClient::GetOrCreateGUID();
aw_field_trial_creator_.SetUpFieldTrials();
}
return content::RESULT_CODE_NORMAL_EXIT;
......
......@@ -7,6 +7,7 @@
#include <memory>
#include "android_webview/browser/aw_field_trial_creator.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "content/public/browser/browser_main_parts.h"
......@@ -36,6 +37,11 @@ class AwBrowserMainParts : public content::BrowserMainParts {
AwContentBrowserClient* browser_client_;
// Responsible for creating a feature list from the seed. This object must
// exist for the lifetime of the process as it contains the FieldTrialList
// that can be queried for the state of experiments.
AwFieldTrialCreator aw_field_trial_creator_;
DISALLOW_COPY_AND_ASSIGN(AwBrowserMainParts);
};
......
// 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 "android_webview/browser/aw_metrics_service_client.h"
#include "base/base_switches.h"
#include "base/feature_list.h"
#include "base/path_service.h"
#include "base/strings/string_split.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 "content/public/common/content_switches.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() {
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 metrics::SHA1EntropyProvider(
// Synchronous read of the client id is permitted as it is fast
// enough to have minimal impact on startup time, and is behind the
// webview-enable-finch flag.
android_webview::AwMetricsServiceClient::GetOrCreateClientId()));
}
// Synchronous read of variations data is permitted as it is fast
// enough to have minimal impact on startup time, and is behind the
// webview-enable-finch flag.
bool ReadVariationsSeedDataFromFile(PrefService* local_state) {
// TODO(kmilka): The data read is being moved to java and the data will be
// passed in via JNI.
return false;
}
} // anonymous namespace
AwFieldTrialCreator::AwFieldTrialCreator()
: aw_field_trials_(base::MakeUnique<AwFieldTrials>()) {}
AwFieldTrialCreator::~AwFieldTrialCreator() {}
std::unique_ptr<PrefService> AwFieldTrialCreator::CreateLocalState() {
scoped_refptr<PrefRegistrySimple> pref_registry =
base::MakeRefCounted<PrefRegistrySimple>();
// Register the variations prefs with default values that must be overridden.
pref_registry->RegisterInt64Pref(variations::prefs::kVariationsSeedDate, 0);
pref_registry->RegisterInt64Pref(variations::prefs::kVariationsLastFetchTime,
0);
pref_registry->RegisterStringPref(variations::prefs::kVariationsCountry,
std::string());
pref_registry->RegisterStringPref(
variations::prefs::kVariationsCompressedSeed, std::string());
pref_registry->RegisterStringPref(variations::prefs::kVariationsSeedSignature,
std::string());
pref_registry->RegisterListPref(
variations::prefs::kVariationsPermanentConsistencyCountry,
base::MakeUnique<base::ListValue>());
pref_service_factory_.set_user_prefs(
make_scoped_refptr(new InMemoryPrefStore()));
return pref_service_factory_.Create(pref_registry.get());
}
void AwFieldTrialCreator::SetUpFieldTrials() {
if (!AwMetricsServiceClient::CheckSDKVersionForMetrics())
return;
DCHECK(!field_trial_list_);
// Set the FieldTrialList singleton.
field_trial_list_ =
base::MakeUnique<base::FieldTrialList>(CreateLowEntropyProvider());
std::unique_ptr<PrefService> local_state = CreateLocalState();
if (!ReadVariationsSeedDataFromFile(local_state.get()))
return;
variations::UIStringOverrider ui_string_overrider;
client_ = base::MakeUnique<AwVariationsServiceClient>();
variations_field_trial_creator_ =
base::MakeUnique<variations::VariationsFieldTrialCreator>(
local_state.get(), client_.get(), ui_string_overrider);
variations_field_trial_creator_->OverrideVariationsPlatform(
variations::Study::PLATFORM_ANDROID_WEBVIEW);
// Unused by WebView, but required by
// VariationsFieldTrialCreator::SetupFieldTrials().
std::vector<std::string> variation_ids;
std::set<std::string> unforceable_field_trials;
// Populates the FieldTrialList singleton via the static member functions.
variations_field_trial_creator_->SetupFieldTrials(
cc::switches::kEnableGpuBenchmarking, switches::kEnableFeatures,
switches::kDisableFeatures, unforceable_field_trials,
CreateLowEntropyProvider(), base::MakeUnique<base::FeatureList>(),
&variation_ids, aw_field_trials_.get());
}
} // namespace android_webview
// 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.
#ifndef ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIAL_CREATOR_H_
#define ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIAL_CREATOR_H_
#include "android_webview/browser/aw_field_trials.h"
#include "android_webview/browser/aw_variations_service_client.h"
#include "base/metrics/field_trial.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "components/variations/service/variations_field_trial_creator.h"
namespace android_webview {
// Used by WebView to set up field trials based on the stored variations
// seed data. Once created this object must exist for the lifetime of the
// process as it contains the FieldTrialList that can be queried for the state
// of experiments.
class AwFieldTrialCreator {
public:
AwFieldTrialCreator();
~AwFieldTrialCreator();
// Creates the PrefService object that stores the variations prefs needed by
// VariationsFieldTrialCreator.
std::unique_ptr<PrefService> CreateLocalState();
// Sets up the field trials and related initialization.
void SetUpFieldTrials();
private:
// A/B testing infrastructure for the entire application. empty until
// |SetupFieldTrials()| is called.
std::unique_ptr<base::FieldTrialList> field_trial_list_;
// Performs set up for any WebView specific field trials.
std::unique_ptr<AwFieldTrials> aw_field_trials_;
// Responsible for creating a feature list from the seed.
std::unique_ptr<variations::VariationsFieldTrialCreator>
variations_field_trial_creator_;
std::unique_ptr<AwVariationsServiceClient> client_;
// Used to create a PrefService for variations prefs.
PrefServiceFactory pref_service_factory_;
DISALLOW_COPY_AND_ASSIGN(AwFieldTrialCreator);
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIAL_CREATOR_H_
// 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.
#ifndef ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIALS_H_
#define ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIALS_H_
#include "base/macros.h"
#include "components/variations/platform_field_trials.h"
// Responsible for setting up field trials specific to WebView. Currently all
// functions are stubs, as WebView has no specific field trials.
class AwFieldTrials : public variations::PlatformFieldTrials {
public:
AwFieldTrials() {}
~AwFieldTrials() override {}
// variations::PlatformFieldTrials:
void SetupFieldTrials() override {}
void SetupFeatureControllingFieldTrials(
bool has_seed,
base::FeatureList* feature_list) override {}
private:
DISALLOW_COPY_AND_ASSIGN(AwFieldTrials);
};
#endif // ANDROID_WEBVIEW_BROWSER_AW_FIELD_TRIALS_H_
......@@ -46,8 +46,7 @@ const int kUploadIntervalMinutes = 30;
const size_t GUID_SIZE = 32 + 4;
// Client ID of the app, read and cached synchronously at startup
base::LazyInstance<std::string>::Leaky g_client_id_guid =
LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<std::string>::Leaky g_client_id = LAZY_INSTANCE_INITIALIZER;
// Callbacks for metrics::MetricsStateManager::Create. Store/LoadClientInfo
// allow Windows Chrome to back up ClientInfo. They're no-ops for WebView.
......@@ -76,10 +75,15 @@ AwMetricsServiceClient* AwMetricsServiceClient::GetInstance() {
return g_lazy_instance_.Pointer();
}
void AwMetricsServiceClient::GetOrCreateGUID() {
// Check for cached GUID
if (g_client_id_guid.Get().length() == GUID_SIZE)
return;
bool AwMetricsServiceClient::CheckSDKVersionForMetrics() {
// For now, UMA is only enabled on Android N+.
return base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_NOUGAT;
}
std::string AwMetricsServiceClient::GetOrCreateClientId() {
// This function should only be called once at start up.
DCHECK_NE(g_client_id.Get().length(), GUID_SIZE);
// UMA uses randomly-generated GUIDs (globally unique identifiers) to
// anonymously identify logs. Every WebView-using app on every device
......@@ -89,29 +93,31 @@ void AwMetricsServiceClient::GetOrCreateGUID() {
LOG(ERROR) << "Failed to get app data directory for Android WebView";
// Generate a 1-time GUID so metrics can still be collected
g_client_id_guid.Get() = base::GenerateGUID();
return;
g_client_id.Get() = base::GenerateGUID();
return g_client_id.Get();
}
const base::FilePath guid_file_path =
user_data_dir.Append(FILE_PATH_LITERAL("metrics_guid"));
// Try to read an existing GUID.
if (base::ReadFileToStringWithMaxSize(guid_file_path, &g_client_id_guid.Get(),
if (base::ReadFileToStringWithMaxSize(guid_file_path, &g_client_id.Get(),
GUID_SIZE)) {
if (base::IsValidGUID(g_client_id_guid.Get()))
return;
if (base::IsValidGUID(g_client_id.Get()))
return g_client_id.Get();
LOG(ERROR) << "Overwriting invalid GUID";
}
// We must write a new GUID.
g_client_id_guid.Get() = base::GenerateGUID();
if (!base::WriteFile(guid_file_path, g_client_id_guid.Get().c_str(),
g_client_id_guid.Get().size())) {
g_client_id.Get() = base::GenerateGUID();
if (!base::WriteFile(guid_file_path, g_client_id.Get().c_str(),
g_client_id.Get().size())) {
// If writing fails, proceed anyway with the new GUID. It won't be persisted
// to the next run, but we can still collect metrics with this 1-time GUID.
LOG(ERROR) << "Failed to write new GUID";
}
return g_client_id.Get();
}
void AwMetricsServiceClient::Initialize(
......@@ -129,23 +135,22 @@ void AwMetricsServiceClient::Initialize(
// at startup
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebViewVariations)) {
InitializeWithGUID();
InitializeWithClientId();
} else {
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::FILE, FROM_HERE,
base::Bind(&AwMetricsServiceClient::GetOrCreateGUID),
base::Bind(&AwMetricsServiceClient::InitializeWithGUID,
base::Bind(
base::IgnoreResult(&AwMetricsServiceClient::GetOrCreateClientId)),
base::Bind(&AwMetricsServiceClient::InitializeWithClientId,
base::Unretained(this)));
}
}
void AwMetricsServiceClient::InitializeWithGUID() {
void AwMetricsServiceClient::InitializeWithClientId() {
// The guid must have already been initialized at this point, either
// synchronously or asynchronously depending on the kEnableWebViewVariations
// flag
DCHECK_EQ(g_client_id_guid.Get().length(), GUID_SIZE);
pref_service_->SetString(metrics::prefs::kMetricsClientID,
g_client_id_guid.Get());
// synchronously or asynchronously depending on the kEnableWebViewFinch flag
DCHECK_EQ(g_client_id.Get().length(), GUID_SIZE);
pref_service_->SetString(metrics::prefs::kMetricsClientID, g_client_id.Get());
metrics_state_manager_ = metrics::MetricsStateManager::Create(
pref_service_, this, base::string16(), base::Bind(&StoreClientInfo),
......@@ -188,11 +193,8 @@ bool AwMetricsServiceClient::IsConsentGiven() {
void AwMetricsServiceClient::SetMetricsEnabled(bool enabled) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// For now, UMA is only enabled on Android N+.
if (base::android::BuildInfo::GetInstance()->sdk_int() <
base::android::SDK_VERSION_NOUGAT) {
if (!CheckSDKVersionForMetrics())
return;
}
if (is_enabled_ != enabled) {
if (enabled) {
......
......@@ -44,8 +44,11 @@ class AwMetricsServiceClient : public metrics::MetricsServiceClient,
public:
static AwMetricsServiceClient* GetInstance();
// Retrieve the client ID or generate one if none exists
static void GetOrCreateGUID();
// Return true if running on an sdk version metrics should be enabled for.
static bool CheckSDKVersionForMetrics();
// Retrieve the client ID or generate one if none exists.
static std::string GetOrCreateClientId();
void Initialize(PrefService* pref_service,
net::URLRequestContextGetter* request_context);
......@@ -79,7 +82,7 @@ class AwMetricsServiceClient : public metrics::MetricsServiceClient,
AwMetricsServiceClient();
~AwMetricsServiceClient() override;
void InitializeWithGUID();
void InitializeWithClientId();
bool is_enabled_;
PrefService* pref_service_;
......
// 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_variations_service_client.h"
#include "base/bind.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/version_info/version_info.h"
namespace android_webview {
namespace {
// Gets the version number to use for variations seed simulation. Must be called
// on a thread where IO is allowed.
base::Version GetVersionForSimulation() {
base::ThreadRestrictions::AssertIOAllowed();
return base::Version(version_info::GetVersionNumber());
}
} // namespace
AwVariationsServiceClient::AwVariationsServiceClient() {}
AwVariationsServiceClient::~AwVariationsServiceClient() {}
std::string AwVariationsServiceClient::GetApplicationLocale() {
return std::string();
}
base::Callback<base::Version(void)>
AwVariationsServiceClient::GetVersionForSimulationCallback() {
return base::Bind(&GetVersionForSimulation);
}
net::URLRequestContextGetter*
AwVariationsServiceClient::GetURLRequestContext() {
return nullptr;
}
network_time::NetworkTimeTracker*
AwVariationsServiceClient::GetNetworkTimeTracker() {
return nullptr;
}
version_info::Channel AwVariationsServiceClient::GetChannel() {
// TODO(kmilka): Investigate the proper value to return here so experiments
// are correctly filtered.
return version_info::Channel::UNKNOWN;
}
bool AwVariationsServiceClient::OverridesRestrictParameter(
std::string* parameter) {
return false;
}
} // namespace android_webview
// 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.
#ifndef ANDROID_WEBVIEW_BROWSER_AW_VARIATIONS_SERVICE_CLIENT_H_
#define ANDROID_WEBVIEW_BROWSER_AW_VARIATIONS_SERVICE_CLIENT_H_
#include <string>
#include "base/macros.h"
#include "components/variations/service/variations_service_client.h"
namespace android_webview {
// AwVariationsServiceClient provides an implementation of
// VariationsServiceClient, all members are currently stubs for WebView.
class AwVariationsServiceClient : public variations::VariationsServiceClient {
public:
AwVariationsServiceClient();
~AwVariationsServiceClient() override;
private:
std::string GetApplicationLocale() override;
base::Callback<base::Version(void)> GetVersionForSimulationCallback()
override;
net::URLRequestContextGetter* GetURLRequestContext() override;
network_time::NetworkTimeTracker* GetNetworkTimeTracker() override;
version_info::Channel GetChannel() override;
bool OverridesRestrictParameter(std::string* parameter) override;
DISALLOW_COPY_AND_ASSIGN(AwVariationsServiceClient);
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_AW_VARIATIONS_SERVICE_CLIENT_H_
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment