Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / voice_search_ui.cc
blob9f45d062f4d0575b25445bba90bc471e1406f4f0
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/voice_search_ui.h"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/files/file_enumerator.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/path_service.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/plugins/plugin_prefs.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/search/hotword_service.h"
22 #include "chrome/browser/search/hotword_service_factory.h"
23 #include "chrome/browser/ui/app_list/start_page_service.h"
24 #include "chrome/browser/ui/webui/version_handler.h"
25 #include "chrome/common/chrome_content_client.h"
26 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_version_info.h"
28 #include "chrome/common/extensions/extension_constants.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/grit/chromium_strings.h"
32 #include "chrome/grit/generated_resources.h"
33 #include "content/public/browser/browser_thread.h"
34 #include "content/public/browser/plugin_service.h"
35 #include "content/public/browser/url_data_source.h"
36 #include "content/public/browser/web_ui.h"
37 #include "content/public/browser/web_ui_data_source.h"
38 #include "content/public/browser/web_ui_message_handler.h"
39 #include "content/public/common/user_agent.h"
40 #include "extensions/browser/extension_prefs.h"
41 #include "extensions/browser/extension_system.h"
42 #include "extensions/common/extension.h"
43 #include "grit/browser_resources.h"
44 #include "ui/base/l10n/l10n_util.h"
45 #include "v8/include/v8.h"
47 #if defined(OS_WIN)
48 #include "base/win/windows_version.h"
49 #endif
51 using base::ASCIIToUTF16;
52 using content::WebUIMessageHandler;
54 namespace {
56 content::WebUIDataSource* CreateVoiceSearchUiHtmlSource() {
57 content::WebUIDataSource* html_source =
58 content::WebUIDataSource::Create(chrome::kChromeUIVoiceSearchHost);
60 html_source->AddLocalizedString("loadingMessage",
61 IDS_VOICESEARCH_LOADING_MESSAGE);
62 html_source->AddLocalizedString("voiceSearchLongTitle",
63 IDS_VOICESEARCH_TITLE_MESSAGE);
65 html_source->SetJsonPath("strings.js");
66 html_source->AddResourcePath("about_voicesearch.js",
67 IDR_ABOUT_VOICESEARCH_JS);
68 html_source->SetDefaultResource(IDR_ABOUT_VOICESEARCH_HTML);
69 return html_source;
72 // Helper functions for collecting a list of key-value pairs that will
73 // be displayed.
74 void AddPair16(base::ListValue* list,
75 const base::string16& key,
76 const base::string16& value) {
77 scoped_ptr<base::DictionaryValue> results(new base::DictionaryValue());
78 results->SetString("key", key);
79 results->SetString("value", value);
80 list->Append(results.release());
83 void AddPair(base::ListValue* list,
84 const base::StringPiece& key,
85 const base::StringPiece& value) {
86 AddPair16(list, UTF8ToUTF16(key), UTF8ToUTF16(value));
89 // Generate an empty data-pair which acts as a line break.
90 void AddLineBreak(base::ListValue* list) {
91 AddPair(list, "", "");
94 void AddSharedModulePlatformsOnFileThread(base::ListValue* list,
95 const base::FilePath& path,
96 base::Closure callback) {
97 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
99 if (!path.empty()) {
100 // Display available platforms for shared module.
101 base::FilePath platforms_path = path.AppendASCII("_platform_specific");
102 base::FileEnumerator enumerator(
103 platforms_path, false, base::FileEnumerator::DIRECTORIES);
104 base::string16 files;
105 for (base::FilePath name = enumerator.Next();
106 !name.empty();
107 name = enumerator.Next()) {
108 files += name.BaseName().LossyDisplayName() + ASCIIToUTF16(" ");
110 AddPair16(list,
111 ASCIIToUTF16("Shared Module Platforms"),
112 files.empty() ? ASCIIToUTF16("undefined") : files);
113 AddLineBreak(list);
116 content::BrowserThread::PostTask(content::BrowserThread::UI,
117 FROM_HERE,
118 callback);
121 ////////////////////////////////////////////////////////////////////////////////
123 // VoiceSearchDomHandler
125 ////////////////////////////////////////////////////////////////////////////////
127 // The handler for Javascript messages for the about:flags page.
128 class VoiceSearchDomHandler : public WebUIMessageHandler {
129 public:
130 explicit VoiceSearchDomHandler(Profile* profile)
131 : profile_(profile),
132 weak_factory_(this) {}
134 ~VoiceSearchDomHandler() override {}
136 // WebUIMessageHandler implementation.
137 void RegisterMessages() override {
138 web_ui()->RegisterMessageCallback(
139 "requestVoiceSearchInfo",
140 base::Bind(&VoiceSearchDomHandler::HandleRequestVoiceSearchInfo,
141 base::Unretained(this)));
144 private:
145 // Callback for the "requestVoiceSearchInfo" message. No arguments.
146 void HandleRequestVoiceSearchInfo(const base::ListValue* args) {
147 PopulatePageInformation();
150 void ReturnVoiceSearchInfo(scoped_ptr<base::ListValue> info) {
151 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
152 DCHECK(info);
153 base::DictionaryValue voiceSearchInfo;
154 voiceSearchInfo.Set("voiceSearchInfo", info.release());
155 web_ui()->CallJavascriptFunction("returnVoiceSearchInfo", voiceSearchInfo);
158 // Fill in the data to be displayed on the page.
159 void PopulatePageInformation() {
160 // Store Key-Value pairs of about-information.
161 scoped_ptr<base::ListValue> list(new base::ListValue());
163 // Populate information.
164 AddOperatingSystemInfo(list.get());
165 AddAudioInfo(list.get());
166 AddLanguageInfo(list.get());
167 AddHotwordInfo(list.get());
168 AddAppListInfo(list.get());
170 AddExtensionInfo(extension_misc::kHotwordNewExtensionId,
171 "Extension",
172 list.get());
174 AddExtensionInfo(extension_misc::kHotwordSharedModuleId,
175 "Shared Module",
176 list.get());
178 base::FilePath path;
179 extensions::ExtensionSystem* extension_system =
180 extensions::ExtensionSystem::Get(profile_);
181 if (extension_system) {
182 ExtensionService* extension_service =
183 extension_system->extension_service();
184 const extensions::Extension* extension =
185 extension_service->GetExtensionById(
186 extension_misc::kHotwordSharedModuleId, true);
187 if (extension)
188 path = extension->path();
190 base::ListValue* raw_list = list.get();
191 content::BrowserThread::PostTask(
192 content::BrowserThread::FILE,
193 FROM_HERE,
194 base::Bind(
195 &AddSharedModulePlatformsOnFileThread,
196 raw_list,
197 path,
198 base::Bind(&VoiceSearchDomHandler::ReturnVoiceSearchInfo,
199 weak_factory_.GetWeakPtr(),
200 base::Passed(list.Pass()))));
203 // Adds information regarding the system and chrome version info to list.
204 void AddOperatingSystemInfo(base::ListValue* list) {
205 // Obtain the Chrome version info.
206 chrome::VersionInfo version_info;
207 AddPair(list,
208 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME),
209 version_info.Version() + " (" +
210 chrome::VersionInfo::GetVersionStringModifier() + ")");
212 // OS version information.
213 std::string os_label = version_info.OSType();
214 #if defined(OS_WIN)
215 base::win::OSInfo* os = base::win::OSInfo::GetInstance();
216 switch (os->version()) {
217 case base::win::VERSION_XP:
218 os_label += " XP";
219 break;
220 case base::win::VERSION_SERVER_2003:
221 os_label += " Server 2003 or XP Pro 64 bit";
222 break;
223 case base::win::VERSION_VISTA:
224 os_label += " Vista or Server 2008";
225 break;
226 case base::win::VERSION_WIN7:
227 os_label += " 7 or Server 2008 R2";
228 break;
229 case base::win::VERSION_WIN8:
230 os_label += " 8 or Server 2012";
231 break;
232 default:
233 os_label += " UNKNOWN";
234 break;
236 os_label += " SP" + base::IntToString(os->service_pack().major);
238 if (os->service_pack().minor > 0)
239 os_label += "." + base::IntToString(os->service_pack().minor);
241 if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE)
242 os_label += " 64 bit";
243 #endif
244 AddPair(list, l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_OS), os_label);
246 AddLineBreak(list);
249 // Adds information regarding audio to the list.
250 void AddAudioInfo(base::ListValue* list) {
251 // NaCl and its associated functions are not available on most mobile
252 // platforms. ENABLE_EXTENSIONS covers those platforms and hey would not
253 // allow Hotwording anyways since it is an extension.
254 std::string nacl_enabled = "not available";
255 #if defined(ENABLE_EXTENSIONS)
256 nacl_enabled = "No";
257 // Determine if NaCl is available.
258 base::FilePath path;
259 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) {
260 content::WebPluginInfo info;
261 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get();
262 if (content::PluginService::GetInstance()->GetPluginInfoByPath(path,
263 &info) &&
264 plugin_prefs->IsPluginEnabled(info)) {
265 nacl_enabled = "Yes";
268 #endif
270 AddPair(list, "NaCl Enabled", nacl_enabled);
272 HotwordService* hotword_service =
273 HotwordServiceFactory::GetForProfile(profile_);
274 AddPair(list, "Microphone",
275 hotword_service && hotword_service->microphone_available() ? "Yes"
276 : "No");
278 std::string audio_capture = "No";
279 if (profile_->GetPrefs()->GetBoolean(prefs::kAudioCaptureAllowed))
280 audio_capture = "Yes";
281 AddPair(list, "Audio Capture Allowed", audio_capture);
283 AddLineBreak(list);
286 // Adds information regarding languages to the list.
287 void AddLanguageInfo(base::ListValue* list) {
288 std::string locale =
289 #if defined(OS_CHROMEOS)
290 // On ChromeOS locale is per-profile.
291 profile_->GetPrefs()->GetString(prefs::kApplicationLocale);
292 #else
293 g_browser_process->GetApplicationLocale();
294 #endif
295 AddPair(list, "Current Language", locale);
297 AddPair(list,
298 "Hotword Previous Language",
299 profile_->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage));
301 AddLineBreak(list);
304 // Adds information specific to the hotword configuration to the list.
305 void AddHotwordInfo(base::ListValue* list) {
306 std::string search_enabled = "No";
307 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled))
308 search_enabled = "Yes";
309 AddPair(list, "Hotword Search Enabled", search_enabled);
311 std::string always_on_search_enabled = "No";
312 if (profile_->GetPrefs()->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled))
313 always_on_search_enabled = "Yes";
314 AddPair(list, "Always-on Hotword Search Enabled", always_on_search_enabled);
316 std::string audio_logging_enabled = "No";
317 HotwordService* hotword_service =
318 HotwordServiceFactory::GetForProfile(profile_);
319 if (hotword_service && hotword_service->IsOptedIntoAudioLogging())
320 audio_logging_enabled = "Yes";
321 AddPair(list, "Hotword Audio Logging Enabled", audio_logging_enabled);
323 AddLineBreak(list);
326 // Adds information specific to an extension to the list.
327 void AddExtensionInfo(const std::string& extension_id,
328 const std::string& name_prefix,
329 base::ListValue* list) {
330 DCHECK(!name_prefix.empty());
331 std::string version("undefined");
332 std::string id("undefined");
333 base::FilePath path;
335 extensions::ExtensionSystem* extension_system =
336 extensions::ExtensionSystem::Get(profile_);
337 if (extension_system) {
338 ExtensionService* extension_service =
339 extension_system->extension_service();
340 const extensions::Extension* extension =
341 extension_service->GetExtensionById(extension_id, true);
342 if (extension) {
343 id = extension->id();
344 version = extension->VersionString();
345 path = extension->path();
348 AddPair(list, name_prefix + " Id", id);
349 AddPair(list, name_prefix + " Version", version);
350 AddPair16(list,
351 ASCIIToUTF16(name_prefix + " Path"),
352 path.empty() ?
353 ASCIIToUTF16("undefined") : path.LossyDisplayName());
355 extensions::ExtensionPrefs* extension_prefs =
356 extensions::ExtensionPrefs::Get(profile_);
357 int pref_state = -1;
358 extension_prefs->ReadPrefAsInteger(extension_id, "state", &pref_state);
359 std::string state;
360 switch (pref_state) {
361 case extensions::Extension::DISABLED:
362 state = "DISABLED";
363 break;
364 case extensions::Extension::ENABLED:
365 state = "ENABLED";
366 break;
367 case extensions::Extension::EXTERNAL_EXTENSION_UNINSTALLED:
368 state = "EXTERNAL_EXTENSION_UNINSTALLED";
369 break;
370 default:
371 state = "undefined";
374 AddPair(list, name_prefix + " State", state);
376 AddLineBreak(list);
379 // Adds information specific to voice search in the app launcher to the list.
380 void AddAppListInfo(base::ListValue* list) {
381 #if defined (ENABLE_APP_LIST)
382 std::string state = "No Start Page Service";
383 app_list::StartPageService* start_page_service =
384 app_list::StartPageService::Get(profile_);
385 if (start_page_service) {
386 app_list::SpeechRecognitionState speech_state =
387 start_page_service->state();
388 switch (speech_state) {
389 case app_list::SPEECH_RECOGNITION_OFF:
390 state = "SPEECH_RECOGNITION_OFF";
391 break;
392 case app_list::SPEECH_RECOGNITION_READY:
393 state = "SPEECH_RECOGNITION_READY";
394 break;
395 case app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING:
396 state = "SPEECH_RECOGNITION_HOTWORD_LISTENING";
397 break;
398 case app_list::SPEECH_RECOGNITION_RECOGNIZING:
399 state = "SPEECH_RECOGNITION_RECOGNIZING";
400 break;
401 case app_list::SPEECH_RECOGNITION_IN_SPEECH:
402 state = "SPEECH_RECOGNITION_IN_SPEECH";
403 break;
404 case app_list::SPEECH_RECOGNITION_STOPPING:
405 state = "SPEECH_RECOGNITION_STOPPING";
406 break;
407 case app_list::SPEECH_RECOGNITION_NETWORK_ERROR:
408 state = "SPEECH_RECOGNITION_NETWORK_ERROR";
409 break;
410 default:
411 state = "undefined";
414 AddPair(list, "Start Page State", state);
415 AddLineBreak(list);
416 #endif
419 Profile* profile_;
420 base::WeakPtrFactory<VoiceSearchDomHandler> weak_factory_;
422 DISALLOW_COPY_AND_ASSIGN(VoiceSearchDomHandler);
425 } // namespace
427 ///////////////////////////////////////////////////////////////////////////////
429 // VoiceSearchUI
431 ///////////////////////////////////////////////////////////////////////////////
433 VoiceSearchUI::VoiceSearchUI(content::WebUI* web_ui)
434 : content::WebUIController(web_ui) {
435 Profile* profile = Profile::FromWebUI(web_ui);
436 web_ui->AddMessageHandler(new VoiceSearchDomHandler(profile));
438 // Set up the about:voicesearch source.
439 content::WebUIDataSource::Add(profile, CreateVoiceSearchUiHtmlSource());
442 VoiceSearchUI::~VoiceSearchUI() {}