hotword_service.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file. 48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/search/hotword_service.h" 68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/i18n/case_conversion.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/field_trial.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/browser_process.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/chrome_notification_types.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/browser/notification_service.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMaxTimesToShowOptInPopup = 10; 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Allowed languages for hotwording. 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic const char* kSupportedLocales[] = { 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "en", 29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "en_us" 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Enum describing the state of the hotword preference. 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This is used for UMA stats -- do not reorder or delete items; only add to 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the end. 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum HotwordEnabled { 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UNSET = 0, // The hotword preference has not been set. 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ENABLED, // The hotword preference is enabled. 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISABLED, // The hotword preference is disabled. 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NUM_HOTWORD_ENABLED_METRICS 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Enum describing the availability state of the hotword extension. 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This is used for UMA stats -- do not reorder or delete items; only add to 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the end. 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum HotwordExtensionAvailability { 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UNAVAILABLE = 0, 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AVAILABLE, 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PENDING_DOWNLOAD, 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISABLED_EXTENSION, 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RecordAvailabilityMetrics( 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionService* service, 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const extensions::Extension* extension) { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HotwordExtensionAvailability availability_state = UNAVAILABLE; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension) { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) availability_state = AVAILABLE; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (service->pending_extension_manager() && 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) service->pending_extension_manager()->IsIdPending( 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_misc::kHotwordExtensionId)) { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) availability_state = PENDING_DOWNLOAD; 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (!service->IsExtensionEnabled( 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_misc::kHotwordExtensionId)) { 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) availability_state = DISABLED_EXTENSION; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Hotword.HotwordExtensionAvailability", 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) availability_state, 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordLoggingMetrics(Profile* profile) { 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the user is not opted in to hotword voice search, the audio logging 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // metric is not valid so it is not recorded. 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!profile->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_BOOLEAN( 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "Hotword.HotwordAudioLogging", 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch profile->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled)); 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ExtensionService* GetExtensionService(Profile* profile) { 8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extensions::ExtensionSystem* extension_system = 8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extensions::ExtensionSystem::Get(profile); 8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (extension_system) 8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return extension_system->extension_service(); 9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return NULL; 9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace hotword_internal { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Constants for the hotword field trial. 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kHotwordFieldTrialName[] = "VoiceTrigger"; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kHotwordFieldTrialDisabledGroupName[] = "Disabled"; 99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Old preference constant. 100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kHotwordUnusablePrefName[] = "hotword.search_enabled"; 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace hotword_internal 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HotwordService::DoesHotwordSupportLanguage(Profile* profile) { 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string locale = 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // On ChromeOS locale is per-profile. 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile->GetPrefs()->GetString(prefs::kApplicationLocale); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_browser_process->GetApplicationLocale(); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string normalized_locale = l10n_util::NormalizeLocale(locale); 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch StringToLowerASCII(&normalized_locale); 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (size_t i = 0; i < arraysize(kSupportedLocales); i++) { 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (kSupportedLocales[i] == normalized_locale) 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)HotwordService::HotwordService(Profile* profile) 1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : profile_(profile) { 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This will be called during profile initialization which is a good time 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to check the user's hotword state. 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HotwordEnabled enabled_state = UNSET; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_state = ENABLED; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enabled_state = DISABLED; 13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // If the preference has not been set the hotword extension should 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // not be running. However, this should only be done if auto-install 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // is enabled which is gated through the IsHotwordAllowed check. 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (IsHotwordAllowed()) 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DisableHotwordExtension(GetExtensionService(profile_)); 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Hotword.Enabled", enabled_state, 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NUM_HOTWORD_ENABLED_METRICS); 14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) pref_registrar_.Init(profile_->GetPrefs()); 14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) pref_registrar_.Add( 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) prefs::kHotwordSearchEnabled, 14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Bind(&HotwordService::OnHotwordSearchEnabledChanged, 14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::Unretained(this))); 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registrar_.Add(this, 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::NOTIFICATION_EXTENSION_INSTALLED, 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::Source<Profile>(profile_)); 151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Clear the old user pref because it became unusable. 153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TODO(rlp): Remove this code per crbug.com/358789. 154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (profile_->GetPrefs()->HasPrefPath( 155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch hotword_internal::kHotwordUnusablePrefName)) { 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch profile_->GetPrefs()->ClearPref(hotword_internal::kHotwordUnusablePrefName); 157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)HotwordService::~HotwordService() { 1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid HotwordService::Observe(int type, 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const content::NotificationSource& source, 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const content::NotificationDetails& details) { 166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (type == chrome::NOTIFICATION_EXTENSION_INSTALLED) { 167effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const extensions::Extension* extension = 168effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::Details<const extensions::InstalledExtensionInfo>(details) 169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ->extension; 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Disabling the extension automatically on install should only occur 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // if the user is in the field trial for auto-install which is gated 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // by the IsHotwordAllowed check. 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (IsHotwordAllowed() && 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extension->id() == extension_misc::kHotwordExtensionId && 175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) { 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DisableHotwordExtension(GetExtensionService(profile_)); 177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Once the extension is disabled, it will not be enabled until the 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // user opts in at which point the pref registrar will take over 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // enabling and disabling. 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registrar_.Remove(this, 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::NOTIFICATION_EXTENSION_INSTALLED, 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::Source<Profile>(profile_)); 183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HotwordService::ShouldShowOptInPopup() { 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (profile_->IsOffTheRecord()) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Profile is not off the record. 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; // Already opted in or opted out; 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int number_shown = profile_->GetPrefs()->GetInteger( 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kHotwordOptInPopupTimesShown); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return number_shown < MaxNumberTimesToShowOptInPopup(); 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int HotwordService::MaxNumberTimesToShowOptInPopup() { 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kMaxTimesToShowOptInPopup; 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HotwordService::ShowOptInPopup() { 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int number_shown = profile_->GetPrefs()->GetInteger( 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kHotwordOptInPopupTimesShown); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_->GetPrefs()->SetInteger(prefs::kHotwordOptInPopupTimesShown, 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++number_shown); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(rlp): actually show opt in popup when linked up to extension. 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HotwordService::IsServiceAvailable() { 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::ExtensionSystem* system = 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::ExtensionSystem::Get(profile_); 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionService* service = system->extension_service(); 21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Include disabled extensions (true parameter) since it may not be enabled 21723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // if the user opted out. 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const extensions::Extension* extension = 21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) service->GetExtensionById(extension_misc::kHotwordExtensionId, true); 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordAvailabilityMetrics(service, extension); 222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordLoggingMetrics(profile_); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return extension && IsHotwordAllowed(); 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HotwordService::IsHotwordAllowed() { 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string group = base::FieldTrialList::FindFullName( 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) hotword_internal::kHotwordFieldTrialName); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !group.empty() && 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group != hotword_internal::kHotwordFieldTrialDisabledGroupName && 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DoesHotwordSupportLanguage(profile_); 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool HotwordService::IsOptedIntoAudioLogging() { 236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Do not opt the user in if the preference has not been set. 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return 238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch profile_->GetPrefs()->HasPrefPath(prefs::kHotwordAudioLoggingEnabled) && 239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch profile_->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled); 240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool HotwordService::RetryHotwordExtension() { 24323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ExtensionService* extension_service = GetExtensionService(profile_); 24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!extension_service) 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extension_service->ReloadExtension(extension_misc::kHotwordExtensionId); 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 25023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 25123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void HotwordService::EnableHotwordExtension( 25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ExtensionService* extension_service) { 25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (extension_service) 25423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extension_service->EnableExtension(extension_misc::kHotwordExtensionId); 25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void HotwordService::DisableHotwordExtension( 25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ExtensionService* extension_service) { 25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (extension_service) { 26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extension_service->DisableExtension( 26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extension_misc::kHotwordExtensionId, 26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extensions::Extension::DISABLE_USER_ACTION); 26323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void HotwordService::OnHotwordSearchEnabledChanged( 26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const std::string& pref_name) { 26823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_EQ(pref_name, std::string(prefs::kHotwordSearchEnabled)); 26923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 27023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ExtensionService* extension_service = GetExtensionService(profile_); 27123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) 27223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) EnableHotwordExtension(extension_service); 27323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) else 27423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DisableHotwordExtension(extension_service); 27523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 276