Commit fa61f300 authored by mukai@chromium.org's avatar mukai@chromium.org

Introduces UMA for app-list voice search.

This CL adds 6 user actions (prefixed by 'AppList_')
- AutoLaunchCanceled
- AutoLaunched
- HotwordRecognized
- SearchedBySpeech
- VoiceSearchCanceled
- VoiceSearchStartedManually

BUG=341239
R=xiyuan@chromium.org
TBR=oshima@chromium.org

Review URL: https://codereview.chromium.org/151903007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251359 0039d316-1c4b-4281-b951-d872f2087c98
parent 5912ad25
......@@ -265,6 +265,7 @@ class ExampleAppListViewDelegate : public app_list::AppListViewDelegate {
}
virtual void OpenSearchResult(app_list::SearchResult* result,
bool auto_launch,
int event_flags) OVERRIDE {
const ExampleSearchResult* example_result =
static_cast<const ExampleSearchResult*>(result);
......
......@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/metrics/user_metrics.h"
#include "base/stl_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
......@@ -234,7 +235,10 @@ void AppListViewDelegate::StopSearch() {
void AppListViewDelegate::OpenSearchResult(
app_list::SearchResult* result,
bool auto_launch,
int event_flags) {
if (auto_launch)
base::RecordAction(base::UserMetricsAction("AppList_AutoLaunched"));
search_controller_->OpenResult(result, event_flags);
}
......@@ -250,6 +254,7 @@ base::TimeDelta AppListViewDelegate::GetAutoLaunchTimeout() {
}
void AppListViewDelegate::AutoLaunchCanceled() {
base::RecordAction(base::UserMetricsAction("AppList_AutoLaunchCanceled"));
auto_launch_timeout_ = base::TimeDelta();
}
......
......@@ -71,6 +71,7 @@ class AppListViewDelegate : public app_list::AppListViewDelegate,
virtual void StartSearch() OVERRIDE;
virtual void StopSearch() OVERRIDE;
virtual void OpenSearchResult(app_list::SearchResult* result,
bool auto_launch,
int event_flags) OVERRIDE;
virtual void InvokeSearchResultAction(app_list::SearchResult* result,
int action_index,
......
......@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/memory/singleton.h"
#include "base/metrics/user_metrics.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/media/media_stream_infobar_delegate.h"
#include "chrome/browser/profiles/profile.h"
......@@ -28,8 +29,20 @@
#include "extensions/common/extension.h"
#include "ui/app_list/app_list_switches.h"
using base::RecordAction;
using base::UserMetricsAction;
namespace app_list {
namespace {
bool InSpeechRecognition(SpeechRecognitionState state) {
return state == SPEECH_RECOGNITION_RECOGNIZING ||
state == SPEECH_RECOGNITION_IN_SPEECH;
}
}
class StartPageService::ProfileDestroyObserver
: public content::NotificationObserver {
public:
......@@ -84,7 +97,9 @@ StartPageService::StartPageService(Profile* profile)
: profile_(profile),
profile_destroy_observer_(new ProfileDestroyObserver(this)),
recommended_apps_(new RecommendedApps(profile)),
state_(app_list::SPEECH_RECOGNITION_OFF) {
state_(app_list::SPEECH_RECOGNITION_OFF),
speech_button_toggled_manually_(false),
speech_result_obtained_(false) {
#if defined(OS_CHROMEOS)
// Updates the default state to hotword listening, because this is
// the default behavior. This will be updated when the page is loaded and
......@@ -123,6 +138,7 @@ void StartPageService::RemoveObserver(StartPageObserver* observer) {
}
void StartPageService::ToggleSpeechRecognition() {
speech_button_toggled_manually_ = true;
contents_->GetWebUI()->CallJavascriptFunction(
"appList.startPage.toggleSpeechRecognition");
}
......@@ -138,6 +154,10 @@ content::WebContents* StartPageService::GetSpeechRecognitionContents() {
void StartPageService::OnSpeechResult(
const base::string16& query, bool is_final) {
if (is_final) {
speech_result_obtained_ = true;
RecordAction(UserMetricsAction("AppList_SearchedBySpeech"));
}
FOR_EACH_OBSERVER(StartPageObserver,
observers_,
OnSpeechResult(query, is_final));
......@@ -151,6 +171,19 @@ void StartPageService::OnSpeechSoundLevelChanged(int16 level) {
void StartPageService::OnSpeechRecognitionStateChanged(
SpeechRecognitionState new_state) {
if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) {
if (!speech_button_toggled_manually_ &&
state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) {
RecordAction(UserMetricsAction("AppList_HotwordRecognized"));
} else {
RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually"));
}
} else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) &&
!speech_result_obtained_) {
RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled"));
}
speech_button_toggled_manually_ = false;
speech_result_obtained_ = false;
state_ = new_state;
FOR_EACH_OBSERVER(StartPageObserver,
observers_,
......
......@@ -78,6 +78,8 @@ class StartPageService : public BrowserContextKeyedService {
scoped_ptr<RecommendedApps> recommended_apps_;
SpeechRecognitionState state_;
ObserverList<StartPageObserver> observers_;
bool speech_button_toggled_manually_;
bool speech_result_obtained_;
DISALLOW_COPY_AND_ASSIGN(StartPageService);
};
......
......@@ -139,9 +139,15 @@
0xe86a88a8a34848a8 ActiveBrowserChanged
0xb52f7beb7f11bedf ActiveTabChanged
0x966cdbb949bad0d7 AppCloseButton_Clk
0xf91a69e600aa53b9 AppList_AutoLaunchCanceled
0x3512923b3703e606 AppList_AutoLaunched
0xfc0c75574fa0f498 AppList_ClickOnApp
0x73d7010c18cf1912 AppList_ClickOnAppFromSearch
0xeca78128207e2c2e AppList_HotwordRecognized
0xdd57b39909cb275a AppList_Search
0xb58656b4552c3bf7 AppList_SearchedBySpeech
0xf91dc0e2612ed54b AppList_VoiceSearchCanceled
0x462539c392c047c2 AppList_VoiceSearchStartedManually
0x9ff9ef57d8d1d87c AutoDetectChange
0x2ec21bf8ac5a6992 AutomaticReset_WebUIBanner_BannerShown
0xaa07e015f2ac0368 AutomaticReset_WebUIBanner_ManuallyClosed
......
......@@ -91,7 +91,9 @@ class APP_LIST_EXPORT AppListViewDelegate {
virtual void StopSearch() = 0;
// Invoked to open the search result.
virtual void OpenSearchResult(SearchResult* result, int event_flags) = 0;
virtual void OpenSearchResult(SearchResult* result,
bool auto_launch,
int event_flags) = 0;
// Called to invoke a custom action on |result|. |action_index| corresponds
// to the index of an icon in |result.action_icons()|.
......
......@@ -348,8 +348,10 @@ void AppListModelObserverBridge::OnProfilesChanged() {
}
- (void)openResult:(app_list::SearchResult*)result {
if (delegate_)
delegate_->OpenSearchResult(result, 0 /* event flags */);
if (delegate_) {
delegate_->OpenSearchResult(
result, false /* auto_launch */, 0 /* event flags */);
}
}
- (void)redoSearch {
......
......@@ -89,6 +89,7 @@ void AppListTestViewDelegate::GetShortcutPathForApp(
}
void AppListTestViewDelegate::OpenSearchResult(SearchResult* result,
bool auto_launch,
int event_flags) {
++open_search_result_count_;
}
......
......@@ -48,6 +48,7 @@ class AppListTestViewDelegate : public AppListViewDelegate {
virtual void StartSearch() OVERRIDE {}
virtual void StopSearch() OVERRIDE {}
virtual void OpenSearchResult(SearchResult* result,
bool auto_launch,
int event_flags) OVERRIDE;
virtual void InvokeSearchResultAction(SearchResult* result,
int action_index,
......
......@@ -226,8 +226,10 @@ void AppListMainView::QueryChanged(SearchBoxView* sender) {
delegate_->StopSearch();
}
void AppListMainView::OpenResult(SearchResult* result, int event_flags) {
delegate_->OpenSearchResult(result, event_flags);
void AppListMainView::OpenResult(SearchResult* result,
bool auto_launch,
int event_flags) {
delegate_->OpenSearchResult(result, auto_launch, event_flags);
}
void AppListMainView::InvokeResultAction(SearchResult* result,
......
......@@ -86,6 +86,7 @@ class APP_LIST_EXPORT AppListMainView : public views::View,
// Overridden from SearchResultListViewDelegate:
virtual void OpenResult(SearchResult* result,
bool auto_launch,
int event_flags) OVERRIDE;
virtual void InvokeResultAction(SearchResult* result,
int action_index,
......
......@@ -201,7 +201,7 @@ void SearchResultListView::VisibilityChanged(views::View* starting_from,
void SearchResultListView::AnimationEnded(const gfx::Animation* animation) {
DCHECK_EQ(auto_launch_animation_.get(), animation);
delegate_->OpenResult(results_->GetItemAt(0), ui::EF_NONE);
delegate_->OpenResult(results_->GetItemAt(0), true, ui::EF_NONE);
}
void SearchResultListView::AnimationProgressed(
......@@ -237,7 +237,7 @@ void SearchResultListView::ListItemsChanged(size_t start, size_t count) {
void SearchResultListView::SearchResultActivated(SearchResultView* view,
int event_flags) {
if (delegate_ && view->result())
delegate_->OpenResult(view->result(), event_flags);
delegate_->OpenResult(view->result(), false, event_flags);
}
void SearchResultListView::SearchResultActionActivated(SearchResultView* view,
......
......@@ -14,9 +14,12 @@ class SearchResult;
class APP_LIST_EXPORT SearchResultListViewDelegate {
public:
// Invoked to open given |result|. |event_flags| contains the flags of the
// keyboard/mouse event that triggers the "open" request. Delegate could use
// the |event_flags| information to choose different ways to open the result.
// keyboard/mouse event that triggers the "open" request. |auto_launch| is
// true when the result is opened automatically through voice-search. Delegate
// could use the |event_flags| information to choose different ways to open
// the result.
virtual void OpenResult(SearchResult* result,
bool auto_launch,
int event_flags) = 0;
// Called to invoke a custom action on |result|. |action_index| corresponds
......
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