Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / voicesearch_ui.cc
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 "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"
42
43 #if defined(OS_WIN)
44 #include "base/win/windows_version.h"
45 #endif
46
47 using base::ASCIIToUTF16;
48 using content::WebUIMessageHandler;
49
50 namespace {
51
52 content::WebUIDataSource* CreateVoiceSearchUiHtmlSource() {
53   content::WebUIDataSource* html_source =
54       content::WebUIDataSource::Create(chrome::kChromeUIVoiceSearchHost);
55
56   html_source->AddLocalizedString("loadingMessage",
57                                   IDS_VOICESEARCH_LOADING_MESSAGE);
58   html_source->AddLocalizedString("voiceSearchLongTitle",
59                                   IDS_VOICESEARCH_TITLE_MESSAGE);
60
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);
66   return html_source;
67 }
68
69 // Helper functions for collecting a list of key-value pairs that will
70 // be displayed.
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());
78 }
79
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()));
84 }
85
86 ////////////////////////////////////////////////////////////////////////////////
87 //
88 // VoiceSearchDomHandler
89 //
90 ////////////////////////////////////////////////////////////////////////////////
91
92 // The handler for Javascript messages for the about:flags page.
93 class VoiceSearchDomHandler : public WebUIMessageHandler {
94  public:
95   explicit VoiceSearchDomHandler(Profile* profile) : profile_(profile) {}
96
97   virtual ~VoiceSearchDomHandler() {}
98
99   // WebUIMessageHandler implementation.
100   virtual void RegisterMessages() OVERRIDE {
101     web_ui()->RegisterMessageCallback(
102         "requestVoiceSearchInfo",
103         base::Bind(&VoiceSearchDomHandler::HandleRequestVoiceSearchInfo,
104                    base::Unretained(this)));
105   }
106
107  private:
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",
113                                      voiceSearchInfo);
114   }
115
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());
120
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());
128
129     // voiceSearchInfo will take ownership of list, and clean it up on
130     // destruction.
131     voiceSearchInfo->Set("voiceSearchInfo", list.release());
132   }
133
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;
138     AddPair(list,
139             l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
140             ASCIIToUTF16(
141                 version_info.Version() + " (" +
142                 chrome::VersionInfo::GetVersionStringModifier() + ")"));
143
144     // OS version information.
145     std::string os_label = version_info.OSType();
146 #if defined(OS_WIN)
147     base::win::OSInfo* os = base::win::OSInfo::GetInstance();
148     switch (os->version()) {
149       case base::win::VERSION_XP:
150         os_label += " XP";
151         break;
152       case base::win::VERSION_SERVER_2003:
153         os_label += " Server 2003 or XP Pro 64 bit";
154         break;
155       case base::win::VERSION_VISTA:
156         os_label += " Vista or Server 2008";
157         break;
158       case base::win::VERSION_WIN7:
159         os_label += " 7 or Server 2008 R2";
160         break;
161       case base::win::VERSION_WIN8:
162         os_label += " 8 or Server 2012";
163         break;
164       default:
165         os_label += " UNKNOWN";
166         break;
167     }
168     os_label += " SP" + base::IntToString(os->service_pack().major);
169
170     if (os->service_pack().minor > 0)
171       os_label += "." + base::IntToString(os->service_pack().minor);
172
173     if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE)
174       os_label += " 64 bit";
175 #endif
176     AddPair(list,
177             l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_OS),
178             ASCIIToUTF16(os_label));
179
180     AddLineBreak(list);
181   }
182
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)
190     nacl_enabled = "No";
191     // Determine if NaCl is available.
192     base::FilePath path;
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,
197                                                                      &info) &&
198           plugin_prefs->IsPluginEnabled(info)) {
199         nacl_enabled = "Yes";
200       }
201     }
202 #endif
203
204     AddPair(list, ASCIIToUTF16("NaCl Enabled"), ASCIIToUTF16(nacl_enabled));
205
206     AddPair(list, ASCIIToUTF16("Microphone"),
207             ASCIIToUTF16(
208                 HotwordServiceFactory::IsMicrophoneAvailable() ? "Yes" : "No"));
209
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));
215
216     AddLineBreak(list);
217   }
218
219   // Adds information regarding languages to the list.
220   void AddLanguageInfo(base::ListValue* list) {
221     std::string locale =
222 #if defined(OS_CHROMEOS)
223         // On ChromeOS locale is per-profile.
224         profile_->GetPrefs()->GetString(prefs::kApplicationLocale);
225 #else
226         g_browser_process->GetApplicationLocale();
227 #endif
228     AddPair(list, ASCIIToUTF16("Current Language"), ASCIIToUTF16(locale));
229
230     AddPair(list, ASCIIToUTF16("Hotword Previous Language"),
231             ASCIIToUTF16(profile_->GetPrefs()->GetString(
232                 prefs::kHotwordPreviousLanguage)));
233
234     AddLineBreak(list);
235   }
236
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));
244
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));
252
253     std::string group = base::FieldTrialList::FindFullName(
254         hotword_internal::kHotwordFieldTrialName);
255     AddPair(list, ASCIIToUTF16("Field trial"), ASCIIToUTF16(group));
256
257     AddLineBreak(list);
258   }
259
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");
264     base::FilePath path;
265
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);
274       if (extension) {
275         id = extension->id();
276         version = extension->VersionString();
277         path = extension->path();
278       }
279     }
280     AddPair(list, ASCIIToUTF16("Extension Id"),
281             ASCIIToUTF16(id));
282     AddPair(list, ASCIIToUTF16("Extension Version"),
283             ASCIIToUTF16(version));
284     AddPair(list, ASCIIToUTF16("Extension Path"),
285             path.empty() ? ASCIIToUTF16("undefined") : path.LossyDisplayName());
286
287     extensions::ExtensionPrefs* extension_prefs =
288         extensions::ExtensionPrefs::Get(profile_);
289     int pref_state = -1;
290     extension_prefs->ReadPrefAsInteger(extension_misc::kHotwordExtensionId,
291                                        "state", &pref_state);
292     std::string state;
293     switch (pref_state) {
294       case extensions::Extension::DISABLED:
295         state = "DISABLED";
296         break;
297       case extensions::Extension::ENABLED:
298         state = "ENABLED";
299         break;
300       case extensions::Extension::EXTERNAL_EXTENSION_UNINSTALLED:
301         state = "EXTERNAL_EXTENSION_UNINSTALLED";
302         break;
303       default:
304         state = "undefined";
305     }
306
307     AddPair(list, ASCIIToUTF16("Extension State"), ASCIIToUTF16(state));
308
309     AddLineBreak(list);
310   }
311
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";
324           break;
325         case app_list::SPEECH_RECOGNITION_READY:
326           state = "SPEECH_RECOGNITION_READY";
327           break;
328         case app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING:
329           state = "SPEECH_RECOGNITION_HOTWORD_LISTENING";
330           break;
331         case app_list::SPEECH_RECOGNITION_RECOGNIZING:
332           state = "SPEECH_RECOGNITION_RECOGNIZING";
333           break;
334         case app_list::SPEECH_RECOGNITION_IN_SPEECH:
335           state = "SPEECH_RECOGNITION_IN_SPEECH";
336           break;
337         case app_list::SPEECH_RECOGNITION_STOPPING:
338           state = "SPEECH_RECOGNITION_STOPPING";
339           break;
340         case app_list::SPEECH_RECOGNITION_NETWORK_ERROR:
341           state = "SPEECH_RECOGNITION_NETWORK_ERROR";
342           break;
343         default:
344           state = "undefined";
345       }
346     }
347     AddPair(list, ASCIIToUTF16("Start Page State"), ASCIIToUTF16(state));
348 #endif
349   }
350
351   Profile* profile_;
352
353   DISALLOW_COPY_AND_ASSIGN(VoiceSearchDomHandler);
354 };
355
356 }  // namespace
357
358 ///////////////////////////////////////////////////////////////////////////////
359 //
360 // VoiceSearchUI
361 //
362 ///////////////////////////////////////////////////////////////////////////////
363
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));
368
369   // Set up the about:voicesearch source.
370   content::WebUIDataSource::Add(profile, CreateVoiceSearchUiHtmlSource());
371 }
372
373 VoiceSearchUI::~VoiceSearchUI() {}