summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/chromium_strings.grd3
-rw-r--r--chrome/app/google_chrome_strings.grd3
-rw-r--r--chrome/browser/first_run/first_run_win.cc26
-rw-r--r--chrome/chrome_common.gypi1
-rw-r--r--chrome/common/attrition_experiments.h31
-rw-r--r--chrome/installer/setup/setup_main.cc8
-rw-r--r--chrome/installer/util/browser_distribution.cc6
-rw-r--r--chrome/installer/util/browser_distribution.h29
-rw-r--r--chrome/installer/util/chrome_frame_distribution.h34
-rw-r--r--chrome/installer/util/chromium_binaries_distribution.h36
-rw-r--r--chrome/installer/util/google_chrome_distribution.cc183
-rw-r--r--chrome/installer/util/google_chrome_distribution.h56
-rw-r--r--chrome/installer/util/google_chrome_distribution_dummy.cc7
-rw-r--r--chrome/installer/util/util_constants.cc3
-rw-r--r--chrome/installer/util/util_constants.h3
15 files changed, 295 insertions, 134 deletions
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 2729f0b..d304a72 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -474,6 +474,9 @@ be available for now. -->
<message name="IDS_TRY_TOAST_HEADING4" desc="Top line of the try-chrome-again dialog">
Chromium has been updated, but you haven't used it for at least 30 days.
</message>
+ <message name="IDS_TRY_TOAST_HEADING_SKYPE" desc="Top line of the try-chrome-again dialog">
+ Chromium lets you click a phone number on the web and call it with Skype!
+ </message>
<message name="IDS_TRY_TOAST_TRY_OPT" desc="First option radio button on the dialog to try chrome">
Try it out (already installed)
</message>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index de3b6c0..717d958 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -480,6 +480,9 @@ Chrome supports. -->
<message name="IDS_TRY_TOAST_HEADING4" desc="Top line of the try-chrome-again dialog">
Google Chrome has been updated, but you haven't used it for at least 30 days.
</message>
+ <message name="IDS_TRY_TOAST_HEADING_SKYPE" desc="Top line of the try-chrome-again dialog">
+ Google Chrome lets you click a phone number on the web and call it with Skype!
+ </message>
<message name="IDS_TRY_TOAST_TRY_OPT" desc="First option radio button on the dialog to try chrome">
Try it out (already installed)
</message>
diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc
index db6d03b..8e8628f 100644
--- a/chrome/browser/first_run/first_run_win.cc
+++ b/chrome/browser/first_run/first_run_win.cc
@@ -660,20 +660,20 @@ class TryChromeDialog : public views::ButtonListener,
// First row views.
layout->StartRow(0, 0);
layout->AddView(icon);
- // The heading has two flavors of text, the alt one features extensions but
- // we only use it in the US until some international issues are fixed.
- const std::string app_locale = g_browser_process->GetApplicationLocale();
- int heading_id;
- switch (version_) {
- case 0: heading_id = IDS_TRY_TOAST_HEADING; break;
- case 1: heading_id = IDS_TRY_TOAST_HEADING2; break;
- case 2: heading_id = IDS_TRY_TOAST_HEADING3; break;
- case 3: heading_id = IDS_TRY_TOAST_HEADING4; break;
- default:
- NOTREACHED() << "Cannot determine which headline to show.";
- return Upgrade::TD_DIALOG_ERROR;
+
+ // Find out what experiment we are conducting.
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ if (!dist) {
+ NOTREACHED() << "Cannot determine browser distribution";
+ return Upgrade::TD_DIALOG_ERROR;
+ }
+ BrowserDistribution::UserExperiment experiment;
+ if (!dist->GetExperimentDetails(&experiment, version_) ||
+ !experiment.heading) {
+ NOTREACHED() << "Cannot determine which headline to show.";
+ return Upgrade::TD_DIALOG_ERROR;
}
- string16 heading = l10n_util::GetStringUTF16(heading_id);
+ string16 heading = l10n_util::GetStringUTF16(experiment.heading);
views::Label* label = new views::Label(heading);
label->SetFont(rb.GetFont(ResourceBundle::MediumBoldFont));
label->SetMultiLine(true);
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 84b38e3..4e7dd6b 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -27,6 +27,7 @@
'common/about_handler.h',
'common/app_mode_common_mac.h',
'common/app_mode_common_mac.mm',
+ 'common/attrition_experiments.h',
'common/auto_start_linux.cc',
'common/auto_start_linux.h',
'common/autofill_messages.h',
diff --git a/chrome/common/attrition_experiments.h b/chrome/common/attrition_experiments.h
new file mode 100644
index 0000000..7595588
--- /dev/null
+++ b/chrome/common/attrition_experiments.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 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 CHROME_COMMON_ATTRITION_EXPERIMENTS_H_
+#define CHROME_COMMON_ATTRITION_EXPERIMENTS_H_
+#pragma once
+
+#include "grit/chromium_strings.h"
+
+namespace attrition_experiments {
+
+// A list of all the IDs we use for the attrition experiments.
+enum Experiment {
+ kEnUs1 = IDS_TRY_TOAST_HEADING,
+ kEnUs2 = IDS_TRY_TOAST_HEADING2,
+ kEnUs3 = IDS_TRY_TOAST_HEADING3,
+ kEnUs4 = IDS_TRY_TOAST_HEADING4,
+ kSkype1 = IDS_TRY_TOAST_HEADING_SKYPE,
+};
+
+// This is used to match against locale and brands, and represents any
+// locale/brand.
+const wchar_t kAll[] = L"*";
+
+// A comma-separated list of brand codes that are associated with Skype.
+const wchar_t kSkype[] = L"SKPC,SKPG,SKPH,SKPI,SKPL,SKPM,SKPN";
+
+} // namespace
+
+#endif // CHROME_COMMON_ATTRITION_EXPERIMENTS_H_
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index f773614..b5dcbc0 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -637,6 +637,7 @@ installer::InstallStatus InstallProductsHelper(
}
}
}
+
// There might be an experiment (for upgrade usually) that needs to happen.
// An experiment's outcome can include chrome's uninstallation. If that is
// the case we would not do that directly at this point but in another
@@ -882,6 +883,8 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
int flavor = -1;
base::StringToInt(cmd_line.GetSwitchValueNative(
installer::switches::kInactiveUserToast), &flavor);
+ std::string experiment_group =
+ cmd_line.GetSwitchValueASCII(installer::switches::kExperimentGroup);
DCHECK_NE(-1, flavor);
if (flavor == -1) {
*exit_code = installer::UNKNOWN_STATUS;
@@ -890,8 +893,9 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
BrowserDistribution* browser_dist = product->distribution();
- browser_dist->InactiveUserToastExperiment(flavor, *product,
- installer_state->target_path());
+ browser_dist->InactiveUserToastExperiment(flavor,
+ ASCIIToUTF16(experiment_group),
+ *product, installer_state->target_path());
}
}
} else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) {
diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc
index 95c0139..8a1ed71 100644
--- a/chrome/installer/util/browser_distribution.cc
+++ b/chrome/installer/util/browser_distribution.cc
@@ -220,6 +220,11 @@ void BrowserDistribution::UpdateInstallStatus(bool system_install,
installer::InstallStatus install_status) {
}
+bool BrowserDistribution::GetExperimentDetails(
+ UserExperiment* experiment, int flavor) {
+ return false;
+}
+
void BrowserDistribution::LaunchUserExperiment(
const FilePath& setup_path, installer::InstallStatus status,
const Version& version, const installer::Product& installation,
@@ -228,6 +233,7 @@ void BrowserDistribution::LaunchUserExperiment(
void BrowserDistribution::InactiveUserToastExperiment(int flavor,
+ const std::wstring& experiment_group,
const installer::Product& installation,
const FilePath& application_path) {
}
diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h
index c20888b..c766a8a 100644
--- a/chrome/installer/util/browser_distribution.h
+++ b/chrome/installer/util/browser_distribution.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
//
@@ -39,6 +39,19 @@ class BrowserDistribution {
NUM_TYPES
};
+ // A struct for communicating what a UserExperiment contains. In these
+ // experiments we show toasts to the user if they are inactive for a certain
+ // amount of time.
+ struct UserExperiment {
+ std::wstring prefix; // The experiment code prefix for this experiment,
+ // also known as the 'TV' part in 'TV80'.
+ int flavor; // The flavor index for this experiment.
+ int heading; // The heading resource ID to use for this experiment.
+ int control_group; // Size of the control group (in percentages). Control
+ // group is the group that qualifies for the
+ // experiment but does not participate.
+ };
+
static BrowserDistribution* GetDistribution();
static BrowserDistribution* GetSpecificDistribution(Type type);
@@ -95,17 +108,25 @@ class BrowserDistribution {
installer::ArchiveType archive_type,
installer::InstallStatus install_status);
+ // Gets the experiment details for a given language-brand combo. If |flavor|
+ // is -1, then a flavor will be selected at random. |experiment| is the struct
+ // you want to write the experiment information to. Returns false if no
+ // experiment details could be gathered.
+ virtual bool GetExperimentDetails(UserExperiment* experiment, int flavor);
+
// After an install or upgrade the user might qualify to participate in an
// experiment. This function determines if the user qualifies and if so it
// sets the wheels in motion or in simple cases does the experiment itself.
virtual void LaunchUserExperiment(const FilePath& setup_path,
- installer::InstallStatus status,
- const Version& version, const installer::Product& installation,
- bool system_level);
+ installer::InstallStatus status,
+ const Version& version,
+ const installer::Product& installation,
+ bool system_level);
// The user has qualified for the inactive user toast experiment and this
// function just performs it.
virtual void InactiveUserToastExperiment(int flavor,
+ const std::wstring& experiment_group,
const installer::Product& installation,
const FilePath& application_path);
diff --git a/chrome/installer/util/chrome_frame_distribution.h b/chrome/installer/util/chrome_frame_distribution.h
index 8f6150e..dca7086 100644
--- a/chrome/installer/util/chrome_frame_distribution.h
+++ b/chrome/installer/util/chrome_frame_distribution.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
//
@@ -21,39 +21,39 @@ class MasterPreferences;
class ChromeFrameDistribution : public BrowserDistribution {
public:
- virtual std::wstring GetAppGuid();
+ virtual std::wstring GetAppGuid() OVERRIDE;
- virtual std::wstring GetApplicationName();
+ virtual std::wstring GetApplicationName() OVERRIDE;
- virtual std::wstring GetAlternateApplicationName();
+ virtual std::wstring GetAlternateApplicationName() OVERRIDE;
- virtual std::wstring GetInstallSubDir();
+ virtual std::wstring GetInstallSubDir() OVERRIDE;
- virtual std::wstring GetPublisherName();
+ virtual std::wstring GetPublisherName() OVERRIDE;
- virtual std::wstring GetAppDescription();
+ virtual std::wstring GetAppDescription() OVERRIDE;
- virtual std::wstring GetLongAppDescription();
+ virtual std::wstring GetLongAppDescription() OVERRIDE;
- virtual std::string GetSafeBrowsingName();
+ virtual std::string GetSafeBrowsingName() OVERRIDE;
- virtual std::wstring GetStateKey();
+ virtual std::wstring GetStateKey() OVERRIDE;
- virtual std::wstring GetStateMediumKey();
+ virtual std::wstring GetStateMediumKey() OVERRIDE;
- virtual std::wstring GetStatsServerURL();
+ virtual std::wstring GetStatsServerURL() OVERRIDE;
- virtual std::wstring GetUninstallLinkName();
+ virtual std::wstring GetUninstallLinkName() OVERRIDE;
- virtual std::wstring GetUninstallRegPath();
+ virtual std::wstring GetUninstallRegPath() OVERRIDE;
- virtual std::wstring GetVersionKey();
+ virtual std::wstring GetVersionKey() OVERRIDE;
- virtual bool CanSetAsDefault();
+ virtual bool CanSetAsDefault() OVERRIDE;
virtual void UpdateInstallStatus(bool system_install,
installer::ArchiveType archive_type,
- installer::InstallStatus install_status);
+ installer::InstallStatus install_status) OVERRIDE;
protected:
friend class BrowserDistribution;
diff --git a/chrome/installer/util/chromium_binaries_distribution.h b/chrome/installer/util/chromium_binaries_distribution.h
index 6ee0c4f..9fe7095 100644
--- a/chrome/installer/util/chromium_binaries_distribution.h
+++ b/chrome/installer/util/chromium_binaries_distribution.h
@@ -14,41 +14,41 @@
class ChromiumBinariesDistribution : public BrowserDistribution {
public:
- virtual std::wstring GetAppGuid();
+ virtual std::wstring GetAppGuid() OVERRIDE;
- virtual std::wstring GetApplicationName();
+ virtual std::wstring GetApplicationName() OVERRIDE;
- virtual std::wstring GetAppShortCutName();
+ virtual std::wstring GetAppShortCutName() OVERRIDE;
- virtual std::wstring GetAlternateApplicationName();
+ virtual std::wstring GetAlternateApplicationName() OVERRIDE;
- virtual std::wstring GetBrowserAppId();
+ virtual std::wstring GetBrowserAppId() OVERRIDE;
- virtual std::wstring GetInstallSubDir();
+ virtual std::wstring GetInstallSubDir() OVERRIDE;
- virtual std::wstring GetPublisherName();
+ virtual std::wstring GetPublisherName() OVERRIDE;
- virtual std::wstring GetAppDescription();
+ virtual std::wstring GetAppDescription() OVERRIDE;
- virtual std::wstring GetLongAppDescription();
+ virtual std::wstring GetLongAppDescription() OVERRIDE;
- virtual std::string GetSafeBrowsingName();
+ virtual std::string GetSafeBrowsingName() OVERRIDE;
- virtual std::wstring GetStateKey();
+ virtual std::wstring GetStateKey() OVERRIDE;
- virtual std::wstring GetStateMediumKey();
+ virtual std::wstring GetStateMediumKey() OVERRIDE;
- virtual std::wstring GetUninstallLinkName();
+ virtual std::wstring GetUninstallLinkName() OVERRIDE;
- virtual std::wstring GetUninstallRegPath();
+ virtual std::wstring GetUninstallRegPath() OVERRIDE;
- virtual std::wstring GetVersionKey();
+ virtual std::wstring GetVersionKey() OVERRIDE;
- virtual bool CanSetAsDefault();
+ virtual bool CanSetAsDefault() OVERRIDE;
- virtual int GetIconIndex();
+ virtual int GetIconIndex() OVERRIDE;
- virtual bool GetChromeChannel(std::wstring* channel);
+ virtual bool GetChromeChannel(std::wstring* channel) OVERRIDE;
protected:
friend class BrowserDistribution;
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc
index a089735..da9eef4 100644
--- a/chrome/installer/util/google_chrome_distribution.cc
+++ b/chrome/installer/util/google_chrome_distribution.cc
@@ -17,11 +17,13 @@
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/scoped_ptr.h"
+#include "base/string_split.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
+#include "chrome/common/attrition_experiments.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/pref_names.h"
@@ -46,29 +48,15 @@ const wchar_t kChromeGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
const wchar_t kBrowserAppId[] = L"Chrome";
// The following strings are the possible outcomes of the toast experiment
-// as recorded in the |client| field. Previously the groups used "TSxx" but
-// the data captured is not valid.
-const wchar_t kToastExpControlGroup[] = L"T%lc01";
-const wchar_t kToastExpCancelGroup[] = L"T%lc02";
-const wchar_t kToastExpUninstallGroup[] = L"T%lc04";
-const wchar_t kToastExpTriesOkGroup[] = L"T%lc18";
-const wchar_t kToastExpTriesErrorGroup[] = L"T%lc28";
-const wchar_t kToastActiveGroup[] = L"T%lc40";
-const wchar_t kToastUDDirFailure[] = L"T%lc40";
-const wchar_t kToastExpBaseGroup[] = L"T%lc80";
-
-// Generates the actual group string that gets written in the registry.
-// |group| is one of the above kToast* strings and |flavor| is a number
-// from 0 to 3.
-//
-// The big experiment in Dec 2009 used TGxx and THxx.
-// The big experiment in Feb 2010 used TKxx and TLxx.
-// The big experiment in Apr 2010 used TMxx and TNxx.
-// The big experiment in Oct 2010 (current) uses TVxx TWxx TXxx TYxx.
-std::wstring GetExperimentGroup(const wchar_t* group, int flavor) {
- wchar_t c = flavor < 4 ? L'V' + flavor : L'Z';
- return StringPrintf(group, c);
-}
+// 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";
// Substitute the locale parameter in uninstall URL with whatever
// Google Update tells us is the locale. In case we fail to find
@@ -130,18 +118,14 @@ int GetDirectoryWriteAgeInHours(const wchar_t* path) {
return (now_time - dir_time);
}
-// Launches setup.exe (located at |setup_path|) with switch --|flag|=|value|.
+// Launches setup.exe (located at |setup_path|) with |cmd_line|.
// If system_level_toast is true, appends --system-level-toast.
// If handle to experiment result key was given at startup, re-add it.
// Does not wait for the process to terminate.
-bool LaunchSetup(const FilePath& setup_path, const std::string& flag,
- int value, bool system_level_toast) {
- CommandLine new_cmd_line(setup_path);
- new_cmd_line.AppendSwitchASCII(flag, base::IntToString(value));
-
+bool LaunchSetup(CommandLine cmd_line, bool system_level_toast) {
// Re-add the system level toast flag.
if (system_level_toast) {
- new_cmd_line.AppendSwitch(installer::switches::kSystemLevelToast);
+ cmd_line.AppendSwitch(installer::switches::kSystemLevelToast);
// Re-add the toast result key. We need to do this because Setup running as
// system passes the key to Setup running as user, but that child process
@@ -151,16 +135,16 @@ bool LaunchSetup(const FilePath& setup_path, const std::string& flag,
std::string key(installer::switches::kToastResultsKey);
std::string toast_key = current_cmd_line.GetSwitchValueASCII(key);
if (!toast_key.empty()) {
- new_cmd_line.AppendSwitchASCII(key, toast_key);
+ cmd_line.AppendSwitchASCII(key, toast_key);
// Use handle inheritance to make sure the duplicated toast results key
// gets inherited by the child process.
return base::LaunchAppWithHandleInheritance(
- new_cmd_line.command_line_string(), false, false, NULL);
+ cmd_line.command_line_string(), false, false, NULL);
}
}
- return base::LaunchApp(new_cmd_line.command_line_string(),
+ return base::LaunchApp(cmd_line.command_line_string(),
false, false, NULL);
}
@@ -548,6 +532,92 @@ void SetClient(std::wstring experiment_group, bool last_write) {
}
}
+bool GoogleChromeDistribution::GetExperimentDetails(
+ UserExperiment* experiment, int flavor) {
+ // Maximum number of experiment flavors we support.
+ const int kMax = 4;
+ // This struct determines which experiment flavors we show for each locale and
+ // brand.
+ //
+ // The big experiment in Dec 2009 used TGxx and THxx.
+ // The big experiment in Feb 2010 used TKxx and TLxx.
+ // The big experiment in Apr 2010 used TMxx and TNxx.
+ // The big experiment in Oct 2010 used TVxx TWxx TXxx TYxx.
+ // The big experiment in Feb 2011 used SJxx SKxx SLxx SMxx.
+ 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[] = {
+ // First in this order are the brand specific ones.
+ {L"en-US", kSkype, 1, L'Z', L'A', 1, { kSkype1, 0, 0, 0 } },
+ // And then we have catch-alls, like en-US (all brands).
+ {L"en-US", kAll, 1, L'T', L'V', 4, { kEnUs1, kEnUs2, kEnUs3, kEnUs4} },
+ // Japan has two experiments, same IDs as en-US but translated differently.
+ {L"jp", kAll, 1, L'T', L'V', 2, { kEnUs1, kEnUs2, 0, 0} },
+ };
+
+ std::wstring locale;
+ std::wstring brand;
+
+ if (!GoogleUpdateSettings::GetLanguage(&locale))
+ locale = L"en-US";
+ if (!GoogleUpdateSettings::GetBrand(&brand))
+ return false;
+
+ for (int i = 0; i < arraysize(kExperimentFlavors); ++i) {
+ // A maximum of four flavors is supported at the moment.
+ DCHECK_LE(kExperimentFlavors[i].flavors, kMax);
+ DCHECK_GT(kExperimentFlavors[i].flavors, 0);
+ // Make sure each experiment has valid headings.
+ for (int f = 0; f < kMax; ++f) {
+ if (f < kExperimentFlavors[i].flavors)
+ DCHECK_GT(kExperimentFlavors[i].headings[f], 0);
+ else
+ DCHECK_EQ(kExperimentFlavors[i].headings[f], 0);
+ }
+ // Make sure we don't overflow on the second letter of the experiment code.
+ DCHECK(kExperimentFlavors[i].prefix2 +
+ kExperimentFlavors[i].flavors - 1 <= 'Z');
+
+ if (kExperimentFlavors[i].locale != locale &&
+ kExperimentFlavors[i].locale != L"*")
+ continue;
+
+ std::vector<std::wstring> brand_codes;
+ base::SplitString(kExperimentFlavors[i].brands, L',', &brand_codes);
+ if (brand_codes.empty())
+ return false;
+ for (std::vector<std::wstring>::iterator it = brand_codes.begin();
+ it != brand_codes.end(); ++it) {
+ if (*it != brand && *it != L"*")
+ continue;
+
+ // We have found our match.
+ if (flavor < 0)
+ flavor = base::RandInt(0, kExperimentFlavors[i].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;
+ return true;
+ }
+ }
+
+ return false;
+}
+
// Currently we only have one experiment: the inactive user toast. Which only
// applies for users doing upgrades.
//
@@ -575,19 +645,15 @@ void GoogleChromeDistribution::LaunchUserExperiment(
}
}
- // This ends up being processed by ShowTryChromeDialog to show different
- // experiments. Only run the experiment in en-US and ja.
- int flavor = 0;
- std::wstring language;
- if (GoogleUpdateSettings::GetLanguage(&language)) {
- if (language == L"en-US") {
- // en-US has four different toasts.
- flavor = base::RandInt(0, 3);
- } else if (language == L"ja") {
- // ja has three different toasts.
- flavor = base::RandInt(0, 2);
- }
+ // The |flavor| value ends up being processed by ShowTryChromeDialog to show
+ // different experiments.
+ UserExperiment experiment;
+ if (!GetExperimentDetails(&experiment, -1)) {
+ VLOG(1) << "Failed to get experiment details.";
+ return;
}
+ int flavor = experiment.flavor;
+ std::wstring base_group = experiment.prefix;
std::wstring brand;
if (GoogleUpdateSettings::GetBrand(&brand) && (brand == L"CHXX")) {
@@ -610,34 +676,41 @@ void GoogleChromeDistribution::LaunchUserExperiment(
// This means that we failed to find the user data dir. The most likely
// cause is that this user has not ever used chrome at all which can
// happen in a system-level install.
- SetClient(GetExperimentGroup(kToastUDDirFailure, flavor), true);
+ SetClient(base_group + kToastUDDirFailure, true);
return;
} else if (dir_age_hours < kThirtyDays) {
// An active user, so it does not qualify.
VLOG(1) << "Chrome used in last " << dir_age_hours << " hours";
- SetClient(GetExperimentGroup(kToastActiveGroup, flavor), true);
+ SetClient(base_group + kToastActiveGroup, true);
return;
}
- // 1% are in the control group that qualifies but does not get drafted.
- if (base::RandDouble() > 0.99) {
- SetClient(GetExperimentGroup(kToastExpControlGroup, flavor), true);
+ // Check to see if this user belongs to the control group.
+ double control_group = 1.0 * (100 - experiment.control_group) / 100;
+ if (base::RandDouble() > control_group) {
+ SetClient(base_group + kToastExpControlGroup, true);
VLOG(1) << "User is control group";
return;
}
}
VLOG(1) << "User drafted for toast experiment " << flavor;
- SetClient(GetExperimentGroup(kToastExpBaseGroup, flavor), false);
+ SetClient(base_group + kToastExpBaseGroup, false);
// User level: The experiment needs to be performed in a different process
// because google_update expects the upgrade process to be quick and nimble.
// System level: We have already been relaunched, so we don't need to be
// quick, but we relaunch to follow the exact same codepath.
- LaunchSetup(setup_path, installer::switches::kInactiveUserToast, flavor,
- system_level);
+ CommandLine cmd_line(setup_path);
+ cmd_line.AppendSwitchASCII(installer::switches::kInactiveUserToast,
+ base::IntToString(flavor));
+ cmd_line.AppendSwitchASCII(installer::switches::kExperimentGroup,
+ WideToASCII(base_group));
+ LaunchSetup(cmd_line, system_level);
}
-// User qualifies for the experiment. Launch chrome with --try-chrome=flavor.
+// User qualifies for the experiment. To test, use --try-chrome-again=|flavor|
+// as a parameter to chrome.exe.
void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
+ const std::wstring& experiment_group,
const installer::Product& installation,
const FilePath& application_path) {
bool has_welcome_url = (flavor == 0);
@@ -677,7 +750,7 @@ void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
};
// Write to the |client| key for the last time.
- SetClient(GetExperimentGroup(outcome, flavor), true);
+ SetClient(experiment_group + outcome, true);
if (outcome != kToastExpUninstallGroup)
return;
diff --git a/chrome/installer/util/google_chrome_distribution.h b/chrome/installer/util/google_chrome_distribution.h
index 3dc3b88..5586896 100644
--- a/chrome/installer/util/google_chrome_distribution.h
+++ b/chrome/installer/util/google_chrome_distribution.h
@@ -29,59 +29,67 @@ class GoogleChromeDistribution : public BrowserDistribution {
// distribution_data contains Google Update related data that will be
// concatenated to the survey url if the file in local_data_path indicates
// the user has opted in to providing anonymous usage data.
- virtual void DoPostUninstallOperations(const Version& version,
- const FilePath& local_data_path,
- const std::wstring& distribution_data);
+ virtual void DoPostUninstallOperations(
+ const Version& version,
+ const FilePath& local_data_path,
+ const std::wstring& distribution_data) OVERRIDE;
- virtual std::wstring GetAppGuid();
+ virtual std::wstring GetAppGuid() OVERRIDE;
- virtual std::wstring GetApplicationName();
+ virtual std::wstring GetApplicationName() OVERRIDE;
- virtual std::wstring GetAlternateApplicationName();
+ virtual std::wstring GetAlternateApplicationName() OVERRIDE;
- virtual std::wstring GetBrowserAppId();
+ virtual std::wstring GetBrowserAppId() OVERRIDE;
- virtual std::wstring GetInstallSubDir();
+ virtual std::wstring GetInstallSubDir() OVERRIDE;
- virtual std::wstring GetPublisherName();
+ virtual std::wstring GetPublisherName() OVERRIDE;
- virtual std::wstring GetAppDescription();
+ virtual std::wstring GetAppDescription() OVERRIDE;
- virtual std::string GetSafeBrowsingName();
+ virtual std::string GetSafeBrowsingName() OVERRIDE;
- virtual std::wstring GetStateKey();
+ virtual std::wstring GetStateKey() OVERRIDE;
- virtual std::wstring GetStateMediumKey();
+ virtual std::wstring GetStateMediumKey() OVERRIDE;
- virtual std::wstring GetStatsServerURL();
+ virtual std::wstring GetStatsServerURL() OVERRIDE;
// This method reads data from the Google Update ClientState key for
// potential use in the uninstall survey. It must be called before the
// key returned by GetVersionKey() is deleted.
- virtual std::wstring GetDistributionData(HKEY root_key);
+ virtual std::wstring GetDistributionData(HKEY root_key) OVERRIDE;
- virtual std::wstring GetUninstallLinkName();
+ virtual std::wstring GetUninstallLinkName() OVERRIDE;
- virtual std::wstring GetUninstallRegPath();
+ virtual std::wstring GetUninstallRegPath() OVERRIDE;
- virtual std::wstring GetVersionKey();
+ virtual std::wstring GetVersionKey() OVERRIDE;
- virtual void UpdateInstallStatus(bool system_install,
+ virtual void UpdateInstallStatus(
+ bool system_install,
installer::ArchiveType archive_type,
- installer::InstallStatus install_status);
+ installer::InstallStatus install_status) OVERRIDE;
+
+ virtual bool GetExperimentDetails(UserExperiment* experiment,
+ int flavor) OVERRIDE;
- virtual void LaunchUserExperiment(const FilePath& setup_path,
+ virtual void LaunchUserExperiment(
+ const FilePath& setup_path,
installer::InstallStatus status,
const Version& version,
const installer::Product& installation,
- bool system_level);
+ bool system_level) OVERRIDE;
// Assuming that the user qualifies, this function performs the inactive user
// toast experiment. It will use chrome to show the UI and it will record the
// outcome in the registry.
- virtual void InactiveUserToastExperiment(int flavor,
+ virtual void InactiveUserToastExperiment(
+ int flavor,
+ const std::wstring& experiment_group,
const installer::Product& installation,
- const FilePath& application_path);
+ const FilePath& application_path) OVERRIDE;
const std::wstring& product_guid() { return product_guid_; }
diff --git a/chrome/installer/util/google_chrome_distribution_dummy.cc b/chrome/installer/util/google_chrome_distribution_dummy.cc
index cac5d1b..496d264 100644
--- a/chrome/installer/util/google_chrome_distribution_dummy.cc
+++ b/chrome/installer/util/google_chrome_distribution_dummy.cc
@@ -106,6 +106,12 @@ void GoogleChromeDistribution::UpdateInstallStatus(bool system_install,
NOTREACHED();
}
+bool GoogleChromeDistribution::GetExperimentDetails(
+ UserExperiment* experiment, int flavor) {
+ NOTREACHED();
+ return false;
+}
+
void GoogleChromeDistribution::LaunchUserExperiment(
const FilePath& setup_path, installer::InstallStatus status,
const Version& version, const installer::Product& installation,
@@ -114,6 +120,7 @@ void GoogleChromeDistribution::LaunchUserExperiment(
}
void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
+ const std::wstring& experiment_group,
const installer::Product& installation,
const FilePath& application_path) {
NOTREACHED();
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index 20b4a0c..bd92223 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -143,6 +143,9 @@ const char kInactiveUserToast[] = "inactive-user-toast";
// User toast experiment switch from system context to user context.
const char kSystemLevelToast[] = "system-level-toast";
+// The group this experiment belongs to.
+const char kExperimentGroup[] = "experiment-group";
+
// A handle value of the key to write the results of the toast experiment
// to. See DuplicateGoogleUpdateSystemClientKey for details.
const char kToastResultsKey[] = "toast-results-key";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index b7e5347..925110b 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -44,7 +44,7 @@ enum InstallStatus {
RENAME_FAILED, // 24. Rename of new_chrome.exe failed
EULA_REJECTED, // 25. EULA dialog was not accepted by user.
EULA_ACCEPTED, // 26. EULA dialog was accepted by user.
- EULA_ACCEPTED_OPT_IN, // 27. EULA accepted wtih the crash optin selected.
+ EULA_ACCEPTED_OPT_IN, // 27. EULA accepted with the crash option selected.
INSTALL_DIR_IN_USE, // 28. Installation directory is in use by another
// process
UNINSTALL_REQUIRES_REBOOT, // 29. Uninstallation required a reboot.
@@ -139,6 +139,7 @@ extern const char kShowEula[];
extern const char kAltDesktopShortcut[];
extern const char kInactiveUserToast[];
extern const char kSystemLevelToast[];
+extern const char kExperimentGroup[];
extern const char kToastResultsKey[];
} // namespace switches