summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-04 15:48:11 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-04 15:48:11 +0000
commitb80965554a11ef9d71df551c993e67a9ebe56cf9 (patch)
tree845c29d921de66ac917cdf74d2018fbf922d3411
parent96abd567af2702ae7dd7a657d99bde38616bb380 (diff)
downloadchromium_src-b80965554a11ef9d71df551c993e67a9ebe56cf9.zip
chromium_src-b80965554a11ef9d71df551c993e67a9ebe56cf9.tar.gz
chromium_src-b80965554a11ef9d71df551c993e67a9ebe56cf9.tar.bz2
cros: Default pinned apps experiment.
- Setup default pinned apps field trial when a regular user signs in; - Existing user prior the trial goes to "Existing" group; - New users split 50/50 to "Control" and "Alternate"; - "Alternate" group users get the alternate default pinned apps; - Add click UMA histogram to compare clicks on the shelf; BUG=234415 Review URL: https://chromiumcodereview.appspot.com/14566003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198327 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.cc4
-rw-r--r--chrome/browser/chromeos/extensions/default_app_order.cc14
-rw-r--r--chrome/browser/chromeos/login/default_pinned_apps_field_trial.cc175
-rw-r--r--chrome/browser/chromeos/login/default_pinned_apps_field_trial.h59
-rw-r--r--chrome/browser/chromeos/login/default_pinned_apps_field_trial_unittest.cc91
-rw-r--r--chrome/browser/chromeos/login/user_manager_impl.cc3
-rw-r--r--chrome/browser/extensions/default_apps.cc14
-rw-r--r--chrome/browser/prefs/browser_prefs.cc2
-rw-r--r--chrome/browser/ui/ash/chrome_launcher_prefs.cc20
-rw-r--r--chrome/browser/ui/ash/chrome_shell_delegate.cc8
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc23
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc5
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc17
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc4
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/common/extensions/extension_constants.cc17
-rw-r--r--chrome/common/extensions/extension_constants.h40
-rw-r--r--tools/metrics/histograms/histograms.xml23
19 files changed, 478 insertions, 44 deletions
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 4662315..a54caae 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -44,6 +44,7 @@
#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.h"
#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
#include "chrome/browser/chromeos/login/authenticator.h"
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
@@ -487,7 +488,7 @@ void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
CrasAudioHandler::Initialize(
AudioDevicesPrefHandler::Create(g_browser_process->local_state()));
} else {
- AudioHandler::Initialize(
+ AudioHandler::Initialize(
AudioPrefHandler::Create(g_browser_process->local_state()));
}
@@ -851,6 +852,7 @@ void ChromeBrowserMainPartsChromeos::PostDestroyThreads() {
void ChromeBrowserMainPartsChromeos::SetupPlatformFieldTrials() {
SetupZramFieldTrial();
+ default_pinned_apps_field_trial::SetupTrial();
}
void ChromeBrowserMainPartsChromeos::SetupZramFieldTrial() {
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index 0d19745..a63df33 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -54,21 +54,21 @@ void GetDefault(std::vector<std::string>* app_ids) {
const char* kDefaultAppOrder[] = {
extension_misc::kChromeAppId,
extension_misc::kWebStoreAppId,
- "coobgpohoikkiipiblmjeljniedjpjpf", // Search
- "blpcfgokakmgnkcojhhkbfbldkacnbeo", // Youtube
- "pjkljhegncpnkpknbcohdijeoejaedia", // Gmail
+ extension_misc::kGoogleSearchAppId,
+ extension_misc::kYoutubeAppId,
+ extension_misc::kGmailAppId,
"ejjicmeblgpmajnghnpcppodonldlgfn", // Calendar
"kjebfhglflhjjjiceimfkgicifkhjlnm", // Scratchpad
"lneaknkopdijkpnocmklfnjbeapigfbh", // Google Maps
"apdfllckaahabafndbhieahigkjlhalf", // Drive
- "aohghmighlieiainnegkcijnfilokake", // Docs
- "felcaaldnbdncclmgdcncolpebgiejap", // Sheets
- "aapocclcgogkmnckokdopfmhonfmgoek", // Slides
+ extension_misc::kGoogleDocAppId,
+ extension_misc::kGoogleSheetsAppId,
+ extension_misc::kGoogleSlidesAppId,
"dlppkpafhbajpcmmoheippocdidnckmm", // Google+
"kbpgddbgniojgndnhlkjbkpknjhppkbk", // Google+ Hangouts
"hhaomjibdihmijegdhdafkllkbggdgoj", // Files
"hkhhlkdconhgemhegnplaldnmnmkaemd", // Tips & Tricks
- "icppfcnhkcmnfdhfhphakoifcfokfdhg", // Play Music
+ extension_misc::kGooglePlayMusicAppId,
"mmimngoggfoobjdlefbcabngfnmieonb", // Play Books
"fppdphmgcddhjeddoeghpjefkdlccljb", // Play Movies
"fobcpibfeplaikcclojfdhfdmbbeofai", // Games
diff --git a/chrome/browser/chromeos/login/default_pinned_apps_field_trial.cc b/chrome/browser/chromeos/login/default_pinned_apps_field_trial.cc
new file mode 100644
index 0000000..f963ac9
--- /dev/null
+++ b/chrome/browser/chromeos/login/default_pinned_apps_field_trial.cc
@@ -0,0 +1,175 @@
+// Copyright 2013 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 "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_constants.h"
+
+namespace chromeos {
+namespace default_pinned_apps_field_trial {
+
+namespace {
+
+// Name of the default pinned app experiment.
+const char kExperimentName[] = "DefaultPinnedApps";
+
+// Name of a local state pref to store the list of users that participate
+// the experiment.
+const char kExperimentUsers[] = "DefaultPinnedAppsExperimentUsers";
+
+// Alternate default pinned apps.
+const char* kAlternateDefaultPinnedApps[] = {
+ extension_misc::kGmailAppId,
+ extension_misc::kGoogleDocAppId,
+ extension_misc::kGoogleSheetsAppId,
+ extension_misc::kGoogleSlidesAppId,
+ extension_misc::kGooglePlayMusicAppId,
+};
+
+// Global state of trial setup.
+bool trial_configured = false;
+int alternate_group = base::FieldTrial::kNotFinalized;
+
+// Returns true if user participates the experiment.
+bool IsUserInExperiment(const std::string& username) {
+ const base::ListValue* users =
+ g_browser_process->local_state()->GetList(kExperimentUsers);
+ return users && users->Find(base::StringValue(username)) != users->end();
+}
+
+// Adds user to the experiment user list.
+void AddUserToExperiment(const std::string& username) {
+ ListPrefUpdate users(g_browser_process->local_state(), kExperimentUsers);
+ users->AppendString(username);
+}
+
+// Gets click target type for given app id. Returns false if the app id is
+// not interesting.
+bool GetClickTargetForApp(const std::string& app_id,
+ ClickTarget* click_target) {
+ static const struct AppIdToClickTarget {
+ const char* app_id;
+ ClickTarget click_target;
+ } kApps[] = {
+ { extension_misc::kChromeAppId, CHROME },
+ { extension_misc::kGmailAppId, GMAIL },
+ { extension_misc::kGoogleSearchAppId, SEARCH },
+ { extension_misc::kYoutubeAppId, YOUTUBE },
+ { extension_misc::kGoogleDocAppId, DOC },
+ { extension_misc::kGoogleSheetsAppId, SHEETS },
+ { extension_misc::kGoogleSlidesAppId, SLIDES },
+ { extension_misc::kGooglePlayMusicAppId, PLAY_MUSIC },
+ };
+
+ // kApps should define an app id for all click types except APP_LAUNCHER.
+ COMPILE_ASSERT(ARRAYSIZE_UNSAFE(kApps) == CLICK_TARGET_COUNT - 1,
+ app_to_click_target_incorrect_size);
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kApps); ++i) {
+ if (app_id == kApps[i].app_id) {
+ *click_target = kApps[i].click_target;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace
+
+void RegisterPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterListPref(kExperimentUsers);
+}
+
+void SetupTrial() {
+ // No trial if multiple profiles are enabled.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kMultiProfiles))
+ return;
+
+ // SetupForUser should only be called once for single profile mode.
+ DCHECK(!trial_configured);
+
+ const base::FieldTrial::Probability kDivisor = 100;
+ scoped_refptr<base::FieldTrial> trial =
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kExperimentName, kDivisor, "Existing", 2013, 12, 31, NULL);
+ trial->UseOneTimeRandomization();
+
+ // Split 50/50 between "Control" and "Alternamte" group for new user.
+ // Existing users already have their default pinned apps and have the trial
+ // disabled to go to "Existing" group.
+ trial->AppendGroup("Control", 50);
+ alternate_group = trial->AppendGroup("Alternate", 50);
+}
+
+void SetupForUser(const std::string& username, bool is_new_user) {
+ base::FieldTrial* trial = base::FieldTrialList::Find(kExperimentName);
+ if (!trial)
+ return;
+
+ trial_configured = true;
+
+ if (is_new_user) {
+ AddUserToExperiment(username);
+ return;
+ }
+
+ if (!IsUserInExperiment(username))
+ trial->Disable();
+}
+
+base::ListValue* GetAlternateDefaultPinnedApps() {
+ // This function is called for login manager profile, which happens
+ // before any user signs in. Returns NULL in this case. The case is covered
+ // by NULL trial check below but checking a boolean flag is faster.
+ if (!trial_configured)
+ return NULL;
+
+ base::FieldTrial* trial = base::FieldTrialList::Find(kExperimentName);
+ if (!trial || trial->group() != alternate_group)
+ return NULL;
+
+ scoped_ptr<base::ListValue> apps(new base::ListValue);
+ for (size_t i = 0; i < arraysize(kAlternateDefaultPinnedApps); ++i)
+ apps->Append(ash::CreateAppDict(kAlternateDefaultPinnedApps[i]));
+
+ return apps.release();
+}
+
+void RecordShelfClick(ClickTarget click_target) {
+ // The experiment does not include certain user types, such as public account,
+ // retail mode user, local user and ephemeral user.
+ if (!trial_configured)
+ return;
+
+ UMA_HISTOGRAM_ENUMERATION("Cros.ClickOnShelf",
+ click_target,
+ CLICK_TARGET_COUNT);
+}
+
+void RecordShelfAppClick(const std::string& app_id) {
+ ClickTarget click_target = CLICK_TARGET_COUNT;
+ if (GetClickTargetForApp(app_id, &click_target))
+ RecordShelfClick(click_target);
+}
+
+void ResetStateForTest() {
+ trial_configured = false;
+ alternate_group = base::FieldTrial::kNotFinalized;
+}
+
+} // namespace default_pinned_apps_field_trial
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/default_pinned_apps_field_trial.h b/chrome/browser/chromeos/login/default_pinned_apps_field_trial.h
new file mode 100644
index 0000000..995bb96
--- /dev/null
+++ b/chrome/browser/chromeos/login/default_pinned_apps_field_trial.h
@@ -0,0 +1,59 @@
+// Copyright 2013 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_BROWSER_CHROMEOS_LOGIN_DEFAULT_PINNED_APPS_FIELD_TRIAL_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_DEFAULT_PINNED_APPS_FIELD_TRIAL_H_
+
+#include <string>
+
+namespace base {
+class ListValue;
+}
+
+class PrefRegistrySimple;
+
+namespace chromeos {
+namespace default_pinned_apps_field_trial {
+
+// Enumeration to track clicks on the shelf.
+enum ClickTarget {
+ CHROME = 0,
+ APP_LAUNCHER = 1,
+ GMAIL = 2,
+ SEARCH = 3,
+ YOUTUBE = 4,
+ DOC = 5,
+ SHEETS = 6,
+ SLIDES = 7,
+ PLAY_MUSIC = 8,
+ CLICK_TARGET_COUNT = 9
+};
+
+// Registers a local state that keeps track of users in experiment.
+void RegisterPrefs(PrefRegistrySimple* registry);
+
+// Creates the trail and setup groups.
+void SetupTrial();
+
+// Sets up the trial for a user. |username| is the email of the user.
+// |is_new_user| is a boolean flag to indicate whether the user is new to
+// the device. It is true when the user signs in the device for the first time.
+void SetupForUser(const std::string& username, bool is_new_user);
+
+// Returns the alternate default pinned apps if the current user is in
+// "Alternate" group. Otherwise, returns NULL. The caller takes the ownership
+// of the returned list.
+base::ListValue* GetAlternateDefaultPinnedApps();
+
+// Record UMA for shelf clicks.
+void RecordShelfClick(ClickTarget click_target);
+void RecordShelfAppClick(const std::string& app_id);
+
+// Resets global states from test.
+void ResetStateForTest();
+
+} // namespace default_pinned_apps_field_trial
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_DEFAULT_PINNED_APPS_FIELD_TRIAL_H_
diff --git a/chrome/browser/chromeos/login/default_pinned_apps_field_trial_unittest.cc b/chrome/browser/chromeos/login/default_pinned_apps_field_trial_unittest.cc
new file mode 100644
index 0000000..1406ca7
--- /dev/null
+++ b/chrome/browser/chromeos/login/default_pinned_apps_field_trial_unittest.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 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 "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/field_trial.h"
+#include "base/prefs/testing_pref_service.h"
+#include "chrome/common/metrics/entropy_provider.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+class DefaultPinnedAppsFieldTrialTest : public testing::Test {
+ public:
+ DefaultPinnedAppsFieldTrialTest() {}
+ virtual ~DefaultPinnedAppsFieldTrialTest() {}
+
+ // testing::Test overrides:
+ virtual void SetUp() OVERRIDE {
+ CreateFieldTrialList();
+ CreateLocalState();
+ }
+ virtual void TearDown() OVERRIDE {
+ Reset();
+ }
+
+ void CreateFieldTrialList() {
+ if (trial_list_)
+ trial_list_.reset();
+ trial_list_.reset(new base::FieldTrialList(
+ new metrics::SHA1EntropyProvider("client_id")));
+ default_pinned_apps_field_trial::SetupTrial();
+ }
+
+ void CreateLocalState() {
+ local_state_.reset(new TestingPrefServiceSimple);
+ default_pinned_apps_field_trial::RegisterPrefs(local_state_->registry());
+ TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get());
+ }
+
+ void Reset() {
+ TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
+ local_state_.reset();
+ trial_list_.reset();
+ default_pinned_apps_field_trial::ResetStateForTest();
+ }
+
+ private:
+ scoped_ptr<base::FieldTrialList> trial_list_;
+ scoped_ptr<TestingPrefServiceSimple> local_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultPinnedAppsFieldTrialTest);
+};
+
+// Tests existing user gets to "Existing" group.
+TEST_F(DefaultPinnedAppsFieldTrialTest, ExistingUser) {
+ default_pinned_apps_field_trial::SetupForUser("existing@gmail.com",
+ false /* is_new_user */);
+ base::FieldTrial* trial = base::FieldTrialList::Find("DefaultPinnedApps");
+ ASSERT_TRUE(trial != NULL);
+ EXPECT_EQ("Existing", trial->group_name());
+}
+
+// Tests new user gets to either "Control" or "Alternate group. And the user
+// should get to the same group all the time.
+TEST_F(DefaultPinnedAppsFieldTrialTest, NewUser) {
+ const char* kTestUser = "new@gmail.com";
+ default_pinned_apps_field_trial::SetupForUser(kTestUser,
+ true /* is_new_user */);
+ base::FieldTrial* trial = base::FieldTrialList::Find("DefaultPinnedApps");
+ ASSERT_TRUE(trial != NULL);
+ const std::string allocated_group = trial->group_name();
+ EXPECT_TRUE("Control" == allocated_group || "Alternate" == allocated_group);
+
+ // Pretend user signs out and signs back in.
+ default_pinned_apps_field_trial::ResetStateForTest();
+ CreateFieldTrialList();
+
+ // This time, the user is no longer a new user.
+ default_pinned_apps_field_trial::SetupForUser(kTestUser,
+ false /* is_new_user */);
+
+ // But he/she should still be included in the trial and in the same group.
+ trial = base::FieldTrialList::Find("DefaultPinnedApps");
+ EXPECT_EQ(allocated_group, trial->group_name());
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index addc810..cfdc9a9 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -27,6 +27,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cert_library.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
#include "chrome/browser/chromeos/login/login_display.h"
#include "chrome/browser/chromeos/login/remove_user_delegate.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
@@ -1017,6 +1018,8 @@ void UserManagerImpl::RegularUserLoggedIn(const std::string& email,
WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
}
+ default_pinned_apps_field_trial::SetupForUser(email, is_current_user_new_);
+
// Make sure that new data is persisted to Local State.
g_browser_process->local_state()->CommitPendingWrite();
}
diff --git a/chrome/browser/extensions/default_apps.cc b/chrome/browser/extensions/default_apps.cc
index 3ecf9a0..9633d12 100644
--- a/chrome/browser/extensions/default_apps.cc
+++ b/chrome/browser/extensions/default_apps.cc
@@ -4,6 +4,9 @@
#include "chrome/browser/extensions/default_apps.h"
+#include <set>
+#include <string>
+
#include "base/command_line.h"
#include "chrome/browser/browser_process.h"
#include "components/user_prefs/pref_registry_syncable.h"
@@ -20,14 +23,11 @@
namespace {
-const char kGmailId[] = "pjkljhegncpnkpknbcohdijeoejaedia";
-const char kSearchId[] = "coobgpohoikkiipiblmjeljniedjpjpf";
-const char kYoutubeId[] = "blpcfgokakmgnkcojhhkbfbldkacnbeo";
-
// Returns true if the app was a default app in Chrome 22
bool IsOldDefaultApp(const std::string& extension_id) {
- return extension_id == kGmailId || extension_id == kSearchId
- || extension_id == kYoutubeId;
+ return extension_id == extension_misc::kGmailAppId ||
+ extension_id == extension_misc::kGoogleSearchAppId ||
+ extension_id == extension_misc::kYoutubeAppId;
}
bool IsLocaleSupported() {
@@ -45,7 +45,7 @@ bool IsLocaleSupported() {
return true;
}
-} // namespace
+} // namespace
namespace default_apps {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index fac503e..77581f3 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -122,6 +122,7 @@
#include "chrome/browser/chromeos/audio/audio_pref_handler_impl.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/display/display_preferences.h"
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/oauth2_login_manager.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
@@ -247,6 +248,7 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
chromeos::DataPromoNotification::RegisterPrefs(registry);
chromeos::DeviceOAuth2TokenService::RegisterPrefs(registry);
chromeos::device_settings_cache::RegisterPrefs(registry);
+ chromeos::default_pinned_apps_field_trial::RegisterPrefs(registry);
chromeos::language_prefs::RegisterPrefs(registry);
chromeos::KioskAppManager::RegisterPrefs(registry);
chromeos::LoginUtils::RegisterPrefs(registry);
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.cc b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
index 05994ea..b0dfdba 100644
--- a/chrome/browser/ui/ash/chrome_launcher_prefs.cc
+++ b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
@@ -7,20 +7,32 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
+#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+#endif
+
namespace {
// App ID of default pinned apps.
const char* kDefaultPinnedApps[] = {
- "pjkljhegncpnkpknbcohdijeoejaedia", // Gmail
- "coobgpohoikkiipiblmjeljniedjpjpf", // Search
- "apdfllckaahabafndbhieahigkjlhalf", // Doc
- "blpcfgokakmgnkcojhhkbfbldkacnbeo", // YouTube
+ extension_misc::kGmailAppId,
+ extension_misc::kGoogleSearchAppId,
+ extension_misc::kGoogleDocAppId,
+ extension_misc::kYoutubeAppId,
};
base::ListValue* CreateDefaultPinnedAppsList() {
+#if defined(OS_CHROMEOS)
+ base::ListValue* alternate = chromeos::default_pinned_apps_field_trial::
+ GetAlternateDefaultPinnedApps();
+ if (alternate)
+ return alternate;
+#endif
+
scoped_ptr<base::ListValue> apps(new base::ListValue);
for (size_t i = 0; i < arraysize(kDefaultPinnedApps); ++i)
apps->Append(ash::CreateAppDict(kDefaultPinnedApps[i]));
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 8657a67..56c4486 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -50,6 +50,10 @@
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+#endif
+
// static
ChromeShellDelegate* ChromeShellDelegate::instance_ = NULL;
@@ -270,6 +274,10 @@ void ChromeShellDelegate::RecordUserMetricsAction(
case ash::UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON:
content::RecordAction(
content::UserMetricsAction("Launcher_ClickOnApplistButton"));
+#if defined(OS_CHROMEOS)
+ chromeos::default_pinned_apps_field_trial::RecordShelfClick(
+ chromeos::default_pinned_apps_field_trial::APP_LAUNCHER);
+#endif
break;
case ash::UMA_MINIMIZE_PER_KEY:
content::RecordAction(content::UserMetricsAction("Minimize_UsingKey"));
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
index f449388..c44eab4 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
@@ -72,14 +72,16 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/corewm/window_animations.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+#endif
+
using extensions::Extension;
+using extension_misc::kGmailAppId;
using content::WebContents;
namespace {
-// The App ID for of the gMail application.
-const char kGmailAppId[] = "pjkljhegncpnkpknbcohdijeoejaedia";
-
std::string GetPrefKeyForRootWindow(aura::RootWindow* root_window) {
gfx::Display display = gfx::Screen::GetScreenFor(
root_window)->GetDisplayNearestWindow(root_window);
@@ -901,6 +903,10 @@ void ChromeLauncherControllerPerApp::ActivateWindowOrMinimizeIfActive(
void ChromeLauncherControllerPerApp::OnBrowserShortcutClicked(
int event_flags) {
+#if defined(OS_CHROMEOS)
+ chromeos::default_pinned_apps_field_trial::RecordShelfClick(
+ chromeos::default_pinned_apps_field_trial::CHROME);
+#endif
if (event_flags & ui::EF_CONTROL_DOWN) {
CreateNewWindow();
return;
@@ -927,7 +933,14 @@ void ChromeLauncherControllerPerApp::ItemSelected(const ash::LauncherItem& item,
return;
}
DCHECK(HasItemController(item.id));
- id_to_item_controller_map_[item.id]->Clicked(event);
+ LauncherItemController* item_controller = id_to_item_controller_map_[item.id];
+#if defined(OS_CHROMEOS)
+ if (!item_controller->app_id().empty()) {
+ chromeos::default_pinned_apps_field_trial::RecordShelfAppClick(
+ item_controller->app_id());
+ }
+#endif
+ item_controller->Clicked(event);
}
int ChromeLauncherControllerPerApp::GetBrowserShortcutResourceId() {
@@ -1300,7 +1313,7 @@ ChromeLauncherControllerPerApp::CreateAppShortcutLauncherItemWithType(
void ChromeLauncherControllerPerApp::UpdateBrowserItemStatus() {
// Determine the new browser's active state and change if necessary.
size_t browser_index = ash::launcher::GetBrowserItemIndex(*model_);
- DCHECK(browser_index >= 0);
+ DCHECK_GE(browser_index, 0u);
ash::LauncherItem browser_item = model_->items()[browser_index];
ash::LauncherItemStatus browser_status = ash::STATUS_CLOSED;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc
index eab87b9..d97c0df 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc
@@ -43,7 +43,6 @@ using extensions::Manifest;
namespace {
const int kExpectedAppIndex = 1;
-const char* gmail_app_id = "pjkljhegncpnkpknbcohdijeoejaedia";
const char* offline_gmail_url = "https://mail.google.com/mail/mu/u";
const char* gmail_url = "https://mail.google.com/mail/u";
}
@@ -187,14 +186,14 @@ class ChromeLauncherControllerPerAppTest : public BrowserWithTestWindowTest {
extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
manifest_gmail,
Extension::NO_FLAGS,
- gmail_app_id,
+ extension_misc::kGmailAppId,
&error);
// Fake search extension.
extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
manifest,
Extension::NO_FLAGS,
- "coobgpohoikkiipiblmjeljniedjpjpf",
+ extension_misc::kGoogleSearchAppId,
&error);
// Create a default launcher controller; some tests will call
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc
index 734035a..8e2eaca 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser.cc
@@ -55,6 +55,10 @@
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
+#endif
+
using content::WebContents;
using extensions::Extension;
@@ -862,6 +866,10 @@ void ChromeLauncherControllerPerBrowser::ActivateWindowOrMinimizeIfActive(
void ChromeLauncherControllerPerBrowser::OnBrowserShortcutClicked(
int event_flags) {
+#if defined(OS_CHROMEOS)
+ chromeos::default_pinned_apps_field_trial::RecordShelfClick(
+ chromeos::default_pinned_apps_field_trial::CHROME);
+#endif
if (event_flags & ui::EF_CONTROL_DOWN) {
CreateNewWindow();
return;
@@ -884,7 +892,14 @@ void ChromeLauncherControllerPerBrowser::ItemSelected(
const ash::LauncherItem& item,
const ui::Event& event) {
DCHECK(HasItemController(item.id));
- id_to_item_controller_map_[item.id]->Clicked(event);
+ LauncherItemController* item_controller = id_to_item_controller_map_[item.id];
+#if defined(OS_CHROMEOS)
+ if (!item_controller->app_id().empty()) {
+ chromeos::default_pinned_apps_field_trial::RecordShelfAppClick(
+ item_controller->app_id());
+ }
+#endif
+ item_controller->Clicked(event);
}
int ChromeLauncherControllerPerBrowser::GetBrowserShortcutResourceId() {
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc
index dea21489..b71fa11 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc
@@ -72,13 +72,13 @@ class ChromeLauncherControllerPerBrowserTest : public testing::Test {
extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
manifest,
Extension::NO_FLAGS,
- "pjkljhegncpnkpknbcohdijeoejaedia",
+ extension_misc::kGmailAppId,
&error);
// Fake search extension.
extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
manifest,
Extension::NO_FLAGS,
- "coobgpohoikkiipiblmjeljniedjpjpf",
+ extension_misc::kGoogleSearchAppId,
&error);
}
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 0180d89..50e8a30 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -388,6 +388,8 @@
'browser/chromeos/login/captive_portal_window_proxy.h',
'browser/chromeos/login/chrome_restart_request.cc',
'browser/chromeos/login/chrome_restart_request.h',
+ 'browser/chromeos/login/default_pinned_apps_field_trial.cc',
+ 'browser/chromeos/login/default_pinned_apps_field_trial.h',
'browser/chromeos/login/default_user_images.cc',
'browser/chromeos/login/default_user_images.h',
'browser/chromeos/login/enrollment/enrollment_screen.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 25f7754..ce7d17a 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -626,6 +626,7 @@
'browser/chromeos/kiosk_mode/kiosk_mode_idle_logout_unittest.cc',
'browser/chromeos/kiosk_mode/kiosk_mode_settings_unittest.cc',
'browser/chromeos/language_preferences_unittest.cc',
+ 'browser/chromeos/login/default_pinned_apps_field_trial_unittest.cc',
'browser/chromeos/login/existing_user_controller_auto_login_unittest.cc',
'browser/chromeos/login/hwid_checker_unittest.cc',
'browser/chromeos/login/merge_session_load_page_unittest.cc',
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index c6e8847..844197b 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -105,7 +105,7 @@ const char kGeneratedBackgroundPageFilename[] =
const char kModulesDir[] = "_modules";
-}
+} // namespace extension_filenames
// These must match the values expected by the chrome.management extension API.
namespace extension_info_keys {
@@ -124,11 +124,20 @@ namespace extension_info_keys {
} // namespace extension_filenames
namespace extension_misc {
+
const char kBookmarkManagerId[] = "eemcgdkfndhakfknompkggombfjjjeno";
+const char kChromeAppId[] = "mgndgikekgjfcpckkfioiadnlibdjbkf";
const char kCitrixReceiverAppId[] = "haiffjcadagjlijoggckpgfnoeiflnem";
const char kCitrixReceiverAppBetaId[] = "gnedhmakppccajfpfiihfcdlnpgomkcf";
const char kCitrixReceiverAppDevId[] = "fjcibdnjlbfnbfdjneajpipnlcppleek";
+const char kCloudPrintAppId[] = "mfehgcgbbipciphmccgaenjidiccnmng";
const char kEnterpriseWebStoreAppId[] = "afchcafgojfnemjkcbhfekplkmjaldaa";
+const char kGmailAppId[] = "pjkljhegncpnkpknbcohdijeoejaedia";
+const char kGoogleDocAppId[] = "aohghmighlieiainnegkcijnfilokake";
+const char kGooglePlayMusicAppId[] = "icppfcnhkcmnfdhfhphakoifcfokfdhg";
+const char kGoogleSearchAppId[] = "coobgpohoikkiipiblmjeljniedjpjpf";
+const char kGoogleSheetsAppId[] = "felcaaldnbdncclmgdcncolpebgiejap";
+const char kGoogleSlidesAppId[] = "aapocclcgogkmnckokdopfmhonfmgoek";
const char kHTermAppId[] = "pnhechapfaindjhompbnflcldabbghjo";
const char kHTermDevAppId[] = "okddffdblfhhnmhodogpojmfkjmhinfp";
const char kCroshBuiltinAppId[] = "nkoccljplnhpfnfiajclkommnmllphnl";
@@ -136,12 +145,12 @@ const char kQuickOfficeComponentExtensionId[] =
"bpmcpldpdmajfigpchkicefoigmkfalc";
const char kQuickOfficeDevExtensionId[] = "ionpfmkccalenbmnddpbmocokhaknphg";
const char kQuickOfficeExtensionId[] = "gbkeegbaiigmenfmjfclcdgdpimamgkj";
+const char kSettingsAppId[] = "ennkphjdgehloodpbhlhldgbnhmacadg";
const char kStreamsPrivateTestExtensionId[] =
"oickdpebdnfbgkcaoklfcdhjniefkcji";
const char kWebStoreAppId[] = "ahfgeienlihckogmohjhadlkjgocpleb";
-const char kCloudPrintAppId[] = "mfehgcgbbipciphmccgaenjidiccnmng";
-const char kChromeAppId[] = "mgndgikekgjfcpckkfioiadnlibdjbkf";
-const char kSettingsAppId[] = "ennkphjdgehloodpbhlhldgbnhmacadg";
+const char kYoutubeAppId[] = "blpcfgokakmgnkcojhhkbfbldkacnbeo";
+
const char kAppLaunchHistogram[] = "Extensions.AppLaunch";
const char kPlatformAppLaunchHistogram[] = "Apps.AppLaunch";
#if defined(OS_CHROMEOS)
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 8ce965f..9566f17 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -94,6 +94,9 @@ namespace extension_misc {
// The extension id of the bookmark manager.
extern const char kBookmarkManagerId[];
+ // The extension id of the Chrome component application.
+ extern const char kChromeAppId[];
+
// The extension id of the Citrix Receiver application.
extern const char kCitrixReceiverAppId[];
@@ -103,9 +106,30 @@ namespace extension_misc {
// The extension id of the dev Citrix Receiver application.
extern const char kCitrixReceiverAppDevId[];
+ // The extension id of the Cloud Print component application.
+ extern const char kCloudPrintAppId[];
+
// The extension id of the Enterprise Web Store component application.
extern const char kEnterpriseWebStoreAppId[];
+ // The extension id of GMail application.
+ extern const char kGmailAppId[];
+
+ // The extension id of the Google Doc application.
+ extern const char kGoogleDocAppId[];
+
+ // The extension id of the Google Play Music application.
+ extern const char kGooglePlayMusicAppId[];
+
+ // The extension id of the Google Search application.
+ extern const char kGoogleSearchAppId[];
+
+ // The extension id of the Google Sheets application.
+ extern const char kGoogleSheetsAppId[];
+
+ // The extension id of the Google Slides application.
+ extern const char kGoogleSlidesAppId[];
+
// The extension id of the HTerm app for ChromeOS.
extern const char kHTermAppId[];
@@ -124,20 +148,17 @@ namespace extension_misc {
// The extension id of the Office Viewer extension.
extern const char kQuickOfficeExtensionId[];
+ // The extension id of the settings application.
+ extern const char kSettingsAppId[];
+
// The extension id used for testing streamsPrivate
extern const char kStreamsPrivateTestExtensionId[];
// The extension id of the Web Store component application.
extern const char kWebStoreAppId[];
- // The extension id of the Cloud Print component application.
- extern const char kCloudPrintAppId[];
-
- // The extension id of the Chrome component application.
- extern const char kChromeAppId[];
-
- // The extension id of the settings application.
- extern const char kSettingsAppId[];
+ // The extension id of the Youtube application.
+ extern const char kYoutubeAppId[];
// Note: this structure is an ASN.1 which encodes the algorithm used
// with its parameters. This is defined in PKCS #1 v2.1 (RFC 3447).
@@ -305,7 +326,6 @@ namespace extension_misc {
// List of sizes for extension icons that can be defined in the manifest.
extern const int kScriptBadgeIconSizes[];
extern const size_t kNumScriptBadgeIconSizes;
-
-} // extension_misc
+} // namespace extension_misc
#endif // CHROME_COMMON_EXTENSIONS_EXTENSION_CONSTANTS_H_
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 524912e..5952c4c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -459,6 +459,10 @@ other types of suffix sets.
</summary>
</histogram>
+<histogram name="Cros.ClickOnShelf" enum="CrosShelfClickTarget">
+ <summary>Chrome OS shelf clicks.</summary>
+</histogram>
+
<histogram name="CrosDisks.ArchiveType" enum="CrosDisksArchiveType">
<summary>
The type of archive file that Chrome OS cros-disks daemon is requested to
@@ -7680,6 +7684,18 @@ other types of suffix sets.
<int value="0" label="ModemManagerCommandSendFailure"/>
</enum>
+<enum name="CrosShelfClickTarget" type="int">
+ <int value="0" label="Chrome"/>
+ <int value="1" label="AppLauncher"/>
+ <int value="2" label="Gmail"/>
+ <int value="3" label="Search"/>
+ <int value="4" label="Youtube"/>
+ <int value="5" label="Doc"/>
+ <int value="6" label="Sheets"/>
+ <int value="7" label="Slides"/>
+ <int value="8" label="PlayMusic"/>
+</enum>
+
<enum name="DomainBoundCerts.GetCertResult" type="int">
<int value="0" label="SYNC_SUCCESS"/>
<int value="1" label="ASYNC_SUCCESS"/>
@@ -10933,6 +10949,13 @@ other types of suffix sets.
<affected-histogram name="PLT.LoadType"/>
</fieldtrial>
+<fieldtrial name="DefaultPinnedApps">
+ <group name="Existing"/>
+ <group name="Control"/>
+ <group name="Alternate"/>
+ <affected-histogram name="Cros.ClickOnShelf"/>
+</fieldtrial>
+
<fieldtrial name="DnsImpact2">
<group name="disabled_prefetch"
label="DNS pre-resolving is disabled in these clients"/>