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/search/hotword_service.h" | 5 #include "chrome/browser/search/hotword_service.h" |
6 | 6 |
7 #include "base/i18n/case_conversion.h" | 7 #include "base/i18n/case_conversion.h" |
8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/path_service.h" |
10 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
11 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
12 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
13 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 15 #include "chrome/browser/plugins/plugin_prefs.h" |
14 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/search/hotword_service_factory.h" |
| 18 #include "chrome/common/chrome_paths.h" |
15 #include "chrome/common/extensions/extension_constants.h" | 19 #include "chrome/common/extensions/extension_constants.h" |
16 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
17 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
| 23 #include "content/public/browser/plugin_service.h" |
| 24 #include "content/public/common/webplugininfo.h" |
19 #include "extensions/browser/extension_system.h" | 25 #include "extensions/browser/extension_system.h" |
20 #include "extensions/common/extension.h" | 26 #include "extensions/common/extension.h" |
| 27 #include "grit/generated_resources.h" |
21 #include "ui/base/l10n/l10n_util.h" | 28 #include "ui/base/l10n/l10n_util.h" |
22 | 29 |
23 // The whole file relies on the extension systems but this file is built on | 30 // The whole file relies on the extension systems but this file is built on |
24 // some non-extension supported platforms and including an API header will cause | 31 // some non-extension supported platforms and including an API header will cause |
25 // a compile error since it depends on header files generated by .idl. | 32 // a compile error since it depends on header files generated by .idl. |
26 // TODO(mukai): clean up file dependencies and remove this clause. | 33 // TODO(mukai): clean up file dependencies and remove this clause. |
27 #if defined(ENABLE_EXTENSIONS) | 34 #if defined(ENABLE_EXTENSIONS) |
28 #include "chrome/browser/extensions/api/hotword_private/hotword_private_api.h" | 35 #include "chrome/browser/extensions/api/hotword_private/hotword_private_api.h" |
29 #endif | 36 #endif |
30 | 37 |
(...skipping 27 matching lines...) Expand all Loading... |
58 // This is used for UMA stats -- do not reorder or delete items; only add to | 65 // This is used for UMA stats -- do not reorder or delete items; only add to |
59 // the end. | 66 // the end. |
60 enum HotwordExtensionAvailability { | 67 enum HotwordExtensionAvailability { |
61 UNAVAILABLE = 0, | 68 UNAVAILABLE = 0, |
62 AVAILABLE, | 69 AVAILABLE, |
63 PENDING_DOWNLOAD, | 70 PENDING_DOWNLOAD, |
64 DISABLED_EXTENSION, | 71 DISABLED_EXTENSION, |
65 NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS | 72 NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS |
66 }; | 73 }; |
67 | 74 |
68 void RecordAvailabilityMetrics( | 75 // Enum describing the types of errors that can arise when determining |
| 76 // if hotwording can be used. NO_ERROR is used so it can be seen how often |
| 77 // errors arise relative to when they do not. |
| 78 // This is used for UMA stats -- do not reorder or delete items; only add to |
| 79 // the end. |
| 80 enum HotwordError { |
| 81 NO_ERROR = 0, |
| 82 GENERIC_ERROR, |
| 83 NACL_ERROR, |
| 84 MICROPHONE_ERROR, |
| 85 NUM_HOTWORD_ERROR_METRICS |
| 86 }; |
| 87 |
| 88 void RecordExtensionAvailabilityMetrics( |
69 ExtensionService* service, | 89 ExtensionService* service, |
70 const extensions::Extension* extension) { | 90 const extensions::Extension* extension) { |
71 HotwordExtensionAvailability availability_state = UNAVAILABLE; | 91 HotwordExtensionAvailability availability_state = UNAVAILABLE; |
72 if (extension) { | 92 if (extension) { |
73 availability_state = AVAILABLE; | 93 availability_state = AVAILABLE; |
74 } else if (service->pending_extension_manager() && | 94 } else if (service->pending_extension_manager() && |
75 service->pending_extension_manager()->IsIdPending( | 95 service->pending_extension_manager()->IsIdPending( |
76 extension_misc::kHotwordExtensionId)) { | 96 extension_misc::kHotwordExtensionId)) { |
77 availability_state = PENDING_DOWNLOAD; | 97 availability_state = PENDING_DOWNLOAD; |
78 } else if (!service->IsExtensionEnabled( | 98 } else if (!service->IsExtensionEnabled( |
79 extension_misc::kHotwordExtensionId)) { | 99 extension_misc::kHotwordExtensionId)) { |
80 availability_state = DISABLED_EXTENSION; | 100 availability_state = DISABLED_EXTENSION; |
81 } | 101 } |
82 UMA_HISTOGRAM_ENUMERATION("Hotword.HotwordExtensionAvailability", | 102 UMA_HISTOGRAM_ENUMERATION("Hotword.HotwordExtensionAvailability", |
83 availability_state, | 103 availability_state, |
84 NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS); | 104 NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS); |
85 } | 105 } |
86 | 106 |
87 void RecordLoggingMetrics(Profile* profile) { | 107 void RecordLoggingMetrics(Profile* profile) { |
88 // If the user is not opted in to hotword voice search, the audio logging | 108 // If the user is not opted in to hotword voice search, the audio logging |
89 // metric is not valid so it is not recorded. | 109 // metric is not valid so it is not recorded. |
90 if (!profile->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) | 110 if (!profile->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) |
91 return; | 111 return; |
92 | 112 |
93 UMA_HISTOGRAM_BOOLEAN( | 113 UMA_HISTOGRAM_BOOLEAN( |
94 "Hotword.HotwordAudioLogging", | 114 "Hotword.HotwordAudioLogging", |
95 profile->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled)); | 115 profile->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled)); |
96 } | 116 } |
97 | 117 |
| 118 void RecordErrorMetrics(int error_message) { |
| 119 HotwordError error = NO_ERROR; |
| 120 switch (error_message) { |
| 121 case IDS_HOTWORD_GENERIC_ERROR_MESSAGE: |
| 122 error = GENERIC_ERROR; |
| 123 break; |
| 124 case IDS_HOTWORD_NACL_DISABLED_ERROR_MESSAGE: |
| 125 error = NACL_ERROR; |
| 126 break; |
| 127 default: |
| 128 error = NO_ERROR; |
| 129 } |
| 130 |
| 131 UMA_HISTOGRAM_ENUMERATION("Hotword.HotwordError", |
| 132 error, |
| 133 NUM_HOTWORD_ERROR_METRICS); |
| 134 } |
| 135 |
98 ExtensionService* GetExtensionService(Profile* profile) { | 136 ExtensionService* GetExtensionService(Profile* profile) { |
99 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 137 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
100 | 138 |
101 extensions::ExtensionSystem* extension_system = | 139 extensions::ExtensionSystem* extension_system = |
102 extensions::ExtensionSystem::Get(profile); | 140 extensions::ExtensionSystem::Get(profile); |
103 if (extension_system) | 141 if (extension_system) |
104 return extension_system->extension_service(); | 142 return extension_system->extension_service(); |
105 return NULL; | 143 return NULL; |
106 } | 144 } |
107 | 145 |
(...skipping 21 matching lines...) Expand all Loading... |
129 | 167 |
130 for (size_t i = 0; i < arraysize(kSupportedLocales); i++) { | 168 for (size_t i = 0; i < arraysize(kSupportedLocales); i++) { |
131 if (normalized_locale.compare(0, 2, kSupportedLocales[i]) == 0) | 169 if (normalized_locale.compare(0, 2, kSupportedLocales[i]) == 0) |
132 return true; | 170 return true; |
133 } | 171 } |
134 return false; | 172 return false; |
135 } | 173 } |
136 | 174 |
137 HotwordService::HotwordService(Profile* profile) | 175 HotwordService::HotwordService(Profile* profile) |
138 : profile_(profile), | 176 : profile_(profile), |
139 client_(NULL) { | 177 client_(NULL), |
| 178 error_message_(0) { |
140 // This will be called during profile initialization which is a good time | 179 // This will be called during profile initialization which is a good time |
141 // to check the user's hotword state. | 180 // to check the user's hotword state. |
142 HotwordEnabled enabled_state = UNSET; | 181 HotwordEnabled enabled_state = UNSET; |
143 if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) { | 182 if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) { |
144 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) | 183 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) |
145 enabled_state = ENABLED; | 184 enabled_state = ENABLED; |
146 else | 185 else |
147 enabled_state = DISABLED; | 186 enabled_state = DISABLED; |
148 } else { | 187 } else { |
149 // If the preference has not been set the hotword extension should | 188 // If the preference has not been set the hotword extension should |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 | 258 |
220 void HotwordService::ShowOptInPopup() { | 259 void HotwordService::ShowOptInPopup() { |
221 int number_shown = profile_->GetPrefs()->GetInteger( | 260 int number_shown = profile_->GetPrefs()->GetInteger( |
222 prefs::kHotwordOptInPopupTimesShown); | 261 prefs::kHotwordOptInPopupTimesShown); |
223 profile_->GetPrefs()->SetInteger(prefs::kHotwordOptInPopupTimesShown, | 262 profile_->GetPrefs()->SetInteger(prefs::kHotwordOptInPopupTimesShown, |
224 ++number_shown); | 263 ++number_shown); |
225 // TODO(rlp): actually show opt in popup when linked up to extension. | 264 // TODO(rlp): actually show opt in popup when linked up to extension. |
226 } | 265 } |
227 | 266 |
228 bool HotwordService::IsServiceAvailable() { | 267 bool HotwordService::IsServiceAvailable() { |
| 268 error_message_ = 0; |
| 269 |
| 270 // Determine if the extension is available. |
229 extensions::ExtensionSystem* system = | 271 extensions::ExtensionSystem* system = |
230 extensions::ExtensionSystem::Get(profile_); | 272 extensions::ExtensionSystem::Get(profile_); |
231 ExtensionService* service = system->extension_service(); | 273 ExtensionService* service = system->extension_service(); |
232 // Include disabled extensions (true parameter) since it may not be enabled | 274 // Include disabled extensions (true parameter) since it may not be enabled |
233 // if the user opted out. | 275 // if the user opted out. |
234 const extensions::Extension* extension = | 276 const extensions::Extension* extension = |
235 service->GetExtensionById(extension_misc::kHotwordExtensionId, true); | 277 service->GetExtensionById(extension_misc::kHotwordExtensionId, true); |
| 278 if (!extension) |
| 279 error_message_ = IDS_HOTWORD_GENERIC_ERROR_MESSAGE; |
236 | 280 |
237 RecordAvailabilityMetrics(service, extension); | 281 RecordExtensionAvailabilityMetrics(service, extension); |
238 RecordLoggingMetrics(profile_); | 282 RecordLoggingMetrics(profile_); |
239 | 283 |
240 return extension && IsHotwordAllowed(); | 284 // Determine if NaCl is available. |
| 285 bool nacl_enabled = false; |
| 286 base::FilePath path; |
| 287 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) { |
| 288 content::WebPluginInfo info; |
| 289 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get(); |
| 290 if (content::PluginService::GetInstance()->GetPluginInfoByPath(path, &info)) |
| 291 nacl_enabled = plugin_prefs->IsPluginEnabled(info); |
| 292 } |
| 293 if (!nacl_enabled) |
| 294 error_message_ = IDS_HOTWORD_NACL_DISABLED_ERROR_MESSAGE; |
| 295 |
| 296 RecordErrorMetrics(error_message_); |
| 297 |
| 298 return (error_message_ == 0) && IsHotwordAllowed(); |
241 } | 299 } |
242 | 300 |
243 bool HotwordService::IsHotwordAllowed() { | 301 bool HotwordService::IsHotwordAllowed() { |
244 std::string group = base::FieldTrialList::FindFullName( | 302 std::string group = base::FieldTrialList::FindFullName( |
245 hotword_internal::kHotwordFieldTrialName); | 303 hotword_internal::kHotwordFieldTrialName); |
246 return !group.empty() && | 304 return !group.empty() && |
247 group != hotword_internal::kHotwordFieldTrialDisabledGroupName && | 305 group != hotword_internal::kHotwordFieldTrialDisabledGroupName && |
248 DoesHotwordSupportLanguage(profile_); | 306 DoesHotwordSupportLanguage(profile_); |
249 } | 307 } |
250 | 308 |
251 bool HotwordService::IsOptedIntoAudioLogging() { | 309 bool HotwordService::IsOptedIntoAudioLogging() { |
252 // Do not opt the user in if the preference has not been set. | 310 // Do not opt the user in if the preference has not been set. |
253 return | 311 return |
254 profile_->GetPrefs()->HasPrefPath(prefs::kHotwordAudioLoggingEnabled) && | 312 profile_->GetPrefs()->HasPrefPath(prefs::kHotwordAudioLoggingEnabled) && |
255 profile_->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled); | 313 profile_->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled); |
256 } | 314 } |
257 | 315 |
258 bool HotwordService::RetryHotwordExtension() { | |
259 ExtensionService* extension_service = GetExtensionService(profile_); | |
260 if (!extension_service) | |
261 return false; | |
262 | |
263 extension_service->ReloadExtension(extension_misc::kHotwordExtensionId); | |
264 return true; | |
265 } | |
266 | |
267 void HotwordService::EnableHotwordExtension( | 316 void HotwordService::EnableHotwordExtension( |
268 ExtensionService* extension_service) { | 317 ExtensionService* extension_service) { |
269 if (extension_service) | 318 if (extension_service) |
270 extension_service->EnableExtension(extension_misc::kHotwordExtensionId); | 319 extension_service->EnableExtension(extension_misc::kHotwordExtensionId); |
271 } | 320 } |
272 | 321 |
273 void HotwordService::DisableHotwordExtension( | 322 void HotwordService::DisableHotwordExtension( |
274 ExtensionService* extension_service) { | 323 ExtensionService* extension_service) { |
275 if (extension_service) { | 324 if (extension_service) { |
276 extension_service->DisableExtension( | 325 extension_service->DisableExtension( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 | 360 |
312 DCHECK(client_ == client); | 361 DCHECK(client_ == client); |
313 | 362 |
314 client_ = NULL; | 363 client_ = NULL; |
315 HotwordPrivateEventService* event_service = | 364 HotwordPrivateEventService* event_service = |
316 BrowserContextKeyedAPIFactory<HotwordPrivateEventService>::Get(profile_); | 365 BrowserContextKeyedAPIFactory<HotwordPrivateEventService>::Get(profile_); |
317 if (event_service) | 366 if (event_service) |
318 event_service->OnHotwordSessionStopped(); | 367 event_service->OnHotwordSessionStopped(); |
319 #endif | 368 #endif |
320 } | 369 } |
OLD | NEW |