| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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/ui/webui/voicesearch_ui.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/metrics/field_trial.h" | |
| 11 #include "base/path_service.h" | |
| 12 #include "base/prefs/pref_service.h" | |
| 13 #include "base/strings/string_number_conversions.h" | |
| 14 #include "base/strings/utf_string_conversions.h" | |
| 15 #include "chrome/browser/browser_process.h" | |
| 16 #include "chrome/browser/extensions/extension_service.h" | |
| 17 #include "chrome/browser/plugins/plugin_prefs.h" | |
| 18 #include "chrome/browser/profiles/profile.h" | |
| 19 #include "chrome/browser/search/hotword_service.h" | |
| 20 #include "chrome/browser/search/hotword_service_factory.h" | |
| 21 #include "chrome/browser/ui/app_list/start_page_service.h" | |
| 22 #include "chrome/browser/ui/webui/version_handler.h" | |
| 23 #include "chrome/common/chrome_content_client.h" | |
| 24 #include "chrome/common/chrome_paths.h" | |
| 25 #include "chrome/common/chrome_version_info.h" | |
| 26 #include "chrome/common/extensions/extension_constants.h" | |
| 27 #include "chrome/common/pref_names.h" | |
| 28 #include "chrome/common/url_constants.h" | |
| 29 #include "chrome/grit/chromium_strings.h" | |
| 30 #include "chrome/grit/generated_resources.h" | |
| 31 #include "chrome/grit/google_chrome_strings.h" | |
| 32 #include "content/public/browser/plugin_service.h" | |
| 33 #include "content/public/browser/url_data_source.h" | |
| 34 #include "content/public/browser/web_ui.h" | |
| 35 #include "content/public/browser/web_ui_data_source.h" | |
| 36 #include "content/public/browser/web_ui_message_handler.h" | |
| 37 #include "content/public/common/user_agent.h" | |
| 38 #include "extensions/browser/extension_prefs.h" | |
| 39 #include "extensions/browser/extension_system.h" | |
| 40 #include "extensions/common/extension.h" | |
| 41 #include "grit/browser_resources.h" | |
| 42 #include "ui/base/l10n/l10n_util.h" | |
| 43 #include "v8/include/v8.h" | |
| 44 | |
| 45 #if defined(OS_WIN) | |
| 46 #include "base/win/windows_version.h" | |
| 47 #endif | |
| 48 | |
| 49 using base::ASCIIToUTF16; | |
| 50 using content::WebUIMessageHandler; | |
| 51 | |
| 52 namespace { | |
| 53 | |
| 54 content::WebUIDataSource* CreateVoiceSearchUiHtmlSource() { | |
| 55 content::WebUIDataSource* html_source = | |
| 56 content::WebUIDataSource::Create(chrome::kChromeUIVoiceSearchHost); | |
| 57 | |
| 58 html_source->AddLocalizedString("loadingMessage", | |
| 59 IDS_VOICESEARCH_LOADING_MESSAGE); | |
| 60 html_source->AddLocalizedString("voiceSearchLongTitle", | |
| 61 IDS_VOICESEARCH_TITLE_MESSAGE); | |
| 62 | |
| 63 html_source->SetJsonPath("strings.js"); | |
| 64 html_source->AddResourcePath("about_voicesearch.js", | |
| 65 IDR_ABOUT_VOICESEARCH_JS); | |
| 66 html_source->SetDefaultResource(IDR_ABOUT_VOICESEARCH_HTML); | |
| 67 return html_source; | |
| 68 } | |
| 69 | |
| 70 // Helper functions for collecting a list of key-value pairs that will | |
| 71 // be displayed. | |
| 72 void AddPair16(base::ListValue* list, | |
| 73 const base::string16& key, | |
| 74 const base::string16& value) { | |
| 75 scoped_ptr<base::DictionaryValue> results(new base::DictionaryValue()); | |
| 76 results->SetString("key", key); | |
| 77 results->SetString("value", value); | |
| 78 list->Append(results.release()); | |
| 79 } | |
| 80 | |
| 81 void AddPair(base::ListValue* list, | |
| 82 const base::StringPiece& key, | |
| 83 const base::StringPiece& value) { | |
| 84 AddPair16(list, UTF8ToUTF16(key), UTF8ToUTF16(value)); | |
| 85 } | |
| 86 | |
| 87 // Generate an empty data-pair which acts as a line break. | |
| 88 void AddLineBreak(base::ListValue* list) { | |
| 89 AddPair(list, "", ""); | |
| 90 } | |
| 91 | |
| 92 //////////////////////////////////////////////////////////////////////////////// | |
| 93 // | |
| 94 // VoiceSearchDomHandler | |
| 95 // | |
| 96 //////////////////////////////////////////////////////////////////////////////// | |
| 97 | |
| 98 // The handler for Javascript messages for the about:flags page. | |
| 99 class VoiceSearchDomHandler : public WebUIMessageHandler { | |
| 100 public: | |
| 101 explicit VoiceSearchDomHandler(Profile* profile) : profile_(profile) {} | |
| 102 | |
| 103 ~VoiceSearchDomHandler() override {} | |
| 104 | |
| 105 // WebUIMessageHandler implementation. | |
| 106 void RegisterMessages() override { | |
| 107 web_ui()->RegisterMessageCallback( | |
| 108 "requestVoiceSearchInfo", | |
| 109 base::Bind(&VoiceSearchDomHandler::HandleRequestVoiceSearchInfo, | |
| 110 base::Unretained(this))); | |
| 111 } | |
| 112 | |
| 113 private: | |
| 114 // Callback for the "requestVoiceSearchInfo" message. No arguments. | |
| 115 void HandleRequestVoiceSearchInfo(const base::ListValue* args) { | |
| 116 base::DictionaryValue voiceSearchInfo; | |
| 117 PopulatePageInformation(&voiceSearchInfo); | |
| 118 web_ui()->CallJavascriptFunction("returnVoiceSearchInfo", | |
| 119 voiceSearchInfo); | |
| 120 } | |
| 121 | |
| 122 // Fill in the data to be displayed on the page. | |
| 123 void PopulatePageInformation(base::DictionaryValue* voiceSearchInfo) { | |
| 124 // Store Key-Value pairs of about-information. | |
| 125 scoped_ptr<base::ListValue> list(new base::ListValue()); | |
| 126 | |
| 127 // Populate information. | |
| 128 AddOperatingSystemInfo(list.get()); | |
| 129 AddAudioInfo(list.get()); | |
| 130 AddLanguageInfo(list.get()); | |
| 131 AddHotwordInfo(list.get()); | |
| 132 | |
| 133 std::string extension_id = extension_misc::kHotwordExtensionId; | |
| 134 HotwordService* hotword_service = | |
| 135 HotwordServiceFactory::GetForProfile(profile_); | |
| 136 if (hotword_service && hotword_service->IsExperimentalHotwordingEnabled()) | |
| 137 extension_id = extension_misc::kHotwordNewExtensionId; | |
| 138 AddExtensionInfo(extension_id, "Extension", list.get()); | |
| 139 | |
| 140 AddExtensionInfo(extension_misc::kHotwordSharedModuleId, | |
| 141 "Shared Module", | |
| 142 list.get()); | |
| 143 AddAppListInfo(list.get()); | |
| 144 | |
| 145 // voiceSearchInfo will take ownership of list, and clean it up on | |
| 146 // destruction. | |
| 147 voiceSearchInfo->Set("voiceSearchInfo", list.release()); | |
| 148 } | |
| 149 | |
| 150 // Adds information regarding the system and chrome version info to list. | |
| 151 void AddOperatingSystemInfo(base::ListValue* list) { | |
| 152 // Obtain the Chrome version info. | |
| 153 chrome::VersionInfo version_info; | |
| 154 AddPair(list, | |
| 155 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME), | |
| 156 version_info.Version() + " (" + | |
| 157 chrome::VersionInfo::GetVersionStringModifier() + ")"); | |
| 158 | |
| 159 // OS version information. | |
| 160 std::string os_label = version_info.OSType(); | |
| 161 #if defined(OS_WIN) | |
| 162 base::win::OSInfo* os = base::win::OSInfo::GetInstance(); | |
| 163 switch (os->version()) { | |
| 164 case base::win::VERSION_XP: | |
| 165 os_label += " XP"; | |
| 166 break; | |
| 167 case base::win::VERSION_SERVER_2003: | |
| 168 os_label += " Server 2003 or XP Pro 64 bit"; | |
| 169 break; | |
| 170 case base::win::VERSION_VISTA: | |
| 171 os_label += " Vista or Server 2008"; | |
| 172 break; | |
| 173 case base::win::VERSION_WIN7: | |
| 174 os_label += " 7 or Server 2008 R2"; | |
| 175 break; | |
| 176 case base::win::VERSION_WIN8: | |
| 177 os_label += " 8 or Server 2012"; | |
| 178 break; | |
| 179 default: | |
| 180 os_label += " UNKNOWN"; | |
| 181 break; | |
| 182 } | |
| 183 os_label += " SP" + base::IntToString(os->service_pack().major); | |
| 184 | |
| 185 if (os->service_pack().minor > 0) | |
| 186 os_label += "." + base::IntToString(os->service_pack().minor); | |
| 187 | |
| 188 if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE) | |
| 189 os_label += " 64 bit"; | |
| 190 #endif | |
| 191 AddPair(list, l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_OS), os_label); | |
| 192 | |
| 193 AddLineBreak(list); | |
| 194 } | |
| 195 | |
| 196 // Adds information regarding audio to the list. | |
| 197 void AddAudioInfo(base::ListValue* list) { | |
| 198 // NaCl and its associated functions are not available on most mobile | |
| 199 // platforms. ENABLE_EXTENSIONS covers those platforms and hey would not | |
| 200 // allow Hotwording anyways since it is an extension. | |
| 201 std::string nacl_enabled = "not available"; | |
| 202 #if defined(ENABLE_EXTENSIONS) | |
| 203 nacl_enabled = "No"; | |
| 204 // Determine if NaCl is available. | |
| 205 base::FilePath path; | |
| 206 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) { | |
| 207 content::WebPluginInfo info; | |
| 208 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get(); | |
| 209 if (content::PluginService::GetInstance()->GetPluginInfoByPath(path, | |
| 210 &info) && | |
| 211 plugin_prefs->IsPluginEnabled(info)) { | |
| 212 nacl_enabled = "Yes"; | |
| 213 } | |
| 214 } | |
| 215 #endif | |
| 216 | |
| 217 AddPair(list, "NaCl Enabled", nacl_enabled); | |
| 218 | |
| 219 AddPair(list, | |
| 220 "Microphone", | |
| 221 HotwordServiceFactory::IsMicrophoneAvailable() ? "Yes" : "No"); | |
| 222 | |
| 223 std::string audio_capture = "No"; | |
| 224 if (profile_->GetPrefs()->GetBoolean(prefs::kAudioCaptureAllowed)) | |
| 225 audio_capture = "Yes"; | |
| 226 AddPair(list, "Audio Capture Allowed", audio_capture); | |
| 227 | |
| 228 AddLineBreak(list); | |
| 229 } | |
| 230 | |
| 231 // Adds information regarding languages to the list. | |
| 232 void AddLanguageInfo(base::ListValue* list) { | |
| 233 std::string locale = | |
| 234 #if defined(OS_CHROMEOS) | |
| 235 // On ChromeOS locale is per-profile. | |
| 236 profile_->GetPrefs()->GetString(prefs::kApplicationLocale); | |
| 237 #else | |
| 238 g_browser_process->GetApplicationLocale(); | |
| 239 #endif | |
| 240 AddPair(list, "Current Language", locale); | |
| 241 | |
| 242 AddPair(list, | |
| 243 "Hotword Previous Language", | |
| 244 profile_->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage)); | |
| 245 | |
| 246 AddLineBreak(list); | |
| 247 } | |
| 248 | |
| 249 // Adds information specific to the hotword configuration to the list. | |
| 250 void AddHotwordInfo(base::ListValue* list) { | |
| 251 std::string search_enabled = "No"; | |
| 252 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) | |
| 253 search_enabled = "Yes"; | |
| 254 AddPair(list, "Hotword Search Enabled", search_enabled); | |
| 255 | |
| 256 std::string always_on_search_enabled = "No"; | |
| 257 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled)) | |
| 258 always_on_search_enabled = "Yes"; | |
| 259 AddPair(list, "Always-on Hotword Search Enabled", always_on_search_enabled); | |
| 260 | |
| 261 std::string audio_logging_enabled = "No"; | |
| 262 HotwordService* hotword_service = | |
| 263 HotwordServiceFactory::GetForProfile(profile_); | |
| 264 if (hotword_service && hotword_service->IsOptedIntoAudioLogging()) | |
| 265 audio_logging_enabled = "Yes"; | |
| 266 AddPair(list, "Hotword Audio Logging Enabled", audio_logging_enabled); | |
| 267 | |
| 268 std::string group = base::FieldTrialList::FindFullName( | |
| 269 hotword_internal::kHotwordFieldTrialName); | |
| 270 AddPair(list, "Field trial", group); | |
| 271 | |
| 272 std::string new_hotwording_enabled = "No"; | |
| 273 if (hotword_service && hotword_service->IsExperimentalHotwordingEnabled()) | |
| 274 new_hotwording_enabled = "Yes"; | |
| 275 AddPair(list, "New Hotwording Enabled", new_hotwording_enabled); | |
| 276 | |
| 277 AddLineBreak(list); | |
| 278 } | |
| 279 | |
| 280 // Adds information specific to an extension to the list. | |
| 281 void AddExtensionInfo(const std::string& extension_id, | |
| 282 const std::string& name_prefix, | |
| 283 base::ListValue* list) { | |
| 284 DCHECK(!name_prefix.empty()); | |
| 285 std::string version("undefined"); | |
| 286 std::string id("undefined"); | |
| 287 base::FilePath path; | |
| 288 | |
| 289 extensions::ExtensionSystem* extension_system = | |
| 290 extensions::ExtensionSystem::Get(profile_); | |
| 291 if (extension_system) { | |
| 292 ExtensionService* extension_service = | |
| 293 extension_system->extension_service(); | |
| 294 const extensions::Extension* extension = | |
| 295 extension_service->GetExtensionById(extension_id, true); | |
| 296 if (extension) { | |
| 297 id = extension->id(); | |
| 298 version = extension->VersionString(); | |
| 299 path = extension->path(); | |
| 300 } | |
| 301 } | |
| 302 AddPair(list, name_prefix + " Id", id); | |
| 303 AddPair(list, name_prefix + " Version", version); | |
| 304 AddPair16(list, | |
| 305 ASCIIToUTF16(name_prefix + " Path"), | |
| 306 path.empty() ? | |
| 307 ASCIIToUTF16("undefined") : path.LossyDisplayName()); | |
| 308 | |
| 309 extensions::ExtensionPrefs* extension_prefs = | |
| 310 extensions::ExtensionPrefs::Get(profile_); | |
| 311 int pref_state = -1; | |
| 312 extension_prefs->ReadPrefAsInteger(extension_id, "state", &pref_state); | |
| 313 std::string state; | |
| 314 switch (pref_state) { | |
| 315 case extensions::Extension::DISABLED: | |
| 316 state = "DISABLED"; | |
| 317 break; | |
| 318 case extensions::Extension::ENABLED: | |
| 319 state = "ENABLED"; | |
| 320 break; | |
| 321 case extensions::Extension::EXTERNAL_EXTENSION_UNINSTALLED: | |
| 322 state = "EXTERNAL_EXTENSION_UNINSTALLED"; | |
| 323 break; | |
| 324 default: | |
| 325 state = "undefined"; | |
| 326 } | |
| 327 | |
| 328 AddPair(list, name_prefix + " State", state); | |
| 329 | |
| 330 AddLineBreak(list); | |
| 331 } | |
| 332 | |
| 333 // Adds information specific to voice search in the app launcher to the list. | |
| 334 void AddAppListInfo(base::ListValue* list) { | |
| 335 #if defined (ENABLE_APP_LIST) | |
| 336 std::string state = "No Start Page Service"; | |
| 337 app_list::StartPageService* start_page_service = | |
| 338 app_list::StartPageService::Get(profile_); | |
| 339 if (start_page_service) { | |
| 340 app_list::SpeechRecognitionState speech_state = | |
| 341 start_page_service->state(); | |
| 342 switch (speech_state) { | |
| 343 case app_list::SPEECH_RECOGNITION_OFF: | |
| 344 state = "SPEECH_RECOGNITION_OFF"; | |
| 345 break; | |
| 346 case app_list::SPEECH_RECOGNITION_READY: | |
| 347 state = "SPEECH_RECOGNITION_READY"; | |
| 348 break; | |
| 349 case app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING: | |
| 350 state = "SPEECH_RECOGNITION_HOTWORD_LISTENING"; | |
| 351 break; | |
| 352 case app_list::SPEECH_RECOGNITION_RECOGNIZING: | |
| 353 state = "SPEECH_RECOGNITION_RECOGNIZING"; | |
| 354 break; | |
| 355 case app_list::SPEECH_RECOGNITION_IN_SPEECH: | |
| 356 state = "SPEECH_RECOGNITION_IN_SPEECH"; | |
| 357 break; | |
| 358 case app_list::SPEECH_RECOGNITION_STOPPING: | |
| 359 state = "SPEECH_RECOGNITION_STOPPING"; | |
| 360 break; | |
| 361 case app_list::SPEECH_RECOGNITION_NETWORK_ERROR: | |
| 362 state = "SPEECH_RECOGNITION_NETWORK_ERROR"; | |
| 363 break; | |
| 364 default: | |
| 365 state = "undefined"; | |
| 366 } | |
| 367 } | |
| 368 AddPair(list, "Start Page State", state); | |
| 369 #endif | |
| 370 } | |
| 371 | |
| 372 Profile* profile_; | |
| 373 | |
| 374 DISALLOW_COPY_AND_ASSIGN(VoiceSearchDomHandler); | |
| 375 }; | |
| 376 | |
| 377 } // namespace | |
| 378 | |
| 379 /////////////////////////////////////////////////////////////////////////////// | |
| 380 // | |
| 381 // VoiceSearchUI | |
| 382 // | |
| 383 /////////////////////////////////////////////////////////////////////////////// | |
| 384 | |
| 385 VoiceSearchUI::VoiceSearchUI(content::WebUI* web_ui) | |
| 386 : content::WebUIController(web_ui) { | |
| 387 Profile* profile = Profile::FromWebUI(web_ui); | |
| 388 web_ui->AddMessageHandler(new VoiceSearchDomHandler(profile)); | |
| 389 | |
| 390 // Set up the about:voicesearch source. | |
| 391 content::WebUIDataSource::Add(profile, CreateVoiceSearchUiHtmlSource()); | |
| 392 } | |
| 393 | |
| 394 VoiceSearchUI::~VoiceSearchUI() {} | |
| OLD | NEW |