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 @@ ...@@ -11,6 +11,7 @@
#include "ash/clipboard/clipboard_history_menu_model_adapter.h" #include "ash/clipboard/clipboard_history_menu_model_adapter.h"
#include "ash/clipboard/clipboard_history_resource_manager.h" #include "ash/clipboard/clipboard_history_resource_manager.h"
#include "ash/clipboard/clipboard_history_util.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/public/cpp/window_tree_host_lookup.h"
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -191,11 +192,20 @@ ClipboardHistoryControllerImpl::ClipboardHistoryControllerImpl() ...@@ -191,11 +192,20 @@ ClipboardHistoryControllerImpl::ClipboardHistoryControllerImpl()
clipboard_history_.get())), clipboard_history_.get())),
accelerator_target_(std::make_unique<AcceleratorTarget>(this)), accelerator_target_(std::make_unique<AcceleratorTarget>(this)),
menu_delegate_(std::make_unique<MenuDelegate>(this)), menu_delegate_(std::make_unique<MenuDelegate>(this)),
nudge_controller_(std::make_unique<ClipboardNudgeController>( nudge_controller_(
clipboard_history_.get())) {} std::make_unique<ClipboardNudgeController>(clipboard_history_.get(),
this)) {}
ClipboardHistoryControllerImpl::~ClipboardHistoryControllerImpl() = default; 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 { bool ClipboardHistoryControllerImpl::IsMenuShowing() const {
return context_menu_ && context_menu_->IsRunning(); return context_menu_ && context_menu_->IsRunning();
} }
...@@ -240,6 +250,8 @@ void ClipboardHistoryControllerImpl::ShowMenu( ...@@ -240,6 +250,8 @@ void ClipboardHistoryControllerImpl::ShowMenu(
// history menu shows. // history menu shows.
context_menu_->SelectMenuItemWithCommandId( context_menu_->SelectMenuItemWithCommandId(
ClipboardHistoryUtil::kFirstItemCommandId); ClipboardHistoryUtil::kFirstItemCommandId);
for (auto& observer : observers_)
observer.OnClipboardHistoryMenuShown();
} }
bool ClipboardHistoryControllerImpl::CanShowMenu() const { bool ClipboardHistoryControllerImpl::CanShowMenu() const {
...@@ -249,11 +261,15 @@ bool ClipboardHistoryControllerImpl::CanShowMenu() const { ...@@ -249,11 +261,15 @@ bool ClipboardHistoryControllerImpl::CanShowMenu() const {
void ClipboardHistoryControllerImpl::ExecuteSelectedMenuItem(int event_flags) { void ClipboardHistoryControllerImpl::ExecuteSelectedMenuItem(int event_flags) {
DCHECK(IsMenuShowing()); DCHECK(IsMenuShowing());
auto command = context_menu_->GetSelectedMenuItemCommand(); auto command = context_menu_->GetSelectedMenuItemCommand();
// If no menu item is currently selected, we'll fallback to the first item. // If no menu item is currently selected, we'll fallback to the first item.
menu_delegate_->ExecuteCommand( menu_delegate_->ExecuteCommand(
command.value_or(ClipboardHistoryUtil::kFirstItemCommandId), event_flags); command.value_or(ClipboardHistoryUtil::kFirstItemCommandId), event_flags);
for (auto& observer : observers_)
observer.OnClipboardHistoryPasted();
} }
void ClipboardHistoryControllerImpl::ExecuteCommand(int command_id, void ClipboardHistoryControllerImpl::ExecuteCommand(int command_id,
......
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/clipboard/clipboard_history_item.h" #include "ash/clipboard/clipboard_history_item.h"
#include "ash/clipboard/clipboard_nudge_controller.h"
#include "ash/public/cpp/clipboard_history_controller.h" #include "ash/public/cpp/clipboard_history_controller.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
namespace views { namespace views {
enum class MenuAnchorPosition; enum class MenuAnchorPosition;
...@@ -27,12 +27,21 @@ namespace ash { ...@@ -27,12 +27,21 @@ namespace ash {
class ClipboardHistory; class ClipboardHistory;
class ClipboardHistoryMenuModelAdapter; class ClipboardHistoryMenuModelAdapter;
class ClipboardHistoryResourceManager; class ClipboardHistoryResourceManager;
class ClipboardNudgeController;
// Shows a menu with the last few things saved in the clipboard when the // Shows a menu with the last few things saved in the clipboard when the
// keyboard shortcut is pressed. // keyboard shortcut is pressed.
class ASH_EXPORT ClipboardHistoryControllerImpl class ASH_EXPORT ClipboardHistoryControllerImpl
: public ClipboardHistoryController { : public ClipboardHistoryController {
public: 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();
ClipboardHistoryControllerImpl(const ClipboardHistoryControllerImpl&) = ClipboardHistoryControllerImpl(const ClipboardHistoryControllerImpl&) =
delete; delete;
...@@ -40,6 +49,9 @@ class ASH_EXPORT ClipboardHistoryControllerImpl ...@@ -40,6 +49,9 @@ class ASH_EXPORT ClipboardHistoryControllerImpl
const ClipboardHistoryControllerImpl&) = delete; const ClipboardHistoryControllerImpl&) = delete;
~ClipboardHistoryControllerImpl() override; ~ClipboardHistoryControllerImpl() override;
void AddObserver(Observer* observer) const;
void RemoveObserver(Observer* observer) const;
// Returns if the contextual menu is currently showing. // Returns if the contextual menu is currently showing.
bool IsMenuShowing() const; bool IsMenuShowing() const;
...@@ -98,6 +110,10 @@ class ASH_EXPORT ClipboardHistoryControllerImpl ...@@ -98,6 +110,10 @@ class ASH_EXPORT ClipboardHistoryControllerImpl
// Called when the contextual menu is closed. // Called when the contextual menu is closed.
void OnMenuClosed(); void OnMenuClosed();
// Mutable to allow adding/removing from |observers_| through a const
// ClipboardHistoryControllerImpl.
mutable base::ObserverList<Observer> observers_;
// The menu being shown. // The menu being shown.
std::unique_ptr<ClipboardHistoryMenuModelAdapter> context_menu_; std::unique_ptr<ClipboardHistoryMenuModelAdapter> context_menu_;
// Used to keep track of what is being copied to the clipboard. // Used to keep track of what is being copied to the clipboard.
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "ash/app_list/app_list_controller_impl.h" #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/public/cpp/clipboard_image_model_factory.h"
#include "ash/session/session_controller_impl.h" #include "ash/session/session_controller_impl.h"
#include "ash/shell.h" #include "ash/shell.h"
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "ash/session/session_controller_impl.h" #include "ash/session/session_controller_impl.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/util/values/values_util.h" #include "base/util/values/values_util.h"
#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_features.h"
...@@ -25,14 +27,21 @@ namespace { ...@@ -25,14 +27,21 @@ namespace {
constexpr char kShownCount[] = "shown_count"; constexpr char kShownCount[] = "shown_count";
constexpr char kLastTimeShown[] = "last_time_shown"; 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
namespace ash { namespace ash {
ClipboardNudgeController::ClipboardNudgeController( ClipboardNudgeController::ClipboardNudgeController(
ClipboardHistory* clipboard_history) ClipboardHistory* clipboard_history,
: clipboard_history_(clipboard_history) { ClipboardHistoryControllerImpl* clipboard_history_controller)
: clipboard_history_(clipboard_history),
clipboard_history_controller_(clipboard_history_controller) {
clipboard_history_->AddObserver(this); clipboard_history_->AddObserver(this);
clipboard_history_controller_->AddObserver(this);
ui::ClipboardMonitor::GetInstance()->AddObserver(this); ui::ClipboardMonitor::GetInstance()->AddObserver(this);
if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled()) if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled())
Shell::Get()->session_controller()->AddObserver(this); Shell::Get()->session_controller()->AddObserver(this);
...@@ -40,6 +49,7 @@ ClipboardNudgeController::ClipboardNudgeController( ...@@ -40,6 +49,7 @@ ClipboardNudgeController::ClipboardNudgeController(
ClipboardNudgeController::~ClipboardNudgeController() { ClipboardNudgeController::~ClipboardNudgeController() {
clipboard_history_->RemoveObserver(this); clipboard_history_->RemoveObserver(this);
clipboard_history_controller_->RemoveObserver(this);
ui::ClipboardMonitor::GetInstance()->RemoveObserver(this); ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled()) if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled())
Shell::Get()->session_controller()->RemoveObserver(this); Shell::Get()->session_controller()->RemoveObserver(this);
...@@ -119,6 +129,13 @@ void ClipboardNudgeController::ShowNudge() { ...@@ -119,6 +129,13 @@ void ClipboardNudgeController::ShowNudge() {
hide_nudge_timer_.Start(FROM_HERE, kNudgeShowTime, hide_nudge_timer_.Start(FROM_HERE, kNudgeShowTime,
base::BindOnce(&ClipboardNudgeController::HideNudge, base::BindOnce(&ClipboardNudgeController::HideNudge,
weak_ptr_factory_.GetWeakPtr())); 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() { void ClipboardNudgeController::HideNudge() {
...@@ -136,6 +153,30 @@ void ClipboardNudgeController::HandleNudgeShown() { ...@@ -136,6 +153,30 @@ void ClipboardNudgeController::HandleNudgeShown() {
update->SetPath(kLastTimeShown, util::TimeToValue(GetTime())); 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( void ClipboardNudgeController::OverrideClockForTesting(
base::Clock* test_clock) { base::Clock* test_clock) {
DCHECK(!g_clock_override); DCHECK(!g_clock_override);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/clipboard/clipboard_history.h" #include "ash/clipboard/clipboard_history.h"
#include "ash/clipboard/clipboard_history_controller_impl.h"
#include "ash/public/cpp/session/session_observer.h" #include "ash/public/cpp/session/session_observer.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/time/clock.h" #include "base/time/clock.h"
...@@ -31,11 +32,15 @@ enum class ClipboardState { ...@@ -31,11 +32,15 @@ enum class ClipboardState {
kShouldShowNudge = 4, kShouldShowNudge = 4,
}; };
class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer, class ASH_EXPORT ClipboardNudgeController
public ui::ClipboardObserver, : public ClipboardHistory::Observer,
public SessionObserver { public ui::ClipboardObserver,
public SessionObserver,
public ClipboardHistoryControllerImpl::Observer {
public: public:
ClipboardNudgeController(ClipboardHistory* clipboard_history); ClipboardNudgeController(
ClipboardHistory* clipboard_history,
ClipboardHistoryControllerImpl* clipboard_history_controller);
ClipboardNudgeController(const ClipboardNudgeController&) = delete; ClipboardNudgeController(const ClipboardNudgeController&) = delete;
ClipboardNudgeController& operator=(const ClipboardNudgeController&) = delete; ClipboardNudgeController& operator=(const ClipboardNudgeController&) = delete;
~ClipboardNudgeController() override; ~ClipboardNudgeController() override;
...@@ -55,6 +60,10 @@ class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer, ...@@ -55,6 +60,10 @@ class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer,
// Resets nudge state and show nudge timer. // Resets nudge state and show nudge timer.
void HandleNudgeShown(); void HandleNudgeShown();
// ClipboardHistoryControllerImpl:
void OnClipboardHistoryMenuShown() override;
void OnClipboardHistoryPasted() override;
// Test methods for overriding and resetting the clock used by GetTime. // Test methods for overriding and resetting the clock used by GetTime.
void OverrideClockForTesting(base::Clock* test_clock); void OverrideClockForTesting(base::Clock* test_clock);
void ClearClockOverrideForTesting(); void ClearClockOverrideForTesting();
...@@ -78,9 +87,15 @@ class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer, ...@@ -78,9 +87,15 @@ class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer,
// Hides the nudge widget. // Hides the nudge widget.
void HideNudge(); void HideNudge();
// Time the nudge was last shown.
base::Time last_shown_time_;
// Owned by ClipboardHistoryController. // Owned by ClipboardHistoryController.
const ClipboardHistory* clipboard_history_; const ClipboardHistory* clipboard_history_;
// Owned by ash/Shell.
const ClipboardHistoryControllerImpl* const clipboard_history_controller_;
// Current clipboard state. // Current clipboard state.
ClipboardState clipboard_state_ = ClipboardState::kInit; ClipboardState clipboard_state_ = ClipboardState::kInit;
// The timestamp of the most recent paste. // The timestamp of the most recent paste.
......
...@@ -272,6 +272,41 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -272,6 +272,41 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </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" <histogram base="true" name="Ash.ContextualNudgeDismissContext"
enum="ContextualNudgeDismissContext" expires_after="M86"> enum="ContextualNudgeDismissContext" expires_after="M86">
<!-- Name completed by histogram_suffixes name="ContextualNudgesNames" --> <!-- 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