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

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

Issue 752253002: Updates the mic icon status based on the device's audio state. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 6 years 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
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"
(...skipping 18 matching lines...) Expand all
29 #include "content/public/browser/notification_registrar.h" 29 #include "content/public/browser/notification_registrar.h"
30 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h" 31 #include "content/public/browser/notification_source.h"
32 #include "content/public/browser/web_contents.h" 32 #include "content/public/browser/web_contents.h"
33 #include "content/public/browser/web_contents_delegate.h" 33 #include "content/public/browser/web_contents_delegate.h"
34 #include "extensions/browser/extension_system_provider.h" 34 #include "extensions/browser/extension_system_provider.h"
35 #include "extensions/browser/extensions_browser_client.h" 35 #include "extensions/browser/extensions_browser_client.h"
36 #include "extensions/common/extension.h" 36 #include "extensions/common/extension.h"
37 #include "ui/app_list/app_list_switches.h" 37 #include "ui/app_list/app_list_switches.h"
38 38
39 #if defined(OS_CHROMEOS)
40 #include "chromeos/audio/cras_audio_handler.h"
41 #endif
42
39 using base::RecordAction; 43 using base::RecordAction;
40 using base::UserMetricsAction; 44 using base::UserMetricsAction;
41 45
42 namespace app_list { 46 namespace app_list {
43 47
44 namespace { 48 namespace {
45 49
46 bool InSpeechRecognition(SpeechRecognitionState state) { 50 bool InSpeechRecognition(SpeechRecognitionState state) {
47 return state == SPEECH_RECOGNITION_RECOGNIZING || 51 return state == SPEECH_RECOGNITION_RECOGNIZING ||
48 state == SPEECH_RECOGNITION_IN_SPEECH; 52 state == SPEECH_RECOGNITION_IN_SPEECH;
49 } 53 }
50 54
51 } 55 } // namespace
52 56
53 class StartPageService::ProfileDestroyObserver 57 class StartPageService::ProfileDestroyObserver
54 : public content::NotificationObserver { 58 : public content::NotificationObserver {
55 public: 59 public:
56 explicit ProfileDestroyObserver(StartPageService* service) 60 explicit ProfileDestroyObserver(StartPageService* service)
57 : service_(service) { 61 : service_(service) {
58 registrar_.Add(this, 62 registrar_.Add(this,
59 chrome::NOTIFICATION_PROFILE_DESTROYED, 63 chrome::NOTIFICATION_PROFILE_DESTROYED,
60 content::Source<Profile>(service_->profile())); 64 content::Source<Profile>(service_->profile()));
61 } 65 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 const GURL& security_origin, 99 const GURL& security_origin,
96 content::MediaStreamType type) override { 100 content::MediaStreamType type) override {
97 return MediaCaptureDevicesDispatcher::GetInstance() 101 return MediaCaptureDevicesDispatcher::GetInstance()
98 ->CheckMediaAccessPermission(web_contents, security_origin, type); 102 ->CheckMediaAccessPermission(web_contents, security_origin, type);
99 } 103 }
100 104
101 private: 105 private:
102 DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate); 106 DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate);
103 }; 107 };
104 108
109 #if defined(OS_CHROMEOS)
110
111 class StartPageService::AudioStatus
112 : public chromeos::CrasAudioHandler::AudioObserver {
113 public:
114 explicit AudioStatus(StartPageService* start_page_service)
115 : start_page_service_(start_page_service) {
116 chromeos::CrasAudioHandler::Get()->AddAudioObserver(this);
117 CheckAndUpdate();
118 }
119
120 ~AudioStatus() override {
121 chromeos::CrasAudioHandler::Get()->RemoveAudioObserver(this);
122 }
123
124 bool CanListen() {
125 chromeos::CrasAudioHandler* audio_handler =
126 chromeos::CrasAudioHandler::Get();
127 return (audio_handler->GetPrimaryActiveInputNode() != 0) &&
128 !audio_handler->IsInputMuted();
129 }
130
131 private:
132 void CheckAndUpdate() {
133 // TODO(mukai): If the system can listen, this should also restart the
134 // hotword recognition.
135 start_page_service_->OnSpeechRecognitionStateChanged(
136 CanListen() ? SPEECH_RECOGNITION_READY : SPEECH_RECOGNITION_OFF);
137 }
138
139 // chromeos::CrasAudioHandler::AudioObserver:
140 void OnInputMuteChanged() override { CheckAndUpdate(); }
141
142 void OnActiveInputNodeChanged() override { CheckAndUpdate(); }
143
144 StartPageService* start_page_service_;
145
146 DISALLOW_COPY_AND_ASSIGN(AudioStatus);
147 };
148
149 #endif // OS_CHROMEOS
150
105 // static 151 // static
106 StartPageService* StartPageService::Get(Profile* profile) { 152 StartPageService* StartPageService::Get(Profile* profile) {
107 return StartPageServiceFactory::GetForProfile(profile); 153 return StartPageServiceFactory::GetForProfile(profile);
108 } 154 }
109 155
110 StartPageService::StartPageService(Profile* profile) 156 StartPageService::StartPageService(Profile* profile)
111 : profile_(profile), 157 : profile_(profile),
112 profile_destroy_observer_(new ProfileDestroyObserver(this)), 158 profile_destroy_observer_(new ProfileDestroyObserver(this)),
113 recommended_apps_(new RecommendedApps(profile)), 159 recommended_apps_(new RecommendedApps(profile)),
114 state_(app_list::SPEECH_RECOGNITION_OFF), 160 state_(app_list::SPEECH_RECOGNITION_OFF),
115 speech_button_toggled_manually_(false), 161 speech_button_toggled_manually_(false),
116 speech_result_obtained_(false), 162 speech_result_obtained_(false),
117 webui_finished_loading_(false), 163 webui_finished_loading_(false),
118 weak_factory_(this) { 164 weak_factory_(this) {
119 // If experimental hotwording is enabled, then we're always "ready". 165 // If experimental hotwording is enabled, then we're always "ready".
120 // Transitioning into the "hotword recognizing" state is handled by the 166 // Transitioning into the "hotword recognizing" state is handled by the
121 // hotword extension. 167 // hotword extension.
122 if (HotwordService::IsExperimentalHotwordingEnabled()) 168 if (HotwordService::IsExperimentalHotwordingEnabled()) {
123 state_ = app_list::SPEECH_RECOGNITION_READY; 169 state_ = app_list::SPEECH_RECOGNITION_READY;
170 }
124 171
125 if (app_list::switches::IsExperimentalAppListEnabled()) 172 if (app_list::switches::IsExperimentalAppListEnabled())
126 LoadContents(); 173 LoadContents();
127 } 174 }
128 175
129 StartPageService::~StartPageService() {} 176 StartPageService::~StartPageService() {}
130 177
131 void StartPageService::AddObserver(StartPageObserver* observer) { 178 void StartPageService::AddObserver(StartPageObserver* observer) {
132 observers_.AddObserver(observer); 179 observers_.AddObserver(observer);
133 } 180 }
134 181
135 void StartPageService::RemoveObserver(StartPageObserver* observer) { 182 void StartPageService::RemoveObserver(StartPageObserver* observer) {
136 observers_.RemoveObserver(observer); 183 observers_.RemoveObserver(observer);
137 } 184 }
138 185
139 void StartPageService::AppListShown() { 186 void StartPageService::AppListShown() {
140 if (!contents_) { 187 if (!contents_) {
141 LoadContents(); 188 LoadContents();
142 } else if (contents_->GetWebUI() && 189 } else if (contents_->GetWebUI() &&
143 !HotwordService::IsExperimentalHotwordingEnabled()) { 190 !HotwordService::IsExperimentalHotwordingEnabled()) {
144 // If experimental hotwording is enabled, don't call onAppListShown. 191 // If experimental hotwording is enabled, don't call onAppListShown.
145 // onAppListShown() initializes the web speech API, which is not used with 192 // onAppListShown() initializes the web speech API, which is not used with
146 // experimental hotwording. 193 // experimental hotwording.
147 contents_->GetWebUI()->CallJavascriptFunction( 194 contents_->GetWebUI()->CallJavascriptFunction(
148 "appList.startPage.onAppListShown", 195 "appList.startPage.onAppListShown",
149 base::FundamentalValue(HotwordEnabled())); 196 base::FundamentalValue(HotwordEnabled()));
150 } 197 }
198
199 #if defined(OS_CHROMEOS)
200 audio_status_.reset(new AudioStatus(this));
201 #endif
151 } 202 }
152 203
153 void StartPageService::AppListHidden() { 204 void StartPageService::AppListHidden() {
154 if (contents_->GetWebUI()) { 205 if (contents_->GetWebUI()) {
155 contents_->GetWebUI()->CallJavascriptFunction( 206 contents_->GetWebUI()->CallJavascriptFunction(
156 "appList.startPage.onAppListHidden"); 207 "appList.startPage.onAppListHidden");
157 } 208 }
158 if (!app_list::switches::IsExperimentalAppListEnabled()) 209 if (!app_list::switches::IsExperimentalAppListEnabled())
159 UnloadContents(); 210 UnloadContents();
160 211
161 if (HotwordService::IsExperimentalHotwordingEnabled() && 212 if (HotwordService::IsExperimentalHotwordingEnabled() &&
162 speech_recognizer_) { 213 speech_recognizer_) {
163 speech_recognizer_->Stop(); 214 speech_recognizer_->Stop();
164 } 215 }
216
217 #if defined(OS_CHROMEOS)
218 audio_status_.reset();
219 #endif
165 } 220 }
166 221
167 void StartPageService::ToggleSpeechRecognition() { 222 void StartPageService::ToggleSpeechRecognition() {
168 DCHECK(contents_); 223 DCHECK(contents_);
169 speech_button_toggled_manually_ = true; 224 speech_button_toggled_manually_ = true;
170 if (!contents_->GetWebUI()) 225 if (!contents_->GetWebUI())
171 return; 226 return;
172 227
173 if (!webui_finished_loading_) { 228 if (!webui_finished_loading_) {
174 pending_webui_callbacks_.push_back( 229 pending_webui_callbacks_.push_back(
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 } 299 }
245 300
246 void StartPageService::OnSpeechSoundLevelChanged(int16_t level) { 301 void StartPageService::OnSpeechSoundLevelChanged(int16_t level) {
247 FOR_EACH_OBSERVER(StartPageObserver, 302 FOR_EACH_OBSERVER(StartPageObserver,
248 observers_, 303 observers_,
249 OnSpeechSoundLevelChanged(level)); 304 OnSpeechSoundLevelChanged(level));
250 } 305 }
251 306
252 void StartPageService::OnSpeechRecognitionStateChanged( 307 void StartPageService::OnSpeechRecognitionStateChanged(
253 SpeechRecognitionState new_state) { 308 SpeechRecognitionState new_state) {
309 #if defined(OS_CHROMEOS)
310 // Sometimes this can be called even though there are no audio input devices.
311 if (!audio_status_->CanListen())
312 new_state = SPEECH_RECOGNITION_OFF;
313 #endif
314
315 if (state_ == new_state)
316 return;
254 317
255 if (HotwordService::IsExperimentalHotwordingEnabled() && 318 if (HotwordService::IsExperimentalHotwordingEnabled() &&
256 new_state == SPEECH_RECOGNITION_READY && 319 new_state == SPEECH_RECOGNITION_READY &&
257 speech_recognizer_) { 320 speech_recognizer_) {
258 speech_recognizer_->Stop(); 321 speech_recognizer_->Stop();
259 } 322 }
260 323
261 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) { 324 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) {
262 if (!speech_button_toggled_manually_ && 325 if (!speech_button_toggled_manually_ &&
263 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) { 326 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) {
(...skipping 12 matching lines...) Expand all
276 observers_, 339 observers_,
277 OnSpeechRecognitionStateChanged(new_state)); 340 OnSpeechRecognitionStateChanged(new_state));
278 } 341 }
279 342
280 content::WebContents* StartPageService::GetSpeechContents() { 343 content::WebContents* StartPageService::GetSpeechContents() {
281 return GetSpeechRecognitionContents(); 344 return GetSpeechRecognitionContents();
282 } 345 }
283 346
284 void StartPageService::Shutdown() { 347 void StartPageService::Shutdown() {
285 UnloadContents(); 348 UnloadContents();
349 #if defined(OS_CHROMEOS)
350 audio_status_.reset();
351 #endif
286 } 352 }
287 353
288 void StartPageService::WebUILoaded() { 354 void StartPageService::WebUILoaded() {
289 // There's a race condition between the WebUI loading, and calling its JS 355 // There's a race condition between the WebUI loading, and calling its JS
290 // functions. Specifically, calling LoadContents() doesn't mean that the page 356 // functions. Specifically, calling LoadContents() doesn't mean that the page
291 // has loaded, but several code paths make this assumption. This function 357 // has loaded, but several code paths make this assumption. This function
292 // allows us to defer calling JS functions until after the page has finished 358 // allows us to defer calling JS functions until after the page has finished
293 // loading. 359 // loading.
294 webui_finished_loading_ = true; 360 webui_finished_loading_ = true;
295 for (const auto& cb : pending_webui_callbacks_) 361 for (const auto& cb : pending_webui_callbacks_)
(...skipping 20 matching lines...) Expand all
316 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, 382 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
317 std::string()); 383 std::string());
318 } 384 }
319 385
320 void StartPageService::UnloadContents() { 386 void StartPageService::UnloadContents() {
321 contents_.reset(); 387 contents_.reset();
322 webui_finished_loading_ = false; 388 webui_finished_loading_ = false;
323 } 389 }
324 390
325 } // namespace app_list 391 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698