Commit 3f73def5 authored by Yulun Wu's avatar Yulun Wu Committed by Commit Bot

Add multipaste nudge metrics.

Bug: 1131573
Change-Id: Idec1dc25f75ddbeb38bde8ecda816a1d7bdd614a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2473677Reviewed-by: default avatarYulun Wu <yulunwu@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Reviewed-by: default avatarAlex Newcomer <newcomer@chromium.org>
Commit-Queue: Yulun Wu <yulunwu@chromium.org>
Auto-Submit: Yulun Wu <yulunwu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822508}
parent 5d8f43e9
......@@ -11,6 +11,7 @@
#include "ash/clipboard/clipboard_history_menu_model_adapter.h"
#include "ash/clipboard/clipboard_history_resource_manager.h"
#include "ash/clipboard/clipboard_history_util.h"
#include "ash/clipboard/clipboard_nudge_controller.h"
#include "ash/public/cpp/window_tree_host_lookup.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
......@@ -191,11 +192,20 @@ ClipboardHistoryControllerImpl::ClipboardHistoryControllerImpl()
clipboard_history_.get())),
accelerator_target_(std::make_unique<AcceleratorTarget>(this)),
menu_delegate_(std::make_unique<MenuDelegate>(this)),
nudge_controller_(std::make_unique<ClipboardNudgeController>(
clipboard_history_.get())) {}
nudge_controller_(
std::make_unique<ClipboardNudgeController>(clipboard_history_.get(),
this)) {}
ClipboardHistoryControllerImpl::~ClipboardHistoryControllerImpl() = default;
void ClipboardHistoryControllerImpl::AddObserver(Observer* observer) const {
observers_.AddObserver(observer);
}
void ClipboardHistoryControllerImpl::RemoveObserver(Observer* observer) const {
observers_.RemoveObserver(observer);
}
bool ClipboardHistoryControllerImpl::IsMenuShowing() const {
return context_menu_ && context_menu_->IsRunning();
}
......@@ -240,6 +250,8 @@ void ClipboardHistoryControllerImpl::ShowMenu(
// history menu shows.
context_menu_->SelectMenuItemWithCommandId(
ClipboardHistoryUtil::kFirstItemCommandId);
for (auto& observer : observers_)
observer.OnClipboardHistoryMenuShown();
}
bool ClipboardHistoryControllerImpl::CanShowMenu() const {
......@@ -249,11 +261,15 @@ bool ClipboardHistoryControllerImpl::CanShowMenu() const {
void ClipboardHistoryControllerImpl::ExecuteSelectedMenuItem(int event_flags) {
DCHECK(IsMenuShowing());
auto command = context_menu_->GetSelectedMenuItemCommand();
// If no menu item is currently selected, we'll fallback to the first item.
menu_delegate_->ExecuteCommand(
command.value_or(ClipboardHistoryUtil::kFirstItemCommandId), event_flags);
for (auto& observer : observers_)
observer.OnClipboardHistoryPasted();
}
void ClipboardHistoryControllerImpl::ExecuteCommand(int command_id,
......
......@@ -10,9 +10,9 @@
#include "ash/ash_export.h"
#include "ash/clipboard/clipboard_history_item.h"
#include "ash/clipboard/clipboard_nudge_controller.h"
#include "ash/public/cpp/clipboard_history_controller.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
namespace views {
enum class MenuAnchorPosition;
......@@ -27,12 +27,21 @@ namespace ash {
class ClipboardHistory;
class ClipboardHistoryMenuModelAdapter;
class ClipboardHistoryResourceManager;
class ClipboardNudgeController;
// Shows a menu with the last few things saved in the clipboard when the
// keyboard shortcut is pressed.
class ASH_EXPORT ClipboardHistoryControllerImpl
: public ClipboardHistoryController {
public:
class Observer : public base::CheckedObserver {
public:
// Called when the clipboard history menu is shown.
virtual void OnClipboardHistoryMenuShown() = 0;
// Called when the user pastes from the clipboard history menu.
virtual void OnClipboardHistoryPasted() = 0;
};
ClipboardHistoryControllerImpl();
ClipboardHistoryControllerImpl(const ClipboardHistoryControllerImpl&) =
delete;
......@@ -40,6 +49,9 @@ class ASH_EXPORT ClipboardHistoryControllerImpl
const ClipboardHistoryControllerImpl&) = delete;
~ClipboardHistoryControllerImpl() override;
void AddObserver(Observer* observer) const;
void RemoveObserver(Observer* observer) const;
// Returns if the contextual menu is currently showing.
bool IsMenuShowing() const;
......@@ -98,6 +110,10 @@ class ASH_EXPORT ClipboardHistoryControllerImpl
// Called when the contextual menu is closed.
void OnMenuClosed();
// Mutable to allow adding/removing from |observers_| through a const
// ClipboardHistoryControllerImpl.
mutable base::ObserverList<Observer> observers_;
// The menu being shown.
std::unique_ptr<ClipboardHistoryMenuModelAdapter> context_menu_;
// Used to keep track of what is being copied to the clipboard.
......
......@@ -7,6 +7,7 @@
#include <memory>
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/clipboard/clipboard_history.h"
#include "ash/public/cpp/clipboard_image_model_factory.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
......
......@@ -11,6 +11,8 @@
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/util/values/values_util.h"
#include "chromeos/constants/chromeos_features.h"
......@@ -25,14 +27,21 @@ namespace {
constexpr char kShownCount[] = "shown_count";
constexpr char kLastTimeShown[] = "last_time_shown";
// The maximum number of 1 second buckets used to record the time between
// showing the nudge and recording the feature being opened/used.
constexpr int kBucketCount = 61;
} // namespace
namespace ash {
ClipboardNudgeController::ClipboardNudgeController(
ClipboardHistory* clipboard_history)
: clipboard_history_(clipboard_history) {
ClipboardHistory* clipboard_history,
ClipboardHistoryControllerImpl* clipboard_history_controller)
: clipboard_history_(clipboard_history),
clipboard_history_controller_(clipboard_history_controller) {
clipboard_history_->AddObserver(this);
clipboard_history_controller_->AddObserver(this);
ui::ClipboardMonitor::GetInstance()->AddObserver(this);
if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled())
Shell::Get()->session_controller()->AddObserver(this);
......@@ -40,6 +49,7 @@ ClipboardNudgeController::ClipboardNudgeController(
ClipboardNudgeController::~ClipboardNudgeController() {
clipboard_history_->RemoveObserver(this);
clipboard_history_controller_->RemoveObserver(this);
ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled())
Shell::Get()->session_controller()->RemoveObserver(this);
......@@ -119,6 +129,13 @@ void ClipboardNudgeController::ShowNudge() {
hide_nudge_timer_.Start(FROM_HERE, kNudgeShowTime,
base::BindOnce(&ClipboardNudgeController::HideNudge,
weak_ptr_factory_.GetWeakPtr()));
last_shown_time_ = GetTime();
// Tracks the number of times the ClipboardHistory nudge is shown.
// This allows us to understand the conversion rate of showing a nudge to
// a user opening and then using the clipboard history feature.
base::UmaHistogramExactLinear(
"Ash.ClipboardHistory.ContextualNudge.ShownCount", 1, 1);
}
void ClipboardNudgeController::HideNudge() {
......@@ -136,6 +153,30 @@ void ClipboardNudgeController::HandleNudgeShown() {
update->SetPath(kLastTimeShown, util::TimeToValue(GetTime()));
}
void ClipboardNudgeController::OnClipboardHistoryMenuShown() {
if (last_shown_time_.is_null())
return;
base::TimeDelta time_since_shown = GetTime() - last_shown_time_;
// Tracks the amount of time between showing the user a nudge and the user
// opening the ClipboardHistory menu.
base::UmaHistogramExactLinear(
"Ash.ClipboardHistory.ContextualNudge.NudgeToFeatureOpenTime",
time_since_shown.InSeconds(), kBucketCount);
}
void ClipboardNudgeController::OnClipboardHistoryPasted() {
if (last_shown_time_.is_null())
return;
base::TimeDelta time_since_shown = GetTime() - last_shown_time_;
// Tracks the amount of time between showing the user a nudge and the user
// using the ClipboardHistory feature.
base::UmaHistogramExactLinear(
"Ash.ClipboardHistory.ContextualNudge.NudgeToFeatureUseTime",
time_since_shown.InSeconds(), kBucketCount);
}
void ClipboardNudgeController::OverrideClockForTesting(
base::Clock* test_clock) {
DCHECK(!g_clock_override);
......
......@@ -7,6 +7,7 @@
#include "ash/ash_export.h"
#include "ash/clipboard/clipboard_history.h"
#include "ash/clipboard/clipboard_history_controller_impl.h"
#include "ash/public/cpp/session/session_observer.h"
#include "base/memory/weak_ptr.h"
#include "base/time/clock.h"
......@@ -31,11 +32,15 @@ enum class ClipboardState {
kShouldShowNudge = 4,
};
class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer,
class ASH_EXPORT ClipboardNudgeController
: public ClipboardHistory::Observer,
public ui::ClipboardObserver,
public SessionObserver {
public SessionObserver,
public ClipboardHistoryControllerImpl::Observer {
public:
ClipboardNudgeController(ClipboardHistory* clipboard_history);
ClipboardNudgeController(
ClipboardHistory* clipboard_history,
ClipboardHistoryControllerImpl* clipboard_history_controller);
ClipboardNudgeController(const ClipboardNudgeController&) = delete;
ClipboardNudgeController& operator=(const ClipboardNudgeController&) = delete;
~ClipboardNudgeController() override;
......@@ -55,6 +60,10 @@ class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer,
// Resets nudge state and show nudge timer.
void HandleNudgeShown();
// ClipboardHistoryControllerImpl:
void OnClipboardHistoryMenuShown() override;
void OnClipboardHistoryPasted() override;
// Test methods for overriding and resetting the clock used by GetTime.
void OverrideClockForTesting(base::Clock* test_clock);
void ClearClockOverrideForTesting();
......@@ -78,9 +87,15 @@ class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer,
// Hides the nudge widget.
void HideNudge();
// Time the nudge was last shown.
base::Time last_shown_time_;
// Owned by ClipboardHistoryController.
const ClipboardHistory* clipboard_history_;
// Owned by ash/Shell.
const ClipboardHistoryControllerImpl* const clipboard_history_controller_;
// Current clipboard state.
ClipboardState clipboard_state_ = ClipboardState::kInit;
// The timestamp of the most recent paste.
......
......@@ -272,6 +272,41 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary>
</histogram>
<histogram name="Ash.ClipboardHistory.ContextualNudge.NudgeToFeatureOpenTime"
units="seconds" expires_after="2021-09-01">
<owner>yulunwu@chromium.org</owner>
<owner>newcomer@chromium.org</owner>
<summary>
The number of seconds between the user being shown the clipboard history
contextual nudge and the opening the clipboard history menu. The sum over
this histogram will also be used to measure the conversion rate between
showing the nudge and the clipboard history feature being opened.
</summary>
</histogram>
<histogram name="Ash.ClipboardHistory.ContextualNudge.NudgeToFeatureUseTime"
units="seconds" expires_after="2021-09-01">
<owner>yulunwu@chromium.org</owner>
<owner>newcomer@chromium.org</owner>
<summary>
The number of seconds between the user being shown the clipboard history
contextual nudge and the user pasting with the clipboard history feature.
The sum over this histogram will also be used to measure the conversion rate
between showing the nudge and the clipboard history feature being used.
</summary>
</histogram>
<histogram name="Ash.ClipboardHistory.ContextualNudge.ShownCount"
enum="BooleanHit" expires_after="2021-09-01">
<owner>yulunwu@chromium.org</owner>
<owner>newcomer@chromium.org</owner>
<summary>
The number of times the clipboard history contextual nudge has been shown.
This number will be used as the baseline against the sum of the
NudgeToFeatureUseTime and NudgeToFeatureOpenTime.
</summary>
</histogram>
<histogram base="true" name="Ash.ContextualNudgeDismissContext"
enum="ContextualNudgeDismissContext" expires_after="M86">
<!-- Name completed by histogram_suffixes name="ContextualNudgesNames" -->
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment