| Index: chrome/browser/ui/webui/sync_promo_handler2.cc
|
| diff --git a/chrome/browser/ui/webui/sync_promo_handler2.cc b/chrome/browser/ui/webui/sync_promo_handler2.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9788d451a0b9176f5b4c5776cee72fa18c5cef93
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/webui/sync_promo_handler2.cc
|
| @@ -0,0 +1,288 @@
|
| +// 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.
|
| +
|
| +#include "chrome/browser/ui/webui/sync_promo_handler2.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/time.h"
|
| +#include "chrome/browser/prefs/pref_service.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/sync/profile_sync_service.h"
|
| +#include "chrome/browser/sync/sync_setup_flow.h"
|
| +#include "chrome/browser/tabs/tab_strip_model.h"
|
| +#include "chrome/browser/ui/browser.h"
|
| +#include "chrome/browser/ui/browser_list.h"
|
| +#include "chrome/browser/ui/webui/sync_promo_trial.h"
|
| +#include "chrome/browser/ui/webui/sync_promo_ui.h"
|
| +#include "chrome/common/chrome_notification_types.h"
|
| +#include "chrome/common/extensions/extension_constants.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "chrome/common/url_constants.h"
|
| +#include "content/browser/tab_contents/tab_contents.h"
|
| +#include "content/public/browser/notification_details.h"
|
| +#include "content/public/browser/notification_service.h"
|
| +
|
| +namespace {
|
| +
|
| +// User actions on the sync promo (aka "Sign in to Chrome").
|
| +enum SyncPromoUserFlowActionEnums {
|
| + SYNC_PROMO_VIEWED,
|
| + SYNC_PROMO_LEARN_MORE_CLICKED,
|
| + SYNC_PROMO_ACCOUNT_HELP_CLICKED,
|
| + SYNC_PROMO_CREATE_ACCOUNT_CLICKED,
|
| + SYNC_PROMO_SKIP_CLICKED,
|
| + SYNC_PROMO_SIGN_IN_ATTEMPTED,
|
| + SYNC_PROMO_SIGNED_IN_SUCCESSFULLY,
|
| + SYNC_PROMO_ADVANCED_CLICKED,
|
| + SYNC_PROMO_ENCRYPTION_HELP_CLICKED,
|
| + SYNC_PROMO_CANCELLED_AFTER_SIGN_IN,
|
| + SYNC_PROMO_CONFIRMED_AFTER_SIGN_IN,
|
| + SYNC_PROMO_CLOSED_TAB,
|
| + SYNC_PROMO_CLOSED_WINDOW,
|
| + SYNC_PROMO_LEFT_DURING_THROBBER,
|
| + SYNC_PROMO_BUCKET_BOUNDARY,
|
| + SYNC_PROMO_FIRST_VALID_JS_ACTION = SYNC_PROMO_LEARN_MORE_CLICKED,
|
| + SYNC_PROMO_LAST_VALID_JS_ACTION = SYNC_PROMO_CONFIRMED_AFTER_SIGN_IN,
|
| +};
|
| +
|
| +// This was added because of the need to change the existing UMA enum for the
|
| +// sync promo mid-flight. Ideally these values would be contiguous, but the
|
| +// real world is not always ideal.
|
| +static bool IsValidUserFlowAction(int action) {
|
| + return (action >= SYNC_PROMO_FIRST_VALID_JS_ACTION &&
|
| + action <= SYNC_PROMO_LAST_VALID_JS_ACTION) ||
|
| + action == SYNC_PROMO_LEFT_DURING_THROBBER;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +SyncPromoHandler2::SyncPromoHandler2(ProfileManager* profile_manager)
|
| + : SyncSetupHandler2(profile_manager),
|
| + window_already_closed_(false) {
|
| +}
|
| +
|
| +SyncPromoHandler2::~SyncPromoHandler2() {
|
| +}
|
| +
|
| +// static
|
| +void SyncPromoHandler2::RegisterUserPrefs(PrefService* prefs) {
|
| + prefs->RegisterIntegerPref(prefs::kSyncPromoViewCount, 0,
|
| + PrefService::UNSYNCABLE_PREF);
|
| + prefs->RegisterBooleanPref(prefs::kSyncPromoShowNTPBubble, false,
|
| + PrefService::UNSYNCABLE_PREF);
|
| +}
|
| +
|
| +WebUIMessageHandler* SyncPromoHandler2::Attach(WebUI* web_ui) {
|
| + DCHECK(web_ui);
|
| + // Keep a reference to the preferences service for convenience and it's
|
| + // probably a little faster that getting it via Profile::FromWebUI() every
|
| + // time we need to interact with preferences.
|
| + prefs_ = Profile::FromWebUI(web_ui)->GetPrefs();
|
| + DCHECK(prefs_);
|
| + // Ignore events from view-source:chrome://syncpromo.
|
| + if (!web_ui->tab_contents()->controller().GetActiveEntry()->
|
| + IsViewSourceMode()) {
|
| + // Listen to see if the tab we're in gets closed.
|
| + registrar_.Add(this, content::NOTIFICATION_TAB_CLOSING,
|
| + content::Source<NavigationController>(
|
| + &web_ui->tab_contents()->controller()));
|
| + // Listen to see if the window we're in gets closed.
|
| + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSING,
|
| + content::NotificationService::AllSources());
|
| + }
|
| + return SyncSetupHandler2::Attach(web_ui);
|
| +}
|
| +
|
| +void SyncPromoHandler2::RegisterMessages() {
|
| + web_ui_->RegisterMessageCallback("SyncPromo:Close",
|
| + base::Bind(&SyncPromoHandler2::HandleCloseSyncPromo,
|
| + base::Unretained(this)));
|
| + web_ui_->RegisterMessageCallback("SyncPromo:Initialize",
|
| + base::Bind(&SyncPromoHandler2::HandleInitializeSyncPromo,
|
| + base::Unretained(this)));
|
| + web_ui_->RegisterMessageCallback("SyncPromo:RecordSignInAttempts",
|
| + base::Bind(&SyncPromoHandler2::HandleRecordSignInAttempts,
|
| + base::Unretained(this)));
|
| + web_ui_->RegisterMessageCallback("SyncPromo:RecordThrobberTime",
|
| + base::Bind(&SyncPromoHandler2::HandleRecordThrobberTime,
|
| + base::Unretained(this)));
|
| + web_ui_->RegisterMessageCallback("SyncPromo:ShowAdvancedSettings",
|
| + base::Bind(&SyncPromoHandler2::HandleShowAdvancedSettings,
|
| + base::Unretained(this)));
|
| + web_ui_->RegisterMessageCallback("SyncPromo:UserFlowAction",
|
| + base::Bind(&SyncPromoHandler2::HandleUserFlowAction,
|
| + base::Unretained(this)));
|
| + web_ui_->RegisterMessageCallback("SyncPromo:UserSkipped",
|
| + base::Bind(&SyncPromoHandler2::HandleUserSkipped,
|
| + base::Unretained(this)));
|
| + SyncSetupHandler2::RegisterMessages();
|
| +}
|
| +
|
| +void SyncPromoHandler2::ShowGaiaSuccessAndClose() {
|
| + if (sync_promo_trial::IsExperimentActive())
|
| + sync_promo_trial::RecordUserSignedIn();
|
| +
|
| + SyncSetupHandler2::ShowGaiaSuccessAndClose();
|
| +}
|
| +
|
| +void SyncPromoHandler2::ShowGaiaSuccessAndSettingUp() {
|
| + if (sync_promo_trial::IsExperimentActive())
|
| + sync_promo_trial::RecordUserSignedIn();
|
| +
|
| + SyncSetupHandler2::ShowGaiaSuccessAndSettingUp();
|
| +}
|
| +
|
| +void SyncPromoHandler2::ShowConfigure(const base::DictionaryValue& args) {
|
| + bool usePassphrase = false;
|
| + args.GetBoolean("usePassphrase", &usePassphrase);
|
| +
|
| + if (usePassphrase) {
|
| + // If a passphrase is required then we must show the configure pane.
|
| + SyncSetupHandler2::ShowConfigure(args);
|
| + } else {
|
| + // If no passphrase is required then skip the configure pane and sync
|
| + // everything by default. This makes the first run experience simpler.
|
| + // Note, there's an advanced link in the sync promo that takes users
|
| + // to Settings where the configure pane is not skipped.
|
| + SyncConfiguration configuration;
|
| + configuration.sync_everything = true;
|
| + DCHECK(flow());
|
| + flow()->OnUserConfigured(configuration);
|
| + }
|
| +}
|
| +
|
| +void SyncPromoHandler2::Observe(int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| + switch (type) {
|
| + case content::NOTIFICATION_TAB_CLOSING: {
|
| + if (!window_already_closed_)
|
| + RecordUserFlowAction(SYNC_PROMO_CLOSED_TAB);
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_BROWSER_CLOSING: {
|
| + // Make sure we're in the tab strip of the closing window.
|
| + Browser* browser = content::Source<Browser>(source).ptr();
|
| + if (browser->tabstrip_model()->GetWrapperIndex(
|
| + web_ui_->tab_contents()) != TabStripModel::kNoTab) {
|
| + RecordUserFlowAction(SYNC_PROMO_CLOSED_WINDOW);
|
| + window_already_closed_ = true;
|
| + }
|
| + break;
|
| + }
|
| + default: {
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +}
|
| +
|
| +void SyncPromoHandler2::StepWizardForShowSetupUI() {
|
| + ProfileSyncService* service =
|
| + Profile::FromWebUI(web_ui_)->GetProfileSyncService();
|
| + service->get_wizard().Step(SyncSetupWizard::GetLoginState());
|
| +}
|
| +
|
| +void SyncPromoHandler2::ShowSetupUI() {
|
| + // We don't need to do anything here; The UI for the sync promo is already
|
| + // displayed.
|
| +}
|
| +
|
| +void SyncPromoHandler2::HandleCloseSyncPromo(const base::ListValue* args) {
|
| + CloseSyncSetup();
|
| +
|
| + // If the user has signed in then set the pref to show them NTP bubble
|
| + // confirming that they're signed in.
|
| + std::string username = prefs_->GetString(prefs::kGoogleServicesUsername);
|
| + if (!username.empty())
|
| + prefs_->SetBoolean(prefs::kSyncPromoShowNTPBubble, true);
|
| +
|
| + GURL url = SyncPromoUI::GetNextPageURLForSyncPromoURL(
|
| + web_ui_->tab_contents()->GetURL());
|
| + web_ui_->tab_contents()->OpenURL(url, GURL(), CURRENT_TAB,
|
| + content::PAGE_TRANSITION_LINK);
|
| +}
|
| +
|
| +void SyncPromoHandler2::HandleInitializeSyncPromo(const base::ListValue* args) {
|
| + // If the promo is also the Chrome launch page, we want to show the title and
|
| + // log an event if we are running an experiment.
|
| + bool is_launch_page = SyncPromoUI::GetIsLaunchPageForSyncPromoURL(
|
| + web_ui_->tab_contents()->GetURL());
|
| + if (is_launch_page && sync_promo_trial::IsExperimentActive())
|
| + sync_promo_trial::RecordUserSawMessage();
|
| + base::FundamentalValue visible(is_launch_page);
|
| + web_ui_->CallJavascriptFunction("SyncSetupOverlay.setPromoTitleVisible",
|
| + visible);
|
| +
|
| + OpenSyncSetup();
|
| + // We don't need to compute anything for this, just do this every time.
|
| + RecordUserFlowAction(SYNC_PROMO_VIEWED);
|
| + // Increment view count first and show natural numbers in stats rather than 0
|
| + // based starting point (if it happened to be our first time showing this).
|
| + IncrementViewCountBy(1);
|
| + // Record +1 for every view. This is the only thing we record that's not part
|
| + // of the user flow histogram.
|
| + UMA_HISTOGRAM_COUNTS("SyncPromo.NumTimesViewed", GetViewCount());
|
| +}
|
| +
|
| +void SyncPromoHandler2::HandleShowAdvancedSettings(
|
| + const base::ListValue* args) {
|
| + CloseSyncSetup();
|
| + std::string url(chrome::kChromeUISettingsURL);
|
| + url += chrome::kSyncSetupSubPage;
|
| + web_ui_->tab_contents()->OpenURL(GURL(url), GURL(), CURRENT_TAB,
|
| + content::PAGE_TRANSITION_LINK);
|
| + RecordUserFlowAction(SYNC_PROMO_ADVANCED_CLICKED);
|
| +}
|
| +
|
| +// TODO(dbeam): Replace with metricsHandler:recordHistogramTime when it exists.
|
| +void SyncPromoHandler2::HandleRecordThrobberTime(const base::ListValue* args) {
|
| + double time_double;
|
| + CHECK(args->GetDouble(0, &time_double));
|
| + UMA_HISTOGRAM_TIMES("SyncPromo.ThrobberTime",
|
| + base::TimeDelta::FromMilliseconds(time_double));
|
| +}
|
| +
|
| +// TODO(dbeam): Replace with metricsHandler:recordHistogramCount when it exists.
|
| +void SyncPromoHandler2::HandleRecordSignInAttempts(const base::ListValue* args) {
|
| + double count_double;
|
| + CHECK(args->GetDouble(0, &count_double));
|
| + UMA_HISTOGRAM_COUNTS("SyncPromo.SignInAttempts", count_double);
|
| +}
|
| +
|
| +void SyncPromoHandler2::HandleUserFlowAction(const base::ListValue* args) {
|
| + double action_double;
|
| + CHECK(args->GetDouble(0, &action_double));
|
| + int action = static_cast<int>(action_double);
|
| +
|
| + if (IsValidUserFlowAction(action))
|
| + RecordUserFlowAction(action);
|
| + else
|
| + NOTREACHED() << "Attempt to record invalid user flow action on sync promo.";
|
| +}
|
| +
|
| +void SyncPromoHandler2::HandleUserSkipped(const base::ListValue* args) {
|
| + SyncPromoUI::SetUserSkippedSyncPromo(Profile::FromWebUI(web_ui_));
|
| + RecordUserFlowAction(SYNC_PROMO_SKIP_CLICKED);
|
| +}
|
| +
|
| +int SyncPromoHandler2::GetViewCount() const {
|
| + // The locally persistent number of times the user has seen the sync promo.
|
| + return prefs_->GetInteger(prefs::kSyncPromoViewCount);
|
| +}
|
| +
|
| +int SyncPromoHandler2::IncrementViewCountBy(unsigned int amount) {
|
| + // Let the user increment by 0 if they really want. It might be useful for a
|
| + // weird way of sending preference change notifications...
|
| + int adjusted = GetViewCount() + amount;
|
| + prefs_->SetInteger(prefs::kSyncPromoViewCount, adjusted);
|
| + return adjusted;
|
| +}
|
| +
|
| +void SyncPromoHandler2::RecordUserFlowAction(int action) {
|
| + // Send an enumeration to our single user flow histogram.
|
| + UMA_HISTOGRAM_ENUMERATION("SyncPromo.UserFlow", action,
|
| + SYNC_PROMO_BUCKET_BOUNDARY);
|
| +}
|
|
|