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

Side by Side Diff: chrome/browser/ui/app_list/start_page_service.cc

Issue 676593003: Implement native speech recognition for the launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Pass in WeakPtr<Delegate>. Created 6 years, 1 month 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 unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/app_list/start_page_service.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/app_list/start_page_service.h" 5 #include "chrome/browser/ui/app_list/start_page_service.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/memory/singleton.h" 11 #include "base/memory/singleton.h"
12 #include "base/metrics/user_metrics.h" 12 #include "base/metrics/user_metrics.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/media/media_stream_infobar_delegate.h" 16 #include "chrome/browser/media/media_stream_infobar_delegate.h"
16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/search/hotword_service.h" 18 #include "chrome/browser/search/hotword_service.h"
18 #include "chrome/browser/search/hotword_service_factory.h" 19 #include "chrome/browser/search/hotword_service_factory.h"
19 #include "chrome/browser/ui/app_list/recommended_apps.h" 20 #include "chrome/browser/ui/app_list/recommended_apps.h"
21 #include "chrome/browser/ui/app_list/speech_recognizer.h"
20 #include "chrome/browser/ui/app_list/start_page_observer.h" 22 #include "chrome/browser/ui/app_list/start_page_observer.h"
21 #include "chrome/browser/ui/app_list/start_page_service_factory.h" 23 #include "chrome/browser/ui/app_list/start_page_service_factory.h"
22 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h" 25 #include "chrome/common/pref_names.h"
24 #include "chrome/common/url_constants.h" 26 #include "chrome/common/url_constants.h"
25 #include "content/public/browser/notification_details.h" 27 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_observer.h" 28 #include "content/public/browser/notification_observer.h"
27 #include "content/public/browser/notification_registrar.h" 29 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/notification_source.h" 31 #include "content/public/browser/notification_source.h"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 return StartPageServiceFactory::GetForProfile(profile); 107 return StartPageServiceFactory::GetForProfile(profile);
106 } 108 }
107 109
108 StartPageService::StartPageService(Profile* profile) 110 StartPageService::StartPageService(Profile* profile)
109 : profile_(profile), 111 : profile_(profile),
110 profile_destroy_observer_(new ProfileDestroyObserver(this)), 112 profile_destroy_observer_(new ProfileDestroyObserver(this)),
111 recommended_apps_(new RecommendedApps(profile)), 113 recommended_apps_(new RecommendedApps(profile)),
112 state_(app_list::SPEECH_RECOGNITION_OFF), 114 state_(app_list::SPEECH_RECOGNITION_OFF),
113 speech_button_toggled_manually_(false), 115 speech_button_toggled_manually_(false),
114 speech_result_obtained_(false), 116 speech_result_obtained_(false),
115 webui_finished_loading_(false) { 117 webui_finished_loading_(false),
118 weak_factory_(this) {
116 // If experimental hotwording is enabled, then we're always "ready". 119 // If experimental hotwording is enabled, then we're always "ready".
117 // Transitioning into the "hotword recognizing" state is handled by the 120 // Transitioning into the "hotword recognizing" state is handled by the
118 // hotword extension. 121 // hotword extension.
119 if (HotwordService::IsExperimentalHotwordingEnabled()) 122 if (HotwordService::IsExperimentalHotwordingEnabled())
120 state_ = app_list::SPEECH_RECOGNITION_READY; 123 state_ = app_list::SPEECH_RECOGNITION_READY;
121 124
122 if (app_list::switches::IsExperimentalAppListEnabled()) 125 if (app_list::switches::IsExperimentalAppListEnabled())
123 LoadContents(); 126 LoadContents();
124 } 127 }
125 128
126 StartPageService::~StartPageService() {} 129 StartPageService::~StartPageService() {}
127 130
128 void StartPageService::AddObserver(StartPageObserver* observer) { 131 void StartPageService::AddObserver(StartPageObserver* observer) {
129 observers_.AddObserver(observer); 132 observers_.AddObserver(observer);
130 } 133 }
131 134
132 void StartPageService::RemoveObserver(StartPageObserver* observer) { 135 void StartPageService::RemoveObserver(StartPageObserver* observer) {
133 observers_.RemoveObserver(observer); 136 observers_.RemoveObserver(observer);
134 } 137 }
135 138
136 void StartPageService::AppListShown() { 139 void StartPageService::AppListShown() {
137 if (!contents_) { 140 if (!contents_) {
138 LoadContents(); 141 LoadContents();
139 } else if (contents_->GetWebUI()) { 142 } else if (contents_->GetWebUI() &&
140 // If experimental hotwording is enabled, don't enable hotwording in the 143 !HotwordService::IsExperimentalHotwordingEnabled()) {
141 // start page, since the hotword extension is taking care of this. 144 // If experimental hotwording is enabled, don't call onAppListShown.
142 bool hotword_enabled = HotwordEnabled() && 145 // onAppListShown() initializes the web speech API, which is not used with
143 !HotwordService::IsExperimentalHotwordingEnabled(); 146 // experimental hotwording.
144 contents_->GetWebUI()->CallJavascriptFunction( 147 contents_->GetWebUI()->CallJavascriptFunction(
145 "appList.startPage.onAppListShown", 148 "appList.startPage.onAppListShown",
146 base::FundamentalValue(hotword_enabled)); 149 base::FundamentalValue(HotwordEnabled()));
147 } 150 }
148 } 151 }
149 152
150 void StartPageService::AppListHidden() { 153 void StartPageService::AppListHidden() {
151 if (contents_->GetWebUI()) { 154 if (contents_->GetWebUI()) {
152 contents_->GetWebUI()->CallJavascriptFunction( 155 contents_->GetWebUI()->CallJavascriptFunction(
153 "appList.startPage.onAppListHidden"); 156 "appList.startPage.onAppListHidden");
154 } 157 }
155 if (!app_list::switches::IsExperimentalAppListEnabled()) 158 if (!app_list::switches::IsExperimentalAppListEnabled())
156 UnloadContents(); 159 UnloadContents();
160
161 if (HotwordService::IsExperimentalHotwordingEnabled() &&
162 speech_recognizer_) {
163 speech_recognizer_->Stop();
164 }
157 } 165 }
158 166
159 void StartPageService::ToggleSpeechRecognition() { 167 void StartPageService::ToggleSpeechRecognition() {
160 DCHECK(contents_); 168 DCHECK(contents_);
161 speech_button_toggled_manually_ = true; 169 speech_button_toggled_manually_ = true;
162 if (!contents_->GetWebUI()) 170 if (!contents_->GetWebUI())
163 return; 171 return;
164 172
165 if (webui_finished_loading_) { 173 if (!webui_finished_loading_) {
166 contents_->GetWebUI()->CallJavascriptFunction(
167 "appList.startPage.toggleSpeechRecognition");
168 } else {
169 pending_webui_callbacks_.push_back( 174 pending_webui_callbacks_.push_back(
170 base::Bind(&StartPageService::ToggleSpeechRecognition, 175 base::Bind(&StartPageService::ToggleSpeechRecognition,
171 base::Unretained(this))); 176 base::Unretained(this)));
177 return;
172 } 178 }
179
180 if (HotwordService::IsExperimentalHotwordingEnabled()) {
181 if (!speech_recognizer_) {
182 std::string profile_locale;
183 #if defined(OS_CHROMEOS)
184 profile_locale = profile_->GetPrefs()->GetString(
185 prefs::kApplicationLocale);
186 #endif
187 if (profile_locale.empty())
188 profile_locale = g_browser_process->GetApplicationLocale();
189
190 speech_recognizer_.reset(
191 new SpeechRecognizer(weak_factory_.GetWeakPtr(),
192 profile_->GetRequestContext(),
193 profile_locale));
194 }
195
196 speech_recognizer_->Start();
197 return;
198 }
199
200 contents_->GetWebUI()->CallJavascriptFunction(
201 "appList.startPage.toggleSpeechRecognition");
173 } 202 }
174 203
175 bool StartPageService::HotwordEnabled() { 204 bool StartPageService::HotwordEnabled() {
176 if (HotwordService::IsExperimentalHotwordingEnabled()) { 205 if (HotwordService::IsExperimentalHotwordingEnabled()) {
177 auto prefs = profile_->GetPrefs(); 206 auto prefs = profile_->GetPrefs();
178 return HotwordServiceFactory::IsServiceAvailable(profile_) && 207 return HotwordServiceFactory::IsServiceAvailable(profile_) &&
179 (prefs->GetBoolean(prefs::kHotwordSearchEnabled) || 208 (prefs->GetBoolean(prefs::kHotwordSearchEnabled) ||
180 prefs->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled)); 209 prefs->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled));
181 } 210 }
182 #if defined(OS_CHROMEOS) 211 #if defined(OS_CHROMEOS)
(...skipping 22 matching lines...) Expand all
205 const base::string16& query, bool is_final) { 234 const base::string16& query, bool is_final) {
206 if (is_final) { 235 if (is_final) {
207 speech_result_obtained_ = true; 236 speech_result_obtained_ = true;
208 RecordAction(UserMetricsAction("AppList_SearchedBySpeech")); 237 RecordAction(UserMetricsAction("AppList_SearchedBySpeech"));
209 } 238 }
210 FOR_EACH_OBSERVER(StartPageObserver, 239 FOR_EACH_OBSERVER(StartPageObserver,
211 observers_, 240 observers_,
212 OnSpeechResult(query, is_final)); 241 OnSpeechResult(query, is_final));
213 } 242 }
214 243
215 void StartPageService::OnSpeechSoundLevelChanged(int16 level) { 244 void StartPageService::OnSpeechSoundLevelChanged(int16_t level) {
216 FOR_EACH_OBSERVER(StartPageObserver, 245 FOR_EACH_OBSERVER(StartPageObserver,
217 observers_, 246 observers_,
218 OnSpeechSoundLevelChanged(level)); 247 OnSpeechSoundLevelChanged(level));
219 } 248 }
220 249
221 void StartPageService::OnSpeechRecognitionStateChanged( 250 void StartPageService::OnSpeechRecognitionStateChanged(
222 SpeechRecognitionState new_state) { 251 SpeechRecognitionState new_state) {
252
253 if (HotwordService::IsExperimentalHotwordingEnabled() &&
254 new_state == SPEECH_RECOGNITION_READY &&
255 speech_recognizer_) {
256 speech_recognizer_->Stop();
257 }
258
223 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) { 259 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) {
224 if (!speech_button_toggled_manually_ && 260 if (!speech_button_toggled_manually_ &&
225 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) { 261 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) {
226 RecordAction(UserMetricsAction("AppList_HotwordRecognized")); 262 RecordAction(UserMetricsAction("AppList_HotwordRecognized"));
227 } else { 263 } else {
228 RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually")); 264 RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually"));
229 } 265 }
230 } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) && 266 } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) &&
231 !speech_result_obtained_) { 267 !speech_result_obtained_) {
232 RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled")); 268 RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled"));
233 } 269 }
234 speech_button_toggled_manually_ = false; 270 speech_button_toggled_manually_ = false;
235 speech_result_obtained_ = false; 271 speech_result_obtained_ = false;
236 state_ = new_state; 272 state_ = new_state;
237 FOR_EACH_OBSERVER(StartPageObserver, 273 FOR_EACH_OBSERVER(StartPageObserver,
238 observers_, 274 observers_,
239 OnSpeechRecognitionStateChanged(new_state)); 275 OnSpeechRecognitionStateChanged(new_state));
240 } 276 }
241 277
278 content::WebContents* StartPageService::GetSpeechContents() {
279 return GetSpeechRecognitionContents();
280 }
281
242 void StartPageService::Shutdown() { 282 void StartPageService::Shutdown() {
243 UnloadContents(); 283 UnloadContents();
244 } 284 }
245 285
246 void StartPageService::WebUILoaded() { 286 void StartPageService::WebUILoaded() {
247 // There's a race condition between the WebUI loading, and calling its JS 287 // There's a race condition between the WebUI loading, and calling its JS
248 // functions. Specifically, calling LoadContents() doesn't mean that the page 288 // functions. Specifically, calling LoadContents() doesn't mean that the page
249 // has loaded, but several code paths make this assumption. This function 289 // has loaded, but several code paths make this assumption. This function
250 // allows us to defer calling JS functions until after the page has finished 290 // allows us to defer calling JS functions until after the page has finished
251 // loading. 291 // loading.
(...skipping 22 matching lines...) Expand all
274 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, 314 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
275 std::string()); 315 std::string());
276 } 316 }
277 317
278 void StartPageService::UnloadContents() { 318 void StartPageService::UnloadContents() {
279 contents_.reset(); 319 contents_.reset();
280 webui_finished_loading_ = false; 320 webui_finished_loading_ = false;
281 } 321 }
282 322
283 } // namespace app_list 323 } // namespace app_list
OLDNEW
« no previous file with comments | « chrome/browser/ui/app_list/start_page_service.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698