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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 }; | 274 }; |
275 | 275 |
276 // static | 276 // static |
277 StartPageService* StartPageService::Get(Profile* profile) { | 277 StartPageService* StartPageService::Get(Profile* profile) { |
278 return StartPageServiceFactory::GetForProfile(profile); | 278 return StartPageServiceFactory::GetForProfile(profile); |
279 } | 279 } |
280 | 280 |
281 StartPageService::StartPageService(Profile* profile) | 281 StartPageService::StartPageService(Profile* profile) |
282 : profile_(profile), | 282 : profile_(profile), |
283 profile_destroy_observer_(new ProfileDestroyObserver(this)), | 283 profile_destroy_observer_(new ProfileDestroyObserver(this)), |
284 state_(app_list::SPEECH_RECOGNITION_OFF), | 284 state_(app_list::SPEECH_RECOGNITION_READY), |
285 speech_button_toggled_manually_(false), | 285 speech_button_toggled_manually_(false), |
286 speech_result_obtained_(false), | 286 speech_result_obtained_(false), |
287 webui_finished_loading_(false), | 287 webui_finished_loading_(false), |
288 speech_auth_helper_(new SpeechAuthHelper(profile, &clock_)), | 288 speech_auth_helper_(new SpeechAuthHelper(profile, &clock_)), |
289 network_available_(true), | 289 network_available_(true), |
290 microphone_available_(true), | 290 microphone_available_(true), |
291 search_engine_is_google_(false), | 291 search_engine_is_google_(false), |
292 weak_factory_(this) { | 292 weak_factory_(this) { |
293 // If experimental hotwording is enabled, then we're always "ready". | |
294 // Transitioning into the "hotword recognizing" state is handled by the | |
295 // hotword extension. | |
296 if (HotwordService::IsExperimentalHotwordingEnabled()) { | |
297 state_ = app_list::SPEECH_RECOGNITION_READY; | |
298 } | |
299 if (switches::IsExperimentalAppListEnabled()) { | 293 if (switches::IsExperimentalAppListEnabled()) { |
300 TemplateURLService* template_url_service = | 294 TemplateURLService* template_url_service = |
301 TemplateURLServiceFactory::GetForProfile(profile_); | 295 TemplateURLServiceFactory::GetForProfile(profile_); |
302 const TemplateURL* default_provider = | 296 const TemplateURL* default_provider = |
303 template_url_service->GetDefaultSearchProvider(); | 297 template_url_service->GetDefaultSearchProvider(); |
304 search_engine_is_google_ = | 298 search_engine_is_google_ = |
305 TemplateURLPrepopulateData::GetEngineType( | 299 TemplateURLPrepopulateData::GetEngineType( |
306 *default_provider, template_url_service->search_terms_data()) == | 300 *default_provider, template_url_service->search_terms_data()) == |
307 SEARCH_ENGINE_GOOGLE; | 301 SEARCH_ENGINE_GOOGLE; |
308 } | 302 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 bool StartPageService::ShouldEnableSpeechRecognition() const { | 356 bool StartPageService::ShouldEnableSpeechRecognition() const { |
363 return microphone_available_ && network_available_; | 357 return microphone_available_ && network_available_; |
364 } | 358 } |
365 | 359 |
366 void StartPageService::AppListShown() { | 360 void StartPageService::AppListShown() { |
367 if (!contents_) { | 361 if (!contents_) { |
368 LoadContents(); | 362 LoadContents(); |
369 } else if (contents_->IsCrashed()) { | 363 } else if (contents_->IsCrashed()) { |
370 LoadStartPageURL(); | 364 LoadStartPageURL(); |
371 } else if (contents_->GetWebUI()) { | 365 } else if (contents_->GetWebUI()) { |
372 // If experimental hotwording is enabled, don't initialize the web speech | |
373 // API, which is not used with | |
374 // experimental hotwording. | |
375 contents_->GetWebUI()->CallJavascriptFunction( | 366 contents_->GetWebUI()->CallJavascriptFunction( |
376 "appList.startPage.onAppListShown", | 367 "appList.startPage.onAppListShown"); |
377 base::FundamentalValue(HotwordEnabled()), | |
378 base::FundamentalValue( | |
379 !HotwordService::IsExperimentalHotwordingEnabled())); | |
380 } | 368 } |
381 | 369 |
382 #if defined(OS_CHROMEOS) | 370 #if defined(OS_CHROMEOS) |
383 audio_status_.reset(new AudioStatus(this)); | 371 audio_status_.reset(new AudioStatus(this)); |
384 #endif | 372 #endif |
385 } | 373 } |
386 | 374 |
387 void StartPageService::AppListHidden() { | 375 void StartPageService::AppListHidden() { |
388 if (contents_->GetWebUI()) { | |
389 contents_->GetWebUI()->CallJavascriptFunction( | |
390 "appList.startPage.onAppListHidden"); | |
391 } | |
392 if (!app_list::switches::IsExperimentalAppListEnabled()) | 376 if (!app_list::switches::IsExperimentalAppListEnabled()) |
393 UnloadContents(); | 377 UnloadContents(); |
394 | 378 |
395 if (HotwordService::IsExperimentalHotwordingEnabled() && | 379 if (speech_recognizer_) { |
396 speech_recognizer_) { | |
397 speech_recognizer_->Stop(); | 380 speech_recognizer_->Stop(); |
398 speech_recognizer_.reset(); | 381 speech_recognizer_.reset(); |
399 | 382 |
400 // When the SpeechRecognizer is destroyed above, we get stuck in the current | 383 // When the SpeechRecognizer is destroyed above, we get stuck in the current |
401 // speech state instead of being reset into the READY state. Reset the | 384 // speech state instead of being reset into the READY state. Reset the |
402 // speech state explicitly so that speech works when the launcher is opened | 385 // speech state explicitly so that speech works when the launcher is opened |
403 // again. | 386 // again. |
404 OnSpeechRecognitionStateChanged(SPEECH_RECOGNITION_READY); | 387 OnSpeechRecognitionStateChanged(SPEECH_RECOGNITION_READY); |
405 } | 388 } |
406 | 389 |
407 #if defined(OS_CHROMEOS) | 390 #if defined(OS_CHROMEOS) |
408 audio_status_.reset(); | 391 audio_status_.reset(); |
409 #endif | 392 #endif |
410 } | 393 } |
411 | 394 |
412 void StartPageService::ToggleSpeechRecognition( | 395 void StartPageService::ToggleSpeechRecognition( |
413 const scoped_refptr<content::SpeechRecognitionSessionPreamble>& preamble) { | 396 const scoped_refptr<content::SpeechRecognitionSessionPreamble>& preamble) { |
414 DCHECK(contents_); | 397 DCHECK(contents_); |
415 speech_button_toggled_manually_ = true; | 398 speech_button_toggled_manually_ = true; |
416 | 399 |
417 // Speech recognition under V2 hotwording does not depend in any way on the | 400 if (!speech_recognizer_) { |
418 // start page web contents. Do this code path first to make this explicit and | 401 std::string profile_locale; |
419 // easier to identify what code needs to be deleted when V2 hotwording is | |
420 // stable. | |
421 if (HotwordService::IsExperimentalHotwordingEnabled()) { | |
422 if (!speech_recognizer_) { | |
423 std::string profile_locale; | |
424 #if defined(OS_CHROMEOS) | 402 #if defined(OS_CHROMEOS) |
425 profile_locale = profile_->GetPrefs()->GetString( | 403 profile_locale = profile_->GetPrefs()->GetString( |
426 prefs::kApplicationLocale); | 404 prefs::kApplicationLocale); |
427 #endif | 405 #endif |
428 if (profile_locale.empty()) | 406 if (profile_locale.empty()) |
429 profile_locale = g_browser_process->GetApplicationLocale(); | 407 profile_locale = g_browser_process->GetApplicationLocale(); |
430 | 408 |
431 speech_recognizer_.reset( | 409 speech_recognizer_.reset( |
432 new SpeechRecognizer(weak_factory_.GetWeakPtr(), | 410 new SpeechRecognizer(weak_factory_.GetWeakPtr(), |
433 profile_->GetRequestContext(), | 411 profile_->GetRequestContext(), |
434 profile_locale)); | 412 profile_locale)); |
435 } | |
436 | |
437 speech_recognizer_->Start(preamble); | |
438 return; | |
439 } | 413 } |
440 | 414 |
441 if (!contents_->GetWebUI()) | 415 speech_recognizer_->Start(preamble); |
442 return; | |
443 | |
444 if (!webui_finished_loading_) { | |
445 pending_webui_callbacks_.push_back( | |
446 base::Bind(&StartPageService::ToggleSpeechRecognition, | |
447 base::Unretained(this), | |
448 preamble)); | |
449 return; | |
450 } | |
451 | |
452 contents_->GetWebUI()->CallJavascriptFunction( | |
453 "appList.startPage.toggleSpeechRecognition"); | |
454 } | 416 } |
455 | 417 |
456 bool StartPageService::HotwordEnabled() { | 418 bool StartPageService::HotwordEnabled() { |
457 // Voice input for the launcher is unsupported on non-ChromeOS platforms. | 419 // Voice input for the launcher is unsupported on non-ChromeOS platforms. |
458 // TODO(amistry): Make speech input, and hotwording, work on non-ChromeOS. | 420 // TODO(amistry): Make speech input, and hotwording, work on non-ChromeOS. |
459 #if defined(OS_CHROMEOS) | 421 #if defined(OS_CHROMEOS) |
460 if (HotwordService::IsExperimentalHotwordingEnabled()) { | 422 HotwordService* service = HotwordServiceFactory::GetForProfile(profile_); |
461 HotwordService* service = HotwordServiceFactory::GetForProfile(profile_); | 423 return state_ != SPEECH_RECOGNITION_OFF && |
462 return state_ != SPEECH_RECOGNITION_OFF && | 424 service && |
463 service && | 425 (service->IsSometimesOnEnabled() || service->IsAlwaysOnEnabled()) && |
464 (service->IsSometimesOnEnabled() || service->IsAlwaysOnEnabled()) && | 426 service->IsServiceAvailable(); |
465 service->IsServiceAvailable(); | |
466 } | |
467 return HotwordServiceFactory::IsServiceAvailable(profile_) && | |
468 profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled); | |
469 #else | 427 #else |
470 return false; | 428 return false; |
471 #endif | 429 #endif |
472 } | 430 } |
473 | 431 |
474 content::WebContents* StartPageService::GetStartPageContents() { | 432 content::WebContents* StartPageService::GetStartPageContents() { |
475 return app_list::switches::IsExperimentalAppListEnabled() ? contents_.get() | 433 return app_list::switches::IsExperimentalAppListEnabled() ? contents_.get() |
476 : NULL; | 434 : NULL; |
477 } | 435 } |
478 | 436 |
(...skipping 29 matching lines...) Expand all Loading... |
508 // Sometimes this can be called even though there are no audio input devices. | 466 // Sometimes this can be called even though there are no audio input devices. |
509 if (audio_status_ && !audio_status_->CanListen()) | 467 if (audio_status_ && !audio_status_->CanListen()) |
510 new_state = SPEECH_RECOGNITION_OFF; | 468 new_state = SPEECH_RECOGNITION_OFF; |
511 #endif | 469 #endif |
512 if (!ShouldEnableSpeechRecognition()) | 470 if (!ShouldEnableSpeechRecognition()) |
513 new_state = SPEECH_RECOGNITION_OFF; | 471 new_state = SPEECH_RECOGNITION_OFF; |
514 | 472 |
515 if (state_ == new_state) | 473 if (state_ == new_state) |
516 return; | 474 return; |
517 | 475 |
518 if (HotwordService::IsExperimentalHotwordingEnabled() && | 476 if ((new_state == SPEECH_RECOGNITION_READY || |
519 (new_state == SPEECH_RECOGNITION_READY || | |
520 new_state == SPEECH_RECOGNITION_OFF) && | 477 new_state == SPEECH_RECOGNITION_OFF) && |
521 speech_recognizer_) { | 478 speech_recognizer_) { |
522 speech_recognizer_->Stop(); | 479 speech_recognizer_->Stop(); |
523 } | 480 } |
524 | 481 |
525 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) { | 482 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) { |
526 if (!speech_button_toggled_manually_ && | 483 if (!speech_button_toggled_manually_ && |
527 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) { | 484 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) { |
528 RecordAction(UserMetricsAction("AppList_HotwordRecognized")); | 485 RecordAction(UserMetricsAction("AppList_HotwordRecognized")); |
529 } else { | 486 } else { |
530 RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually")); | 487 RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually")); |
531 } | 488 } |
532 } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) && | 489 } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) && |
533 !speech_result_obtained_) { | 490 !speech_result_obtained_) { |
534 RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled")); | 491 RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled")); |
535 } | 492 } |
536 speech_button_toggled_manually_ = false; | 493 speech_button_toggled_manually_ = false; |
537 speech_result_obtained_ = false; | 494 speech_result_obtained_ = false; |
538 state_ = new_state; | 495 state_ = new_state; |
539 FOR_EACH_OBSERVER(StartPageObserver, | 496 FOR_EACH_OBSERVER(StartPageObserver, |
540 observers_, | 497 observers_, |
541 OnSpeechRecognitionStateChanged(new_state)); | 498 OnSpeechRecognitionStateChanged(new_state)); |
542 } | 499 } |
543 | 500 |
544 void StartPageService::GetSpeechAuthParameters(std::string* auth_scope, | 501 void StartPageService::GetSpeechAuthParameters(std::string* auth_scope, |
545 std::string* auth_token) { | 502 std::string* auth_token) { |
546 if (HotwordService::IsExperimentalHotwordingEnabled()) { | 503 HotwordService* service = HotwordServiceFactory::GetForProfile(profile_); |
547 HotwordService* service = HotwordServiceFactory::GetForProfile(profile_); | 504 if (service && |
548 if (service && | 505 service->IsOptedIntoAudioLogging() && |
549 service->IsOptedIntoAudioLogging() && | 506 service->IsAlwaysOnEnabled() && |
550 service->IsAlwaysOnEnabled() && | 507 !speech_auth_helper_->GetToken().empty()) { |
551 !speech_auth_helper_->GetToken().empty()) { | 508 *auth_scope = speech_auth_helper_->GetScope(); |
552 *auth_scope = speech_auth_helper_->GetScope(); | 509 *auth_token = speech_auth_helper_->GetToken(); |
553 *auth_token = speech_auth_helper_->GetToken(); | |
554 } | |
555 } | 510 } |
556 } | 511 } |
557 | 512 |
558 void StartPageService::Shutdown() { | 513 void StartPageService::Shutdown() { |
559 UnloadContents(); | 514 UnloadContents(); |
560 #if defined(OS_CHROMEOS) | 515 #if defined(OS_CHROMEOS) |
561 audio_status_.reset(); | 516 audio_status_.reset(); |
562 #endif | 517 #endif |
563 | 518 |
564 speech_auth_helper_.reset(); | 519 speech_auth_helper_.reset(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 | 646 |
692 // Check for a new doodle. | 647 // Check for a new doodle. |
693 content::BrowserThread::PostDelayedTask( | 648 content::BrowserThread::PostDelayedTask( |
694 content::BrowserThread::UI, FROM_HERE, | 649 content::BrowserThread::UI, FROM_HERE, |
695 base::Bind(&StartPageService::FetchDoodleJson, | 650 base::Bind(&StartPageService::FetchDoodleJson, |
696 weak_factory_.GetWeakPtr()), | 651 weak_factory_.GetWeakPtr()), |
697 recheck_delay); | 652 recheck_delay); |
698 } | 653 } |
699 | 654 |
700 } // namespace app_list | 655 } // namespace app_list |
OLD | NEW |