hotword_service.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 3// found in the LICENSE file. 4 5#include "chrome/browser/search/hotword_service.h" 6 7#include "base/i18n/case_conversion.h" 8#include "base/metrics/field_trial.h" 9#include "base/metrics/histogram.h" 10#include "base/prefs/pref_service.h" 11#include "chrome/browser/browser_process.h" 12#include "chrome/browser/extensions/extension_service.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/common/extensions/extension_constants.h" 15#include "chrome/common/pref_names.h" 16#include "extensions/browser/extension_system.h" 17#include "extensions/common/extension.h" 18#include "ui/base/l10n/l10n_util.h" 19 20namespace { 21const int kMaxTimesToShowOptInPopup = 10; 22 23// Enum describing the state of the hotword preference. 24// This is used for UMA stats -- do not reorder or delete items; only add to 25// the end. 26enum HotwordEnabled { 27 UNSET = 0, // The hotword preference has not been set. 28 ENABLED, // The hotword preference is enabled. 29 DISABLED, // The hotword preference is disabled. 30 NUM_HOTWORD_ENABLED_METRICS 31}; 32 33// Enum describing the availability state of the hotword extension. 34// This is used for UMA stats -- do not reorder or delete items; only add to 35// the end. 36enum HotwordExtensionAvailability { 37 UNAVAILABLE = 0, 38 AVAILABLE, 39 PENDING_DOWNLOAD, 40 DISABLED_EXTENSION, 41 NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS 42}; 43 44void RecordAvailabilityMetrics( 45 ExtensionService* service, 46 const extensions::Extension* extension) { 47 HotwordExtensionAvailability availability_state = UNAVAILABLE; 48 if (extension) { 49 availability_state = AVAILABLE; 50 } else if (service->pending_extension_manager() && 51 service->pending_extension_manager()->IsIdPending( 52 extension_misc::kHotwordExtensionId)) { 53 availability_state = PENDING_DOWNLOAD; 54 } else if (!service->IsExtensionEnabled( 55 extension_misc::kHotwordExtensionId)) { 56 availability_state = DISABLED_EXTENSION; 57 } 58 UMA_HISTOGRAM_ENUMERATION("Hotword.HotwordExtensionAvailability", 59 availability_state, 60 NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS); 61} 62 63} // namespace 64 65namespace hotword_internal { 66// Constants for the hotword field trial. 67const char kHotwordFieldTrialName[] = "VoiceTrigger"; 68const char kHotwordFieldTrialDisabledGroupName[] = "Disabled"; 69} // namespace hotword_internal 70 71// static 72bool HotwordService::DoesHotwordSupportLanguage(Profile* profile) { 73 std::string locale = 74#if defined(OS_CHROMEOS) 75 // On ChromeOS locale is per-profile. 76 profile->GetPrefs()->GetString(prefs::kApplicationLocale); 77#else 78 g_browser_process->GetApplicationLocale(); 79#endif 80 // Only available for English now. 81 std::string normalized_locale = l10n_util::NormalizeLocale(locale); 82 return normalized_locale == "en" || normalized_locale == "en_us" || 83 normalized_locale =="en_US"; 84} 85 86HotwordService::HotwordService(Profile* profile) 87 : profile_(profile) { 88 // This will be called during profile initialization which is a good time 89 // to check the user's hotword state. 90 HotwordEnabled enabled_state = UNSET; 91 if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) { 92 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) 93 enabled_state = ENABLED; 94 else 95 enabled_state = DISABLED; 96 } 97 UMA_HISTOGRAM_ENUMERATION("Hotword.Enabled", enabled_state, 98 NUM_HOTWORD_ENABLED_METRICS); 99} 100 101HotwordService::~HotwordService() { 102} 103 104bool HotwordService::ShouldShowOptInPopup() { 105 if (profile_->IsOffTheRecord()) 106 return false; 107 108 // Profile is not off the record. 109 if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) 110 return false; // Already opted in or opted out; 111 112 int number_shown = profile_->GetPrefs()->GetInteger( 113 prefs::kHotwordOptInPopupTimesShown); 114 return number_shown < MaxNumberTimesToShowOptInPopup(); 115} 116 117int HotwordService::MaxNumberTimesToShowOptInPopup() { 118 return kMaxTimesToShowOptInPopup; 119} 120 121void HotwordService::ShowOptInPopup() { 122 int number_shown = profile_->GetPrefs()->GetInteger( 123 prefs::kHotwordOptInPopupTimesShown); 124 profile_->GetPrefs()->SetInteger(prefs::kHotwordOptInPopupTimesShown, 125 ++number_shown); 126 // TODO(rlp): actually show opt in popup when linked up to extension. 127} 128 129bool HotwordService::IsServiceAvailable() { 130 extensions::ExtensionSystem* system = 131 extensions::ExtensionSystem::Get(profile_); 132 ExtensionService* service = system->extension_service(); 133 // Do not include disabled extension (false parameter) because if the 134 // extension is disabled, it's not available. 135 const extensions::Extension* extension = 136 service->GetExtensionById(extension_misc::kHotwordExtensionId, false); 137 138 RecordAvailabilityMetrics(service, extension); 139 140 return extension && IsHotwordAllowed(); 141} 142 143bool HotwordService::IsHotwordAllowed() { 144 std::string group = base::FieldTrialList::FindFullName( 145 hotword_internal::kHotwordFieldTrialName); 146 return !group.empty() && 147 group != hotword_internal::kHotwordFieldTrialDisabledGroupName && 148 DoesHotwordSupportLanguage(profile_); 149} 150