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.
5 #include "chrome/browser/ui/webui/voicesearch_ui.h"
7 #include "base/command_line.h"
8 #include "base/metrics/field_trial.h"
9 #include "base/path_service.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/plugins/plugin_prefs.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/search/hotword_service.h"
18 #include "chrome/browser/search/hotword_service_factory.h"
19 #include "chrome/browser/ui/app_list/start_page_service.h"
20 #include "chrome/browser/ui/webui/version_handler.h"
21 #include "chrome/common/chrome_content_client.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_version_info.h"
24 #include "chrome/common/extensions/extension_constants.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/grit/chromium_strings.h"
28 #include "chrome/grit/generated_resources.h"
29 #include "chrome/grit/google_chrome_strings.h"
30 #include "content/public/browser/plugin_service.h"
31 #include "content/public/browser/url_data_source.h"
32 #include "content/public/browser/web_ui.h"
33 #include "content/public/browser/web_ui_data_source.h"
34 #include "content/public/browser/web_ui_message_handler.h"
35 #include "content/public/common/user_agent.h"
36 #include "extensions/browser/extension_prefs.h"
37 #include "extensions/browser/extension_system.h"
38 #include "extensions/common/extension.h"
39 #include "grit/browser_resources.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "v8/include/v8.h"
44 #include "base/win/windows_version.h"
47 using base::ASCIIToUTF16;
48 using content::WebUIMessageHandler;
52 content::WebUIDataSource* CreateVoiceSearchUiHtmlSource() {
53 content::WebUIDataSource* html_source =
54 content::WebUIDataSource::Create(chrome::kChromeUIVoiceSearchHost);
56 html_source->AddLocalizedString("loadingMessage",
57 IDS_VOICESEARCH_LOADING_MESSAGE);
58 html_source->AddLocalizedString("voiceSearchLongTitle",
59 IDS_VOICESEARCH_TITLE_MESSAGE);
61 html_source->SetUseJsonJSFormatV2();
62 html_source->SetJsonPath("strings.js");
63 html_source->AddResourcePath("about_voicesearch.js",
64 IDR_ABOUT_VOICESEARCH_JS);
65 html_source->SetDefaultResource(IDR_ABOUT_VOICESEARCH_HTML);
69 // Helper functions for collecting a list of key-value pairs that will
71 void AddPair(base::ListValue* list,
72 const base::string16& key,
73 const base::string16& value) {
74 scoped_ptr<base::DictionaryValue> results(new base::DictionaryValue());
75 results->SetString("key", key);
76 results->SetString("value", value);
77 list->Append(results.release());
80 // Generate an empty data-pair which acts as a line break.
81 void AddLineBreak(base::ListValue* list) {
82 AddPair(list, ASCIIToUTF16(base::StringPiece()),
83 ASCIIToUTF16(base::StringPiece()));
86 ////////////////////////////////////////////////////////////////////////////////
88 // VoiceSearchDomHandler
90 ////////////////////////////////////////////////////////////////////////////////
92 // The handler for Javascript messages for the about:flags page.
93 class VoiceSearchDomHandler : public WebUIMessageHandler {
95 explicit VoiceSearchDomHandler(Profile* profile) : profile_(profile) {}
97 virtual ~VoiceSearchDomHandler() {}
99 // WebUIMessageHandler implementation.
100 virtual void RegisterMessages() OVERRIDE {
101 web_ui()->RegisterMessageCallback(
102 "requestVoiceSearchInfo",
103 base::Bind(&VoiceSearchDomHandler::HandleRequestVoiceSearchInfo,
104 base::Unretained(this)));
108 // Callback for the "requestVoiceSearchInfo" message. No arguments.
109 void HandleRequestVoiceSearchInfo(const base::ListValue* args) {
110 base::DictionaryValue voiceSearchInfo;
111 PopulatePageInformation(&voiceSearchInfo);
112 web_ui()->CallJavascriptFunction("returnVoiceSearchInfo",
116 // Fill in the data to be displayed on the page.
117 void PopulatePageInformation(base::DictionaryValue* voiceSearchInfo) {
118 // Store Key-Value pairs of about-information.
119 scoped_ptr<base::ListValue> list(new base::ListValue());
121 // Populate information.
122 AddOperatingSystemInfo(list.get());
123 AddAudioInfo(list.get());
124 AddLanguageInfo(list.get());
125 AddHotwordInfo(list.get());
126 AddHotwordExtensionInfo(list.get());
127 AddAppListInfo(list.get());
129 // voiceSearchInfo will take ownership of list, and clean it up on
131 voiceSearchInfo->Set("voiceSearchInfo", list.release());
134 // Adds information regarding the system and chrome version info to list.
135 void AddOperatingSystemInfo(base::ListValue* list) {
136 // Obtain the Chrome version info.
137 chrome::VersionInfo version_info;
139 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
141 version_info.Version() + " (" +
142 chrome::VersionInfo::GetVersionStringModifier() + ")"));
144 // OS version information.
145 std::string os_label = version_info.OSType();
147 base::win::OSInfo* os = base::win::OSInfo::GetInstance();
148 switch (os->version()) {
149 case base::win::VERSION_XP:
152 case base::win::VERSION_SERVER_2003:
153 os_label += " Server 2003 or XP Pro 64 bit";
155 case base::win::VERSION_VISTA:
156 os_label += " Vista or Server 2008";
158 case base::win::VERSION_WIN7:
159 os_label += " 7 or Server 2008 R2";
161 case base::win::VERSION_WIN8:
162 os_label += " 8 or Server 2012";
165 os_label += " UNKNOWN";
168 os_label += " SP" + base::IntToString(os->service_pack().major);
170 if (os->service_pack().minor > 0)
171 os_label += "." + base::IntToString(os->service_pack().minor);
173 if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE)
174 os_label += " 64 bit";
177 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_OS),
178 ASCIIToUTF16(os_label));
183 // Adds information regarding audio to the list.
184 void AddAudioInfo(base::ListValue* list) {
185 // NaCl and its associated functions are not available on most mobile
186 // platforms. ENABLE_EXTENSIONS covers those platforms and hey would not
187 // allow Hotwording anyways since it is an extension.
188 std::string nacl_enabled = "not available";
189 #if defined(ENABLE_EXTENSIONS)
191 // Determine if NaCl is available.
193 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) {
194 content::WebPluginInfo info;
195 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get();
196 if (content::PluginService::GetInstance()->GetPluginInfoByPath(path,
198 plugin_prefs->IsPluginEnabled(info)) {
199 nacl_enabled = "Yes";
204 AddPair(list, ASCIIToUTF16("NaCl Enabled"), ASCIIToUTF16(nacl_enabled));
206 AddPair(list, ASCIIToUTF16("Microphone"),
208 HotwordServiceFactory::IsMicrophoneAvailable() ? "Yes" : "No"));
210 std::string audio_capture = "No";
211 if (profile_->GetPrefs()->GetBoolean(prefs::kAudioCaptureAllowed))
212 audio_capture = "Yes";
213 AddPair(list, ASCIIToUTF16("Audio Capture Allowed"),
214 ASCIIToUTF16(audio_capture));
219 // Adds information regarding languages to the list.
220 void AddLanguageInfo(base::ListValue* list) {
222 #if defined(OS_CHROMEOS)
223 // On ChromeOS locale is per-profile.
224 profile_->GetPrefs()->GetString(prefs::kApplicationLocale);
226 g_browser_process->GetApplicationLocale();
228 AddPair(list, ASCIIToUTF16("Current Language"), ASCIIToUTF16(locale));
230 AddPair(list, ASCIIToUTF16("Hotword Previous Language"),
231 ASCIIToUTF16(profile_->GetPrefs()->GetString(
232 prefs::kHotwordPreviousLanguage)));
237 // Adds information specific to the hotword configuration to the list.
238 void AddHotwordInfo(base::ListValue* list) {
239 std::string search_enabled = "No";
240 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled))
241 search_enabled = "Yes";
242 AddPair(list, ASCIIToUTF16("Hotword Search Enabled"),
243 ASCIIToUTF16(search_enabled));
245 std::string audio_logging_enabled = "No";
246 HotwordService* hotword_service =
247 HotwordServiceFactory::GetForProfile(profile_);
248 if (hotword_service && hotword_service->IsOptedIntoAudioLogging())
249 audio_logging_enabled = "Yes";
250 AddPair(list, ASCIIToUTF16("Hotword Audio Logging Enabled"),
251 ASCIIToUTF16(audio_logging_enabled));
253 std::string group = base::FieldTrialList::FindFullName(
254 hotword_internal::kHotwordFieldTrialName);
255 AddPair(list, ASCIIToUTF16("Field trial"), ASCIIToUTF16(group));
260 // Adds information specific to the hotword extension to the list.
261 void AddHotwordExtensionInfo(base::ListValue* list) {
262 std::string version("undefined");
263 std::string id("undefined");
266 extensions::ExtensionSystem* extension_system =
267 extensions::ExtensionSystem::Get(profile_);
268 if (extension_system) {
269 ExtensionService* extension_service =
270 extension_system->extension_service();
271 const extensions::Extension* extension =
272 extension_service->GetExtensionById(
273 extension_misc::kHotwordExtensionId, true);
275 id = extension->id();
276 version = extension->VersionString();
277 path = extension->path();
280 AddPair(list, ASCIIToUTF16("Extension Id"),
282 AddPair(list, ASCIIToUTF16("Extension Version"),
283 ASCIIToUTF16(version));
284 AddPair(list, ASCIIToUTF16("Extension Path"),
285 path.empty() ? ASCIIToUTF16("undefined") : path.LossyDisplayName());
287 extensions::ExtensionPrefs* extension_prefs =
288 extensions::ExtensionPrefs::Get(profile_);
290 extension_prefs->ReadPrefAsInteger(extension_misc::kHotwordExtensionId,
291 "state", &pref_state);
293 switch (pref_state) {
294 case extensions::Extension::DISABLED:
297 case extensions::Extension::ENABLED:
300 case extensions::Extension::EXTERNAL_EXTENSION_UNINSTALLED:
301 state = "EXTERNAL_EXTENSION_UNINSTALLED";
307 AddPair(list, ASCIIToUTF16("Extension State"), ASCIIToUTF16(state));
312 // Adds information specific to voice search in the app launcher to the list.
313 void AddAppListInfo(base::ListValue* list) {
314 #if defined (ENABLE_APP_LIST)
315 std::string state = "No Start Page Service";
316 app_list::StartPageService* start_page_service =
317 app_list::StartPageService::Get(profile_);
318 if (start_page_service) {
319 app_list::SpeechRecognitionState speech_state =
320 start_page_service->state();
321 switch (speech_state) {
322 case app_list::SPEECH_RECOGNITION_OFF:
323 state = "SPEECH_RECOGNITION_OFF";
325 case app_list::SPEECH_RECOGNITION_READY:
326 state = "SPEECH_RECOGNITION_READY";
328 case app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING:
329 state = "SPEECH_RECOGNITION_HOTWORD_LISTENING";
331 case app_list::SPEECH_RECOGNITION_RECOGNIZING:
332 state = "SPEECH_RECOGNITION_RECOGNIZING";
334 case app_list::SPEECH_RECOGNITION_IN_SPEECH:
335 state = "SPEECH_RECOGNITION_IN_SPEECH";
337 case app_list::SPEECH_RECOGNITION_STOPPING:
338 state = "SPEECH_RECOGNITION_STOPPING";
340 case app_list::SPEECH_RECOGNITION_NETWORK_ERROR:
341 state = "SPEECH_RECOGNITION_NETWORK_ERROR";
347 AddPair(list, ASCIIToUTF16("Start Page State"), ASCIIToUTF16(state));
353 DISALLOW_COPY_AND_ASSIGN(VoiceSearchDomHandler);
358 ///////////////////////////////////////////////////////////////////////////////
362 ///////////////////////////////////////////////////////////////////////////////
364 VoiceSearchUI::VoiceSearchUI(content::WebUI* web_ui)
365 : content::WebUIController(web_ui) {
366 Profile* profile = Profile::FromWebUI(web_ui);
367 web_ui->AddMessageHandler(new VoiceSearchDomHandler(profile));
369 // Set up the about:voicesearch source.
370 content::WebUIDataSource::Add(profile, CreateVoiceSearchUiHtmlSource());
373 VoiceSearchUI::~VoiceSearchUI() {}