| Index: chrome/installer/util/google_chrome_distribution.cc
|
| ===================================================================
|
| --- chrome/installer/util/google_chrome_distribution.cc (revision 149057)
|
| +++ chrome/installer/util/google_chrome_distribution.cc (working copy)
|
| @@ -60,14 +60,15 @@
|
|
|
| // The following strings are the possible outcomes of the toast experiment
|
| // as recorded in the |client| field.
|
| -const wchar_t kToastExpControlGroup[] = L"01";
|
| -const wchar_t kToastExpCancelGroup[] = L"02";
|
| -const wchar_t kToastExpUninstallGroup[] = L"04";
|
| -const wchar_t kToastExpTriesOkGroup[] = L"18";
|
| -const wchar_t kToastExpTriesErrorGroup[] = L"28";
|
| -const wchar_t kToastActiveGroup[] = L"40";
|
| -const wchar_t kToastUDDirFailure[] = L"40";
|
| -const wchar_t kToastExpBaseGroup[] = L"80";
|
| +const wchar_t kToastExpControlGroup[] = L"01";
|
| +const wchar_t kToastExpCancelGroup[] = L"02";
|
| +const wchar_t kToastExpUninstallGroup[] = L"04";
|
| +const wchar_t kToastExpTriesOkGroup[] = L"18";
|
| +const wchar_t kToastExpTriesErrorGroup[] = L"28";
|
| +const wchar_t kToastExpTriesOkDefaultGroup[] = L"48";
|
| +const wchar_t kToastActiveGroup[] = L"40";
|
| +const wchar_t kToastUDDirFailure[] = L"40";
|
| +const wchar_t kToastExpBaseGroup[] = L"80";
|
|
|
| // Substitute the locale parameter in uninstall URL with whatever
|
| // Google Update tells us is the locale. In case we fail to find
|
| @@ -612,6 +613,10 @@
|
|
|
| bool GoogleChromeDistribution::GetExperimentDetails(
|
| UserExperiment* experiment, int flavor) {
|
| + struct FlavorDetails {
|
| + int heading_id;
|
| + int flags;
|
| + };
|
| // Maximum number of experiment flavors we support.
|
| static const int kMax = 4;
|
| // This struct determines which experiment flavors we show for each locale and
|
| @@ -624,29 +629,37 @@
|
| // The big experiment in Feb 2011 used SJxx SKxx SLxx SMxx.
|
| // Note: the plugin infobar experiment uses PIxx codes.
|
| using namespace attrition_experiments;
|
| +
|
| static const struct UserExperimentDetails {
|
| const wchar_t* locale; // Locale to show this experiment for (* for all).
|
| const wchar_t* brands; // Brand codes show this experiment for (* for all).
|
| int control_group; // Size of the control group, in percentages.
|
| - const wchar_t prefix1; // The first letter for the experiment code.
|
| - const wchar_t prefix2; // The second letter for the experiment code. This
|
| - // will be incremented by one for each additional
|
| - // experiment flavor beyond the first.
|
| - int flavors; // Numbers of flavors for this experiment. Should
|
| - // always be positive and never exceed the number
|
| - // of headings (below).
|
| - int headings[kMax]; // A list of IDs per experiment. 0 == no heading.
|
| - } kExperimentFlavors[] = {
|
| - // This list should be ordered most-specific rule first (catch-all, like all
|
| - // brands or all locales should be last).
|
| -
|
| - // The experiment with the more compact bubble. This one is a bit special
|
| - // because it is split into two: CAxx is regular style bubble and CBxx is
|
| - // compact style bubble. See |compact_bubble| below.
|
| - {L"en-US", kBrief, 1, L'C', L'A', 2, { kEnUs3, kEnUs3, 0, 0 } },
|
| -
|
| - // Catch-all rules.
|
| - {kAll, kAll, 1, L'B', L'A', 1, {kEnUs3, 0, 0, 0} },
|
| + const wchar_t* prefix; // The two letter experiment code. The second letter
|
| + // will be incremented with the flavor.
|
| + FlavorDetails flavors[kMax];
|
| + } kExperiments[] = {
|
| + // The first match from top to bottom is used so this list should be ordered
|
| + // most-specific rule first.
|
| + { L"*", L"CHMA", // All locales, CHMA brand.
|
| + 25, // 25 percent control group.
|
| + L"ZA", // Experiment is ZAxx, ZBxx, ZCxx, ZDxx etc.
|
| + // Three flavors.
|
| + { { IDS_TRY_TOAST_HEADING3, kDontBugMeAsButton | kUninstall | kWhyLink },
|
| + { IDS_TRY_TOAST_HEADING3, 0 },
|
| + { IDS_TRY_TOAST_HEADING3, kMakeDefault },
|
| + { 0, 0 },
|
| + }
|
| + },
|
| + { L"*", L"GGRV", // All locales, GGRV is enterprise.
|
| + 0, // 0 percent control group.
|
| + L"EA", // Experiment is EAxx, EBxx, etc.
|
| + // No flavors means no experiment.
|
| + { { 0, 0 },
|
| + { 0, 0 },
|
| + { 0, 0 },
|
| + { 0, 0 }
|
| + }
|
| + }
|
| };
|
|
|
| string16 locale;
|
| @@ -657,50 +670,36 @@
|
| string16 brand;
|
| if (!GoogleUpdateSettings::GetBrand(&brand))
|
| brand = ASCIIToWide(""); // Could still be viable for catch-all rules.
|
| - if (brand == kEnterprise)
|
| - return false;
|
|
|
| - for (int i = 0; i < arraysize(kExperimentFlavors); ++i) {
|
| - // A maximum of four flavors are supported at the moment.
|
| - CHECK_LE(kExperimentFlavors[i].flavors, kMax);
|
| - CHECK_GT(kExperimentFlavors[i].flavors, 0);
|
| - // Make sure each experiment has valid headings.
|
| - for (int f = 0; f < kMax; ++f) {
|
| - if (f < kExperimentFlavors[i].flavors) {
|
| - CHECK_GT(kExperimentFlavors[i].headings[f], 0);
|
| - } else {
|
| - CHECK_EQ(kExperimentFlavors[i].headings[f], 0);
|
| - }
|
| - }
|
| - // The prefix has to be a valid two letter combo.
|
| - CHECK(kExperimentFlavors[i].prefix1 >= 'A');
|
| - CHECK(kExperimentFlavors[i].prefix2 >= 'A');
|
| - CHECK(kExperimentFlavors[i].prefix2 +
|
| - kExperimentFlavors[i].flavors - 1 <= 'Z');
|
| -
|
| - if (kExperimentFlavors[i].locale != locale &&
|
| - kExperimentFlavors[i].locale != ASCIIToWide("*"))
|
| + for (int i = 0; i < arraysize(kExperiments); ++i) {
|
| + if (kExperiments[i].locale != locale &&
|
| + kExperiments[i].locale != ASCIIToWide("*"))
|
| continue;
|
|
|
| std::vector<string16> brand_codes;
|
| - base::SplitString(kExperimentFlavors[i].brands, L',', &brand_codes);
|
| + base::SplitString(kExperiments[i].brands, L',', &brand_codes);
|
| if (brand_codes.empty())
|
| return false;
|
| for (std::vector<string16>::iterator it = brand_codes.begin();
|
| it != brand_codes.end(); ++it) {
|
| if (*it != brand && *it != L"*")
|
| continue;
|
| + // We have found our match.
|
| + const UserExperimentDetails& match = kExperiments[i];
|
| + // Find out how many flavors we have. Zero means no experiment.
|
| + int num_flavors = 0;
|
| + while (match.flavors[num_flavors].heading_id) { ++num_flavors; }
|
| + if (!num_flavors)
|
| + return false;
|
|
|
| - // We have found our match.
|
| if (flavor < 0)
|
| - flavor = base::RandInt(0, kExperimentFlavors[i].flavors - 1);
|
| + flavor = base::RandInt(0, num_flavors - 1);
|
| experiment->flavor = flavor;
|
| - experiment->heading = kExperimentFlavors[i].headings[flavor];
|
| - experiment->control_group = kExperimentFlavors[i].control_group;
|
| - experiment->prefix.resize(2);
|
| - experiment->prefix[0] = kExperimentFlavors[i].prefix1;
|
| - experiment->prefix[1] = kExperimentFlavors[i].prefix2 + flavor;
|
| - experiment->compact_bubble = (brand == kBrief) && (flavor == 1);
|
| + experiment->heading = match.flavors[flavor].heading_id;
|
| + experiment->control_group = match.control_group;
|
| + const wchar_t prefix[] = { match.prefix[0], match.prefix[1] + flavor, 0 };
|
| + experiment->prefix = prefix;
|
| + experiment->flags = match.flavors[flavor].flags;
|
| return true;
|
| }
|
| }
|
| @@ -853,6 +852,16 @@
|
| outcome = kToastExpTriesErrorGroup;
|
| };
|
|
|
| + if (outcome == kToastExpTriesOkGroup) {
|
| + // User tried chrome, but if it had the default group button it belongs
|
| + // to a different outcome group.
|
| + UserExperiment experiment;
|
| + if (GetExperimentDetails(&experiment, flavor)) {
|
| + outcome = experiment.flags & kMakeDefault ? kToastExpTriesOkDefaultGroup :
|
| + kToastExpTriesOkGroup;
|
| + }
|
| + }
|
| +
|
| // Write to the |client| key for the last time.
|
| SetClient(experiment_group + outcome, true);
|
|
|
|
|