Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3161)

Unified Diff: chrome/browser/ui/passwords/password_bubble_experiment.cc

Issue 1022843003: New smart passsword bubble algorithm. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mac Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/passwords/password_bubble_experiment.cc
diff --git a/chrome/browser/ui/passwords/password_bubble_experiment.cc b/chrome/browser/ui/passwords/password_bubble_experiment.cc
index 276a038e6a4e20cef8503e302217bc8bb390dbad..dc1bcc1312fb1065fb33beab4a873392d6f481e7 100644
--- a/chrome/browser/ui/passwords/password_bubble_experiment.cc
+++ b/chrome/browser/ui/passwords/password_bubble_experiment.cc
@@ -6,9 +6,7 @@
#include "base/metrics/field_trial.h"
#include "base/prefs/pref_service.h"
-#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/time/time.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/variations/variations_associated_data.h"
@@ -16,190 +14,44 @@
namespace password_bubble_experiment {
namespace {
-bool IsNegativeEvent(password_manager::metrics_util::UIDismissalReason reason) {
- return (reason == password_manager::metrics_util::NO_DIRECT_INTERACTION ||
- reason == password_manager::metrics_util::CLICKED_NOPE ||
- reason == password_manager::metrics_util::CLICKED_NEVER);
-}
-
-// "TimeSpan" experiment -----------------------------------------------------
-
-bool ExtractTimeSpanParams(base::TimeDelta* time_delta, int* nopes_limit) {
- std::map<std::string, std::string> params;
- bool retrieved = variations::GetVariationParams(kExperimentName, &params);
- if (!retrieved)
- return false;
- int days = 0;
- if (!base::StringToInt(params[kParamTimeSpan], &days) ||
- !base::StringToInt(params[kParamTimeSpanNopeThreshold], nopes_limit))
- return false;
- *time_delta = base::TimeDelta::FromDays(days);
- return true;
-}
-
-bool OverwriteTimeSpanPrefsIfNeeded(PrefService* prefs,
- base::TimeDelta time_span) {
- base::Time beginning = base::Time::FromInternalValue(
- prefs->GetInt64(prefs::kPasswordBubbleTimeStamp));
- base::Time now = base::Time::Now();
- if (beginning + time_span < now) {
- prefs->SetInt64(prefs::kPasswordBubbleTimeStamp, now.ToInternalValue());
- prefs->SetInteger(prefs::kPasswordBubbleNopesCount, 0);
- return true;
- }
- return false;
-}
-
-// If user dismisses the bubble >= kParamTimeSpanNopeThreshold times during
-// kParamTimeSpan days then the bubble isn't shown until the end of this time
-// span.
-bool ShouldShowBubbleTimeSpanExperiment(PrefService* prefs) {
- base::TimeDelta time_span;
- int nopes_limit = 0;
- if (!ExtractTimeSpanParams(&time_span, &nopes_limit)) {
- VLOG(2) << "Can't read parameters for "
- << kExperimentName << " experiment";
- return true;
- }
- // Check if the new time span has started.
- if (OverwriteTimeSpanPrefsIfNeeded(prefs, time_span))
- return true;
- int current_nopes = prefs->GetInteger(prefs::kPasswordBubbleNopesCount);
- return current_nopes < nopes_limit;
-}
-
-// Increase the "Nope" counter in prefs and start a new time span if needed.
-void UpdateTimeSpanPrefs(
- PrefService* prefs,
- password_manager::metrics_util::UIDismissalReason reason) {
- if (!IsNegativeEvent(reason))
- return;
- base::TimeDelta time_span;
- int nopes_limit = 0;
- if (!ExtractTimeSpanParams(&time_span, &nopes_limit)) {
- VLOG(2) << "Can't read parameters for "
- << kExperimentName << " experiment";
- return;
- }
- OverwriteTimeSpanPrefsIfNeeded(prefs, time_span);
- int current_nopes = prefs->GetInteger(prefs::kPasswordBubbleNopesCount);
- prefs->SetInteger(prefs::kPasswordBubbleNopesCount, current_nopes + 1);
-}
-
-// "Probability" experiment --------------------------------------------------
-
-bool ExtractProbabilityParams(unsigned* history_length, unsigned* saves) {
- std::map<std::string, std::string> params;
- bool retrieved = variations::GetVariationParams(kExperimentName, &params);
- if (!retrieved)
- return false;
- return base::StringToUint(params[kParamProbabilityInteractionsCount],
- history_length) &&
- base::StringToUint(params[kParamProbabilityFakeSaves], saves);
-}
-
-std::vector<int> ReadInteractionHistory(PrefService* prefs) {
- std::vector<int> interactions;
- const base::ListValue* list =
- prefs->GetList(prefs::kPasswordBubbleLastInteractions);
- if (!list)
- return interactions;
- for (const base::Value* value : *list) {
- int out_value;
- if (value->GetAsInteger(&out_value))
- interactions.push_back(out_value);
- }
- return interactions;
-}
-
-// We keep the history of last kParamProbabilityInteractionsCount interactions
-// with the bubble. We implicitly add kParamProbabilityFakeSaves "Save" clicks.
-// If there are x "Save" clicks among those kParamProbabilityInteractionsCount
-// then the bubble is shown with probability (x + kParamProbabilityFakeSaves)/
-// (kParamProbabilityInteractionsCount + kParamProbabilityFakeSaves).
-bool ShouldShowBubbleProbabilityExperiment(PrefService* prefs) {
- unsigned history_length = 0, fake_saves = 0;
- if (!ExtractProbabilityParams(&history_length, &fake_saves)) {
- VLOG(2) << "Can't read parameters for "
- << kExperimentName << " experiment";
- return true;
- }
- std::vector<int> interactions = ReadInteractionHistory(prefs);
- unsigned real_saves =
- std::count(interactions.begin(), interactions.end(),
- password_manager::metrics_util::CLICKED_SAVE);
- return (interactions.size() + fake_saves) * base::RandDouble() <=
- real_saves + fake_saves;
-}
-
-void UpdateProbabilityPrefs(
- PrefService* prefs,
- password_manager::metrics_util::UIDismissalReason reason) {
- if (!IsNegativeEvent(reason) &&
- reason != password_manager::metrics_util::CLICKED_SAVE)
- return;
- unsigned history_length = 0, fake_saves = 0;
- if (!ExtractProbabilityParams(&history_length, &fake_saves)) {
- VLOG(2) << "Can't read parameters for "
- << kExperimentName << " experiment";
- return;
- }
- std::vector<int> interactions = ReadInteractionHistory(prefs);
- interactions.push_back(reason);
- size_t history_beginning = interactions.size() > history_length ?
- interactions.size() - history_length : 0;
- base::ListValue value;
- for (size_t i = history_beginning; i < interactions.size(); ++i)
- value.AppendInteger(interactions[i]);
- prefs->Set(prefs::kPasswordBubbleLastInteractions, value);
+// Return the number of consecutive times the user clicked "Not now" in the
+// "Save password" bubble.
+int GetCurrentNopesCount(PrefService* prefs) {
+ return prefs->GetInteger(prefs::kPasswordBubbleNopesCount);
}
} // namespace
const char kExperimentName[] = "PasswordBubbleAlgorithm";
-const char kGroupTimeSpanBased[] = "TimeSpan";
-const char kGroupProbabilityBased[] = "Probability";
-const char kParamProbabilityFakeSaves[] = "saves_count";
-const char kParamProbabilityInteractionsCount[] = "last_interactions_count";
-const char kParamTimeSpan[] = "time_span";
-const char kParamTimeSpanNopeThreshold[] = "nope_threshold";
+const char kParamNopeThreshold[] = "consecutive_nope_threshold";
void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) {
- registry->RegisterInt64Pref(
- prefs::kPasswordBubbleTimeStamp,
- 0,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterIntegerPref(
prefs::kPasswordBubbleNopesCount,
0,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
- registry->RegisterListPref(
- prefs::kPasswordBubbleLastInteractions,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
-bool ShouldShowBubble(PrefService* prefs) {
+bool ShouldShowNeverForThisSiteDefault(PrefService* prefs) {
if (!base::FieldTrialList::TrialExists(kExperimentName))
- return true;
- std::string group_name =
- base::FieldTrialList::FindFullName(kExperimentName);
-
- if (group_name == kGroupTimeSpanBased) {
- return ShouldShowBubbleTimeSpanExperiment(prefs);
- }
- if (group_name == kGroupProbabilityBased) {
- return ShouldShowBubbleProbabilityExperiment(prefs);
- }
+ return false;
+ std::string param =
+ variations::GetVariationParamValue(kExperimentName, kParamNopeThreshold);
- // The "Show Always" should be the default case.
- return true;
+ int threshold = 0;
+ return base::StringToInt(param, &threshold) &&
+ GetCurrentNopesCount(prefs) >= threshold;
}
void RecordBubbleClosed(
PrefService* prefs,
password_manager::metrics_util::UIDismissalReason reason) {
- UpdateTimeSpanPrefs(prefs, reason);
- UpdateProbabilityPrefs(prefs, reason);
+ int nopes_count = GetCurrentNopesCount(prefs);
+ if (reason == password_manager::metrics_util::CLICKED_NOPE)
+ nopes_count++;
+ else
+ nopes_count = 0;
vabr (Chromium) 2015/03/24 09:09:04 I'm not sure why clicking "Never" or just abandoni
vasilii 2015/03/24 10:30:53 The case of NO_DIRECT_INTERACTION was discussed wi
vabr (Chromium) 2015/03/24 10:40:59 Fair enough for NO_DIRECT_INTERACTION. To be clear
vasilii 2015/03/24 11:00:04 I changed the algorithm and the test.
+ prefs->SetInteger(prefs::kPasswordBubbleNopesCount, nopes_count);
}
} // namespace password_bubble_experiment

Powered by Google App Engine
This is Rietveld 408576698