1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h"
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/sha1.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/flags_storage.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/signin/core/browser/signin_manager.h"
20 #include "components/sync_driver/pref_names.h"
21 #include "components/variations/variations_associated_data.h"
22 #include "extensions/common/features/feature.h"
23 #include "extensions/common/features/feature_provider.h"
27 const char kFieldTrialName
[] = "EnhancedBookmarks";
29 // Get extension id from Finch EnhancedBookmarks group parameters.
30 std::string
GetEnhancedBookmarksExtensionIdFromFinch() {
31 return variations::GetVariationParamValue(kFieldTrialName
, "id");
34 // Returns true if enhanced bookmarks experiment is enabled from Finch.
35 bool IsEnhancedBookmarksExperimentEnabledFromFinch() {
36 const std::string ext_id
= GetEnhancedBookmarksExtensionIdFromFinch();
37 #if defined(OS_ANDROID)
38 return !ext_id
.empty();
40 const extensions::FeatureProvider
* feature_provider
=
41 extensions::FeatureProvider::GetPermissionFeatures();
42 extensions::Feature
* feature
= feature_provider
->GetFeature("metricsPrivate");
43 return feature
&& feature
->IsIdInWhitelist(ext_id
);
49 bool GetBookmarksExperimentExtensionID(const PrefService
* user_prefs
,
50 std::string
* extension_id
) {
51 BookmarksExperimentState bookmarks_experiment_state
=
52 static_cast<BookmarksExperimentState
>(user_prefs
->GetInteger(
53 sync_driver::prefs::kEnhancedBookmarksExperimentEnabled
));
54 if (bookmarks_experiment_state
== BOOKMARKS_EXPERIMENT_ENABLED_FROM_FINCH
) {
55 *extension_id
= GetEnhancedBookmarksExtensionIdFromFinch();
56 return !extension_id
->empty();
58 if (bookmarks_experiment_state
== BOOKMARKS_EXPERIMENT_ENABLED
) {
59 *extension_id
= user_prefs
->GetString(
60 sync_driver::prefs::kEnhancedBookmarksExtensionId
);
61 return !extension_id
->empty();
67 void UpdateBookmarksExperimentState(
68 PrefService
* user_prefs
,
69 PrefService
* local_state
,
71 BookmarksExperimentState experiment_enabled_from_sync
) {
72 PrefService
* flags_storage
= local_state
;
73 #if defined(OS_CHROMEOS)
74 // Chrome OS is using user prefs for flags storage.
75 flags_storage
= user_prefs
;
78 BookmarksExperimentState bookmarks_experiment_state_before
=
79 static_cast<BookmarksExperimentState
>(user_prefs
->GetInteger(
80 sync_driver::prefs::kEnhancedBookmarksExperimentEnabled
));
81 // If user signed out, clear possible previous state.
82 if (!user_signed_in
) {
83 bookmarks_experiment_state_before
= BOOKMARKS_EXPERIMENT_NONE
;
84 ForceFinchBookmarkExperimentIfNeeded(flags_storage
,
85 BOOKMARKS_EXPERIMENT_NONE
);
88 // kEnhancedBookmarksExperiment flag could have values "", "1" and "0".
89 // "0" - user opted out.
90 bool opt_out
= base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
91 switches::kEnhancedBookmarksExperiment
) == "0";
93 BookmarksExperimentState bookmarks_experiment_new_state
=
94 BOOKMARKS_EXPERIMENT_NONE
;
96 if (IsEnhancedBookmarksExperimentEnabledFromFinch() && !user_signed_in
) {
98 // Experiment enabled but user opted out.
99 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_OPT_OUT_FROM_FINCH
;
101 // Experiment enabled.
102 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_ENABLED_FROM_FINCH
;
104 } else if (experiment_enabled_from_sync
== BOOKMARKS_EXPERIMENT_ENABLED
) {
105 // Experiment enabled from Chrome sync.
107 // Experiment enabled but user opted out.
108 bookmarks_experiment_new_state
=
109 BOOKMARKS_EXPERIMENT_ENABLED_USER_OPT_OUT
;
111 // Experiment enabled.
112 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_ENABLED
;
114 } else if (experiment_enabled_from_sync
== BOOKMARKS_EXPERIMENT_NONE
) {
115 // Experiment is not enabled from Chrome sync.
116 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_NONE
;
117 } else if (bookmarks_experiment_state_before
==
118 BOOKMARKS_EXPERIMENT_ENABLED
) {
120 // Experiment enabled but user opted out.
121 bookmarks_experiment_new_state
=
122 BOOKMARKS_EXPERIMENT_ENABLED_USER_OPT_OUT
;
124 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_ENABLED
;
126 } else if (bookmarks_experiment_state_before
==
127 BOOKMARKS_EXPERIMENT_ENABLED_USER_OPT_OUT
) {
129 bookmarks_experiment_new_state
=
130 BOOKMARKS_EXPERIMENT_ENABLED_USER_OPT_OUT
;
132 // User opted in again.
133 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_ENABLED
;
137 #if defined(OS_ANDROID)
138 bool opt_in
= !opt_out
&&
139 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
140 switches::kEnhancedBookmarksExperiment
) == "1";
141 if (opt_in
&& bookmarks_experiment_new_state
== BOOKMARKS_EXPERIMENT_NONE
)
142 bookmarks_experiment_new_state
= BOOKMARKS_EXPERIMENT_ENABLED
;
145 UMA_HISTOGRAM_ENUMERATION("EnhancedBookmarks.SyncExperimentState",
146 bookmarks_experiment_new_state
,
147 BOOKMARKS_EXPERIMENT_ENUM_SIZE
);
148 user_prefs
->SetInteger(
149 sync_driver::prefs::kEnhancedBookmarksExperimentEnabled
,
150 bookmarks_experiment_new_state
);
151 ForceFinchBookmarkExperimentIfNeeded(flags_storage
,
152 bookmarks_experiment_new_state
);
155 void InitBookmarksExperimentState(Profile
* profile
) {
156 SigninManagerBase
* signin
= SigninManagerFactory::GetForProfile(profile
);
157 bool is_signed_in
= signin
&& signin
->IsAuthenticated();
158 UpdateBookmarksExperimentState(
160 g_browser_process
->local_state(),
162 BOOKMARKS_EXPERIMENT_ENABLED_FROM_SYNC_UNKNOWN
);
165 void ForceFinchBookmarkExperimentIfNeeded(
166 PrefService
* flags_storage
,
167 BookmarksExperimentState bookmarks_experiment_state
) {
170 ListPrefUpdate
update(flags_storage
, prefs::kEnabledLabsExperiments
);
171 base::ListValue
* experiments_list
= update
.Get();
172 if (!experiments_list
)
175 if (bookmarks_experiment_state
== BOOKMARKS_EXPERIMENT_NONE
) {
176 experiments_list
->Remove(
177 base::StringValue(switches::kManualEnhancedBookmarks
), &index
);
178 experiments_list
->Remove(
179 base::StringValue(switches::kManualEnhancedBookmarksOptout
), &index
);
180 } else if (bookmarks_experiment_state
== BOOKMARKS_EXPERIMENT_ENABLED
) {
181 experiments_list
->Remove(
182 base::StringValue(switches::kManualEnhancedBookmarksOptout
), &index
);
183 experiments_list
->AppendIfNotPresent(
184 new base::StringValue(switches::kManualEnhancedBookmarks
));
185 } else if (bookmarks_experiment_state
==
186 BOOKMARKS_EXPERIMENT_ENABLED_USER_OPT_OUT
) {
187 experiments_list
->Remove(
188 base::StringValue(switches::kManualEnhancedBookmarks
), &index
);
189 experiments_list
->AppendIfNotPresent(
190 new base::StringValue(switches::kManualEnhancedBookmarksOptout
));
194 bool IsEnhancedBookmarksExperimentEnabled(
195 about_flags::FlagsStorage
* flags_storage
) {
196 #if defined(OS_CHROMEOS)
197 // We are not setting command line flags on Chrome OS to avoid browser restart
198 // but still have flags in flags_storage. So check flags_storage instead.
199 const std::set
<std::string
> flags
= flags_storage
->GetFlags();
200 if (flags
.find(switches::kManualEnhancedBookmarks
) != flags
.end())
202 if (flags
.find(switches::kManualEnhancedBookmarksOptout
) != flags
.end())
205 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
206 if (command_line
->HasSwitch(switches::kManualEnhancedBookmarks
) ||
207 command_line
->HasSwitch(switches::kManualEnhancedBookmarksOptout
)) {
212 return IsEnhancedBookmarksExperimentEnabledFromFinch();
215 #if defined(OS_ANDROID)
216 bool IsEnhancedBookmarkImageFetchingEnabled(const PrefService
* user_prefs
) {
217 if (IsEnhancedBookmarksEnabled(user_prefs
))
220 // Salient images are collected from visited bookmarked pages even if the
221 // enhanced bookmark feature is turned off. This is to have some images
222 // available so that in the future, when the feature is turned on, the user
223 // experience is not a big list of flat colors. However as a precautionary
224 // measure it is possible to disable this collection of images from finch.
225 std::string disable_fetching
= variations::GetVariationParamValue(
226 kFieldTrialName
, "DisableImagesFetching");
227 return disable_fetching
.empty();
230 bool IsEnhancedBookmarksEnabled(const PrefService
* user_prefs
) {
231 BookmarksExperimentState bookmarks_experiment_state
=
232 static_cast<BookmarksExperimentState
>(user_prefs
->GetInteger(
233 sync_driver::prefs::kEnhancedBookmarksExperimentEnabled
));
234 return bookmarks_experiment_state
== BOOKMARKS_EXPERIMENT_ENABLED
||
235 bookmarks_experiment_state
== BOOKMARKS_EXPERIMENT_ENABLED_FROM_FINCH
;
239 bool IsEnableDomDistillerSet() {
240 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
241 switches::kEnableDomDistiller
)) {
244 if (variations::GetVariationParamValue(
245 kFieldTrialName
, "enable-dom-distiller") == "1")
251 bool IsEnableSyncArticlesSet() {
252 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
253 switches::kEnableSyncArticles
)) {
256 if (variations::GetVariationParamValue(
257 kFieldTrialName
, "enable-sync-articles") == "1")