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 determing |
Jered
2014/05/19 16:45:52
determing -> determining
rpetterson
2014/05/19 17:39:17
Done.
| |
76 // if hotwording can be used. NO_ERROR is used so errors can be seen as a | |
77 // percentage compared to successes. | |
Jered
2014/05/19 16:45:52
I don't understand this sentence.
rpetterson
2014/05/19 17:39:17
I've reworded it. Hopefully it's clearer.
| |
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; | |
Jered
2014/05/19 16:45:52
Missing "break"s between these case labels.
rpetterson
2014/05/19 17:39:17
Whoops. Done.
| |
123 case IDS_HOTWORD_NACL_DISABLED_ERROR_MESSAGE: | |
124 error = NACL_ERROR; | |
125 default: | |
126 error = NO_ERROR; | |
127 } | |
128 | |
129 UMA_HISTOGRAM_ENUMERATION("Hotword.HotwordError", | |
130 error, | |
131 NUM_HOTWORD_ERROR_METRICS); | |
132 } | |
133 | |
98 ExtensionService* GetExtensionService(Profile* profile) { | 134 ExtensionService* GetExtensionService(Profile* profile) { |
99 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 135 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
100 | 136 |
101 extensions::ExtensionSystem* extension_system = | 137 extensions::ExtensionSystem* extension_system = |
102 extensions::ExtensionSystem::Get(profile); | 138 extensions::ExtensionSystem::Get(profile); |
103 if (extension_system) | 139 if (extension_system) |
104 return extension_system->extension_service(); | 140 return extension_system->extension_service(); |
105 return NULL; | 141 return NULL; |
106 } | 142 } |
107 | 143 |
(...skipping 21 matching lines...) Expand all Loading... | |
129 | 165 |
130 for (size_t i = 0; i < arraysize(kSupportedLocales); i++) { | 166 for (size_t i = 0; i < arraysize(kSupportedLocales); i++) { |
131 if (normalized_locale.compare(0, 2, kSupportedLocales[i]) == 0) | 167 if (normalized_locale.compare(0, 2, kSupportedLocales[i]) == 0) |
132 return true; | 168 return true; |
133 } | 169 } |
134 return false; | 170 return false; |
135 } | 171 } |
136 | 172 |
137 HotwordService::HotwordService(Profile* profile) | 173 HotwordService::HotwordService(Profile* profile) |
138 : profile_(profile), | 174 : profile_(profile), |
139 client_(NULL) { | 175 client_(NULL), |
176 error_message_(0) { | |
140 // This will be called during profile initialization which is a good time | 177 // This will be called during profile initialization which is a good time |
141 // to check the user's hotword state. | 178 // to check the user's hotword state. |
142 HotwordEnabled enabled_state = UNSET; | 179 HotwordEnabled enabled_state = UNSET; |
143 if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) { | 180 if (profile_->GetPrefs()->HasPrefPath(prefs::kHotwordSearchEnabled)) { |
144 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) | 181 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) |
145 enabled_state = ENABLED; | 182 enabled_state = ENABLED; |
146 else | 183 else |
147 enabled_state = DISABLED; | 184 enabled_state = DISABLED; |
148 } else { | 185 } else { |
149 // If the preference has not been set the hotword extension should | 186 // 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 | 256 |
220 void HotwordService::ShowOptInPopup() { | 257 void HotwordService::ShowOptInPopup() { |
221 int number_shown = profile_->GetPrefs()->GetInteger( | 258 int number_shown = profile_->GetPrefs()->GetInteger( |
222 prefs::kHotwordOptInPopupTimesShown); | 259 prefs::kHotwordOptInPopupTimesShown); |
223 profile_->GetPrefs()->SetInteger(prefs::kHotwordOptInPopupTimesShown, | 260 profile_->GetPrefs()->SetInteger(prefs::kHotwordOptInPopupTimesShown, |
224 ++number_shown); | 261 ++number_shown); |
225 // TODO(rlp): actually show opt in popup when linked up to extension. | 262 // TODO(rlp): actually show opt in popup when linked up to extension. |
226 } | 263 } |
227 | 264 |
228 bool HotwordService::IsServiceAvailable() { | 265 bool HotwordService::IsServiceAvailable() { |
266 error_message_ = 0; | |
267 | |
268 // Determine if the extension is available. | |
229 extensions::ExtensionSystem* system = | 269 extensions::ExtensionSystem* system = |
230 extensions::ExtensionSystem::Get(profile_); | 270 extensions::ExtensionSystem::Get(profile_); |
231 ExtensionService* service = system->extension_service(); | 271 ExtensionService* service = system->extension_service(); |
232 // Include disabled extensions (true parameter) since it may not be enabled | 272 // Include disabled extensions (true parameter) since it may not be enabled |
233 // if the user opted out. | 273 // if the user opted out. |
234 const extensions::Extension* extension = | 274 const extensions::Extension* extension = |
235 service->GetExtensionById(extension_misc::kHotwordExtensionId, true); | 275 service->GetExtensionById(extension_misc::kHotwordExtensionId, true); |
276 if (!extension) | |
277 error_message_ = IDS_HOTWORD_GENERIC_ERROR_MESSAGE; | |
236 | 278 |
237 RecordAvailabilityMetrics(service, extension); | 279 RecordExtensionAvailabilityMetrics(service, extension); |
238 RecordLoggingMetrics(profile_); | 280 RecordLoggingMetrics(profile_); |
239 | 281 |
240 return extension && IsHotwordAllowed(); | 282 // Determine if NaCl is available. |
283 bool nacl_enabled = false; | |
284 base::FilePath path; | |
285 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) { | |
286 content::WebPluginInfo info; | |
287 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get(); | |
288 if (content::PluginService::GetInstance()->GetPluginInfoByPath(path, &info)) | |
289 nacl_enabled = plugin_prefs->IsPluginEnabled(info); | |
290 } | |
291 if (!nacl_enabled) | |
292 error_message_ = IDS_HOTWORD_NACL_DISABLED_ERROR_MESSAGE; | |
293 | |
294 RecordErrorMetrics(error_message_); | |
295 | |
296 return (error_message_ == 0) && IsHotwordAllowed(); | |
241 } | 297 } |
242 | 298 |
243 bool HotwordService::IsHotwordAllowed() { | 299 bool HotwordService::IsHotwordAllowed() { |
244 std::string group = base::FieldTrialList::FindFullName( | 300 std::string group = base::FieldTrialList::FindFullName( |
245 hotword_internal::kHotwordFieldTrialName); | 301 hotword_internal::kHotwordFieldTrialName); |
246 return !group.empty() && | 302 return !group.empty() && |
247 group != hotword_internal::kHotwordFieldTrialDisabledGroupName && | 303 group != hotword_internal::kHotwordFieldTrialDisabledGroupName && |
248 DoesHotwordSupportLanguage(profile_); | 304 DoesHotwordSupportLanguage(profile_); |
249 } | 305 } |
250 | 306 |
251 bool HotwordService::IsOptedIntoAudioLogging() { | 307 bool HotwordService::IsOptedIntoAudioLogging() { |
252 // Do not opt the user in if the preference has not been set. | 308 // Do not opt the user in if the preference has not been set. |
253 return | 309 return |
254 profile_->GetPrefs()->HasPrefPath(prefs::kHotwordAudioLoggingEnabled) && | 310 profile_->GetPrefs()->HasPrefPath(prefs::kHotwordAudioLoggingEnabled) && |
255 profile_->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled); | 311 profile_->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled); |
256 } | 312 } |
257 | 313 |
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( | 314 void HotwordService::EnableHotwordExtension( |
268 ExtensionService* extension_service) { | 315 ExtensionService* extension_service) { |
269 if (extension_service) | 316 if (extension_service) |
270 extension_service->EnableExtension(extension_misc::kHotwordExtensionId); | 317 extension_service->EnableExtension(extension_misc::kHotwordExtensionId); |
271 } | 318 } |
272 | 319 |
273 void HotwordService::DisableHotwordExtension( | 320 void HotwordService::DisableHotwordExtension( |
274 ExtensionService* extension_service) { | 321 ExtensionService* extension_service) { |
275 if (extension_service) { | 322 if (extension_service) { |
276 extension_service->DisableExtension( | 323 extension_service->DisableExtension( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 | 358 |
312 DCHECK(client_ == client); | 359 DCHECK(client_ == client); |
313 | 360 |
314 client_ = NULL; | 361 client_ = NULL; |
315 HotwordPrivateEventService* event_service = | 362 HotwordPrivateEventService* event_service = |
316 BrowserContextKeyedAPIFactory<HotwordPrivateEventService>::Get(profile_); | 363 BrowserContextKeyedAPIFactory<HotwordPrivateEventService>::Get(profile_); |
317 if (event_service) | 364 if (event_service) |
318 event_service->OnHotwordSessionStopped(); | 365 event_service->OnHotwordSessionStopped(); |
319 #endif | 366 #endif |
320 } | 367 } |
OLD | NEW |