Skip to content

Commit

Permalink
Hard coded UIRefreshPhase1 field trial for first run
Browse files Browse the repository at this point in the history
Bug: 831971

Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: Id656f7fec7577080116e01c5883d9cbf21fd4ce8
Reviewed-on: https://chromium-review.googlesource.com/1128269
Commit-Queue: Peter Lee <[email protected]>
Reviewed-by: Alexei Svitkine <[email protected]>
Cr-Commit-Position: refs/heads/master@{#576960}
  • Loading branch information
Peter K. Lee authored and Commit Bot committed Jul 20, 2018
1 parent c23db9c commit 0d313e2
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 1 deletion.
3 changes: 3 additions & 0 deletions ios/chrome/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,14 @@ source_set("browser") {
"install_time_util.mm",
"installation_notifier.h",
"installation_notifier.mm",
"ios_chrome_field_trials.cc",
"ios_chrome_field_trials.h",
"ios_chrome_flag_descriptions.cc",
"ios_chrome_flag_descriptions.h",
"ios_chrome_io_thread.h",
"ios_chrome_io_thread.mm",
"ios_first_run_field_trials.cc",
"ios_first_run_field_trials.h",
"notification_promo.cc",
"notification_promo.h",
"pref_names.cc",
Expand Down
105 changes: 105 additions & 0 deletions ios/chrome/browser/ios_chrome_field_trials.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2018 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 "ios/chrome/browser/ios_chrome_field_trials.h"

#include <string>
#include <vector>

#include "base/metrics/field_trial.h"
#include "components/variations/variations_associated_data.h"
#include "components/version_info/version_info.h"
#include "ios/chrome/browser/ios_first_run_field_trials.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
#include "ios/chrome/common/channel_info.h"

namespace {

// Probabilities for all field trial groups add up to kTotalProbability.
const base::FieldTrial::Probability kTotalProbability = 100;

// Each field trial has 3 trial groups.
// Default - Majority of users will be in default group which receive the
// default UI. In the case of UI Refresh rollout, this will be the new UI.
// Old UI - A small percentage of users will be held back in the old UI for
// so usage metrics differences between users with old UI can be compared
// against users with new UI.
// New UI - Same sized group as Old UI for comparison.
const char kDefaultGroup[] = "NewUIRollout";
const char kOldUIControlGroup[] = "OldUIControl";
const char kNewUIExperimentGroup[] = "NewUIExperiment";
// Experiment IDs defined for the above field trial groups.
const variations::VariationID kDefaultTrialID = 3314527;
const variations::VariationID kOldUIControlTrialID = 3314528;
const variations::VariationID kNewUIExperimentTrialID = 3314529;

// Returns the percentage of users who are to be held back in "old" UI. The
// same percentage will be placed in a separate experiment group, but shown
// the "new" UI such that there will be two equal sized groups for comparing
// user behavior under "old" and "new" UI. Field trial configuration depends
// on release channel.
base::FieldTrial::Probability UIRefreshHoldbackPercent(
version_info::Channel channel) {
switch (channel) {
// Stable Channel has 3% of users held back with Old UI.
case version_info::Channel::STABLE:
case version_info::Channel::UNKNOWN: // Same as DEFAULT
return 3;
// Beta Channel is 50/50 split between Old UI and New UI.
case version_info::Channel::BETA:
return 50;
// Canary and Dev is 100% rolled out with New UI.
case version_info::Channel::CANARY:
case version_info::Channel::DEV:
return 0;
}
}

// Field trials do not take effect until configurations have been downloaded.
// In order for field trials involving substantial UI changes to take effect
// at first run, the configuration must be pre-defined in client code. This
// sets up the field trial for UI Refresh.
void SetupUIRefreshFieldTrial(base::FeatureList* feature_list) {
// Field trial configuration pre-defined here for UI Refresh should match the
// configuration stored on the servers. Server-stored configuration will
// override this pre-defined configuration.
base::FieldTrial::Probability holdback =
UIRefreshHoldbackPercent(GetChannel());
FirstRunFieldTrialConfig config("IOSUIRefreshRolloutWithHoldback");
config.AddGroup(kDefaultGroup, kDefaultTrialID,
kTotalProbability - 2 * holdback);
config.AddGroup(kOldUIControlGroup, kOldUIControlTrialID, holdback);
config.AddGroup(kNewUIExperimentGroup, kNewUIExperimentTrialID, holdback);

scoped_refptr<base::FieldTrial> trial(
base::FieldTrialList::FactoryGetFieldTrial(
config.trial_name(), kTotalProbability, kDefaultGroup,
config.expire_year(), config.expire_month(),
config.expire_day_of_month(), base::FieldTrial::ONE_TIME_RANDOMIZED,
/*default_group_number=*/nullptr));
for (const auto& group : config.groups()) {
variations::AssociateGoogleVariationID(variations::GOOGLE_WEB_PROPERTIES,
config.trial_name(), group.name(),
group.variation());
trial->AppendGroup(group.name(), group.percentage());
}

// Tests which group this user has been assigned to. Based on the group,
// sets the UI Refresh Phase 1 feature flag.
const std::string& chosen_group_name = trial->GetGroupNameWithoutActivation();
base::FeatureList::OverrideState feature_state =
chosen_group_name == kOldUIControlGroup
? base::FeatureList::OVERRIDE_DISABLE_FEATURE
: base::FeatureList::OVERRIDE_ENABLE_FEATURE;
feature_list->RegisterFieldTrialOverride(kUIRefreshPhase1.name, feature_state,
trial.get());
}

} // namespace

void IOSChromeFieldTrials::SetupFeatureControllingFieldTrials(
bool has_seed,
base::FeatureList* feature_list) {
SetupUIRefreshFieldTrial(feature_list);
}
2 changes: 1 addition & 1 deletion ios/chrome/browser/ios_chrome_field_trials.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class IOSChromeFieldTrials : public variations::PlatformFieldTrials {
void SetupFieldTrials() override {}
void SetupFeatureControllingFieldTrials(
bool has_seed,
base::FeatureList* feature_list) override {}
base::FeatureList* feature_list) override;

private:
DISALLOW_COPY_AND_ASSIGN(IOSChromeFieldTrials);
Expand Down
41 changes: 41 additions & 0 deletions ios/chrome/browser/ios_first_run_field_trials.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018 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 "ios/chrome/browser/ios_first_run_field_trials.h"

// FirstRunFieldTrialGroup
FirstRunFieldTrialGroup::FirstRunFieldTrialGroup(
const std::string& name,
variations::VariationID variation,
base::FieldTrial::Probability percentage)
: name_(name), variation_(variation), percentage_(percentage) {}

FirstRunFieldTrialGroup::~FirstRunFieldTrialGroup() {}

// FirstRunFieldTrialConfig
FirstRunFieldTrialConfig::FirstRunFieldTrialConfig(
const std::string& trial_name)
: FirstRunFieldTrialConfig(trial_name,
base::FieldTrialList::kNoExpirationYear,
1,
1) {}

FirstRunFieldTrialConfig::FirstRunFieldTrialConfig(
const std::string& trial_name,
int year,
int month,
int day_of_month)
: trial_name_(trial_name),
expire_year_(year),
expire_month_(month),
expire_day_of_month_(day_of_month) {}

FirstRunFieldTrialConfig::~FirstRunFieldTrialConfig() {}

void FirstRunFieldTrialConfig::AddGroup(
const std::string& name,
variations::VariationID variation,
base::FieldTrial::Probability percentage) {
groups_.emplace_back(name, variation, percentage);
}
75 changes: 75 additions & 0 deletions ios/chrome/browser/ios_first_run_field_trials.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2018 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 IOS_CHROME_BROWSER_IOS_FIRST_RUN_FIELD_TRIALS_H_
#define IOS_CHROME_BROWSER_IOS_FIRST_RUN_FIELD_TRIALS_H_

#include <string>
#include <vector>

#include "base/metrics/field_trial.h"
#include "components/variations/variations_associated_data.h"

// Helper class defining a FieldTrial group.
class FirstRunFieldTrialGroup {
public:
FirstRunFieldTrialGroup(const std::string& name,
variations::VariationID variation,
base::FieldTrial::Probability percentage);
~FirstRunFieldTrialGroup();

// Accessors for this FieldTrial group.
const std::string& name() const { return name_; }
variations::VariationID variation() const { return variation_; }
base::FieldTrial::Probability percentage() const { return percentage_; }

private:
std::string name_;
variations::VariationID variation_;
base::FieldTrial::Probability percentage_;
};

// Helper class defining a FieldTrial configuration that will be valid at the
// time of Chrome First Run. Since server-provided FieldTrial configurations
// that need to be downloaded will not take effect until at least the second
// run, FieldTrials involving substantial UI changes that need to take effect
// at first run must be pre-defined in client code.
class FirstRunFieldTrialConfig {
public:
// Initializes with |trial_name| as the name of the FieldTrial with default
// duration.
FirstRunFieldTrialConfig(const std::string& trial_name);
// Initializes with |trial_name| as the name of the FieldTrial and one that
// ends on (year, month, day_of_month).
FirstRunFieldTrialConfig(const std::string& trial_name,
int year,
int month,
int day_of_month);
~FirstRunFieldTrialConfig();

// Adds a new FieldTrial group of |name| with a probability of |percentage|.
// |variation| defines a server-side variation configuration.
void AddGroup(const std::string& name,
variations::VariationID variation,
base::FieldTrial::Probability percentage);

// Returns a vector of FieldTrial groups for this FieldTrial configuration.
const std::vector<FirstRunFieldTrialGroup>& groups() const { return groups_; }
// Accessors for this FieldTrial.
const std::string& trial_name() { return trial_name_; }
int expire_year() { return expire_year_; }
int expire_month() { return expire_month_; }
int expire_day_of_month() { return expire_day_of_month_; }

private:
std::string trial_name_;
std::vector<FirstRunFieldTrialGroup> groups_;
int expire_year_;
int expire_month_;
int expire_day_of_month_;

DISALLOW_COPY_AND_ASSIGN(FirstRunFieldTrialConfig);
};

#endif // IOS_CHROME_BROWSER_IOS_FIRST_RUN_FIELD_TRIALS_H_

0 comments on commit 0d313e2

Please sign in to comment.