start_page_handler.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/webui/app_list/start_page_handler.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/prefs/pref_service.h"
12#include "base/sys_info.h"
13#include "base/values.h"
14#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/search/hotword_service.h"
17#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
18#include "chrome/browser/ui/app_list/app_list_service.h"
19#include "chrome/browser/ui/app_list/recommended_apps.h"
20#include "chrome/browser/ui/app_list/start_page_service.h"
21#include "chrome/browser/ui/host_desktop.h"
22#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
23#include "chrome/common/extensions/extension_icon_set.h"
24#include "chrome/common/pref_names.h"
25#include "content/public/browser/web_contents_view.h"
26#include "content/public/browser/web_ui.h"
27#include "extensions/browser/extension_system.h"
28#include "extensions/common/extension.h"
29#include "ui/app_list/app_list_switches.h"
30#include "ui/app_list/speech_ui_model_observer.h"
31#include "ui/events/event_constants.h"
32
33namespace app_list {
34
35namespace {
36
37scoped_ptr<base::DictionaryValue> CreateAppInfo(
38    const extensions::Extension* app) {
39  scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
40  dict->SetString("appId", app->id());
41  dict->SetString("textTitle", app->short_name());
42  dict->SetString("title", app->name());
43
44  const bool grayscale = false;
45  bool icon_exists = true;
46  GURL icon_url = extensions::ExtensionIconSource::GetIconURL(
47      app,
48      extension_misc::EXTENSION_ICON_MEDIUM,
49      ExtensionIconSet::MATCH_BIGGER,
50      grayscale,
51      &icon_exists);
52  dict->SetString("iconUrl", icon_url.spec());
53
54  return dict.Pass();
55}
56
57}  // namespace
58
59StartPageHandler::StartPageHandler() : recommended_apps_(NULL) {}
60
61StartPageHandler::~StartPageHandler() {
62  if (recommended_apps_)
63    recommended_apps_->RemoveObserver(this);
64}
65
66void StartPageHandler::RegisterMessages() {
67  web_ui()->RegisterMessageCallback(
68      "initialize",
69      base::Bind(&StartPageHandler::HandleInitialize, base::Unretained(this)));
70  web_ui()->RegisterMessageCallback(
71      "launchApp",
72      base::Bind(&StartPageHandler::HandleLaunchApp, base::Unretained(this)));
73  web_ui()->RegisterMessageCallback(
74      "speechResult",
75      base::Bind(&StartPageHandler::HandleSpeechResult,
76                 base::Unretained(this)));
77  web_ui()->RegisterMessageCallback(
78      "speechSoundLevel",
79      base::Bind(&StartPageHandler::HandleSpeechSoundLevel,
80                 base::Unretained(this)));
81  web_ui()->RegisterMessageCallback(
82      "setSpeechRecognitionState",
83      base::Bind(&StartPageHandler::HandleSpeechRecognition,
84                 base::Unretained(this)));
85}
86
87void StartPageHandler::OnRecommendedAppsChanged() {
88  SendRecommendedApps();
89}
90
91void StartPageHandler::SendRecommendedApps() {
92  const RecommendedApps::Apps& recommends = recommended_apps_->apps();
93
94  base::ListValue recommended_list;
95  for (size_t i = 0; i < recommends.size(); ++i) {
96    recommended_list.Append(CreateAppInfo(recommends[i].get()).release());
97  }
98
99  web_ui()->CallJavascriptFunction("appList.startPage.setRecommendedApps",
100                                   recommended_list);
101}
102
103#if defined(OS_CHROMEOS)
104bool StartPageHandler::HotwordEnabled() {
105  Profile* profile = Profile::FromWebUI(web_ui());
106  return HotwordService::DoesHotwordSupportLanguage(profile) &&
107      profile->GetPrefs()->GetBoolean(prefs::kHotwordAppListEnabled);
108}
109
110void StartPageHandler::OnHotwordEnabledChanged() {
111  web_ui()->CallJavascriptFunction(
112      "appList.startPage.setHotwordEnabled",
113      base::FundamentalValue(HotwordEnabled()));
114}
115
116void StartPageHandler::SynchronizeHotwordEnabled() {
117  Profile* profile = Profile::FromWebUI(web_ui());
118  PrefService* pref_service = profile->GetPrefs();
119  const PrefService::Preference* pref =
120      pref_service->FindPreference(prefs::kHotwordSearchEnabled);
121  if (!pref || pref->IsDefaultValue())
122    return;
123
124  bool search_enabled = false;
125  if (!pref->GetValue()->GetAsBoolean(&search_enabled))
126    return;
127
128  if (pref_service->GetBoolean(prefs::kHotwordAppListEnabled) != search_enabled)
129    pref_service->SetBoolean(prefs::kHotwordAppListEnabled, search_enabled);
130}
131#endif
132
133void StartPageHandler::HandleInitialize(const base::ListValue* args) {
134  Profile* profile = Profile::FromWebUI(web_ui());
135  StartPageService* service = StartPageService::Get(profile);
136  if (!service)
137    return;
138
139  recommended_apps_ = service->recommended_apps();
140  recommended_apps_->AddObserver(this);
141
142  SendRecommendedApps();
143
144#if defined(OS_CHROMEOS)
145  if (app_list::switches::IsVoiceSearchEnabled() &&
146      HotwordService::DoesHotwordSupportLanguage(profile) &&
147      base::SysInfo::IsRunningOnChromeOS()) {
148    SynchronizeHotwordEnabled();
149    OnHotwordEnabledChanged();
150    pref_change_registrar_.Init(profile->GetPrefs());
151    pref_change_registrar_.Add(
152        prefs::kHotwordSearchEnabled,
153        base::Bind(&StartPageHandler::SynchronizeHotwordEnabled,
154                   base::Unretained(this)));
155    pref_change_registrar_.Add(
156        prefs::kHotwordAppListEnabled,
157        base::Bind(&StartPageHandler::OnHotwordEnabledChanged,
158                   base::Unretained(this)));
159  }
160#endif
161}
162
163void StartPageHandler::HandleLaunchApp(const base::ListValue* args) {
164  std::string app_id;
165  CHECK(args->GetString(0, &app_id));
166
167  Profile* profile = Profile::FromWebUI(web_ui());
168  ExtensionService* service =
169      extensions::ExtensionSystem::Get(profile)->extension_service();
170  const extensions::Extension* app = service->GetInstalledExtension(app_id);
171  if (!app) {
172    NOTREACHED();
173    return;
174  }
175
176  AppListControllerDelegate* controller = AppListService::Get(
177      chrome::GetHostDesktopTypeForNativeView(
178          web_ui()->GetWebContents()->GetView()->GetNativeView()))
179      ->GetControllerDelegate();
180  controller->ActivateApp(profile,
181                          app,
182                          AppListControllerDelegate::LAUNCH_FROM_APP_LIST,
183                          ui::EF_NONE);
184}
185
186void StartPageHandler::HandleSpeechResult(const base::ListValue* args) {
187  base::string16 query;
188  bool is_final = false;
189  CHECK(args->GetString(0, &query));
190  CHECK(args->GetBoolean(1, &is_final));
191
192  StartPageService::Get(Profile::FromWebUI(web_ui()))->OnSpeechResult(
193      query, is_final);
194}
195
196void StartPageHandler::HandleSpeechSoundLevel(const base::ListValue* args) {
197  double level;
198  CHECK(args->GetDouble(0, &level));
199
200  StartPageService* service =
201      StartPageService::Get(Profile::FromWebUI(web_ui()));
202  if (service)
203    service->OnSpeechSoundLevelChanged(static_cast<int16>(level));
204}
205
206void StartPageHandler::HandleSpeechRecognition(const base::ListValue* args) {
207  std::string state_string;
208  CHECK(args->GetString(0, &state_string));
209
210  SpeechRecognitionState new_state = SPEECH_RECOGNITION_OFF;
211  if (state_string == "READY")
212    new_state = SPEECH_RECOGNITION_READY;
213  else if (state_string == "HOTWORD_RECOGNIZING")
214    new_state = SPEECH_RECOGNITION_HOTWORD_LISTENING;
215  else if (state_string == "RECOGNIZING")
216    new_state = SPEECH_RECOGNITION_RECOGNIZING;
217  else if (state_string == "IN_SPEECH")
218    new_state = SPEECH_RECOGNITION_IN_SPEECH;
219  else if (state_string == "STOPPING")
220    new_state = SPEECH_RECOGNITION_STOPPING;
221
222  StartPageService* service =
223      StartPageService::Get(Profile::FromWebUI(web_ui()));
224  if (service)
225    service->OnSpeechRecognitionStateChanged(new_state);
226}
227
228}  // namespace app_list
229