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