start_page_handler.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Copyright 2013 The Chromium Authors. All rights reserved. 230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Use of this source code is governed by a BSD-style license that can be 330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// found in the LICENSE file. 430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/webui/app_list/start_page_handler.h" 630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <string> 830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "base/bind.h" 1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "base/memory/scoped_ptr.h" 1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "base/values.h" 1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "base/version.h" 1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/omaha_query_params/omaha_query_params.h" 1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/profiles/profile.h" 1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/search/hotword_service.h" 1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" 1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/app_list/app_list_service.h" 1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/app_list/recommended_apps.h" 1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/app_list/start_page_service.h" 2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/host_desktop.h" 2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "chrome/common/pref_names.h" 2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "content/public/browser/web_ui.h" 2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "extensions/browser/extension_registry.h" 2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "extensions/browser/extension_system.h" 2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "extensions/common/constants.h" 2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "extensions/common/extension.h" 2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "extensions/common/extension_icon_set.h" 2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "ui/app_list/app_list_switches.h" 3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "ui/app_list/speech_ui_model_observer.h" 3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "ui/events/event_constants.h" 3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace app_list { 3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace { 3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined(OS_CHROMEOS) 3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst char kOldHotwordExtensionVersionString[] = "0.1.1.5014_0"; 3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunscoped_ptr<base::DictionaryValue> CreateAppInfo( 42 const extensions::Extension* app) { 43 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 44 dict->SetString("appId", app->id()); 45 dict->SetString("textTitle", app->short_name()); 46 dict->SetString("title", app->name()); 47 48 const bool grayscale = false; 49 bool icon_exists = true; 50 GURL icon_url = extensions::ExtensionIconSource::GetIconURL( 51 app, 52 extension_misc::EXTENSION_ICON_MEDIUM, 53 ExtensionIconSet::MATCH_BIGGER, 54 grayscale, 55 &icon_exists); 56 dict->SetString("iconUrl", icon_url.spec()); 57 58 return dict.Pass(); 59} 60 61} // namespace 62 63StartPageHandler::StartPageHandler() 64 : recommended_apps_(NULL), 65 extension_registry_observer_(this) { 66} 67 68StartPageHandler::~StartPageHandler() { 69 if (recommended_apps_) 70 recommended_apps_->RemoveObserver(this); 71} 72 73void StartPageHandler::RegisterMessages() { 74 web_ui()->RegisterMessageCallback( 75 "initialize", 76 base::Bind(&StartPageHandler::HandleInitialize, base::Unretained(this))); 77 web_ui()->RegisterMessageCallback( 78 "launchApp", 79 base::Bind(&StartPageHandler::HandleLaunchApp, base::Unretained(this))); 80 web_ui()->RegisterMessageCallback( 81 "speechResult", 82 base::Bind(&StartPageHandler::HandleSpeechResult, 83 base::Unretained(this))); 84 web_ui()->RegisterMessageCallback( 85 "speechSoundLevel", 86 base::Bind(&StartPageHandler::HandleSpeechSoundLevel, 87 base::Unretained(this))); 88 web_ui()->RegisterMessageCallback( 89 "setSpeechRecognitionState", 90 base::Bind(&StartPageHandler::HandleSpeechRecognition, 91 base::Unretained(this))); 92} 93 94void StartPageHandler::OnExtensionLoaded( 95 content::BrowserContext* browser_context, 96 const extensions::Extension* extension) { 97#if defined(OS_CHROMEOS) 98 DCHECK_EQ(Profile::FromWebUI(web_ui()), 99 Profile::FromBrowserContext(browser_context)); 100 if (extension->id() == extension_misc::kHotwordExtensionId) 101 OnHotwordEnabledChanged(); 102#endif 103} 104 105void StartPageHandler::OnExtensionUnloaded( 106 content::BrowserContext* browser_context, 107 const extensions::Extension* extension, 108 extensions::UnloadedExtensionInfo::Reason reason) { 109#if defined(OS_CHROMEOS) 110 DCHECK_EQ(Profile::FromWebUI(web_ui()), 111 Profile::FromBrowserContext(browser_context)); 112 if (extension->id() == extension_misc::kHotwordExtensionId) 113 OnHotwordEnabledChanged(); 114#endif 115} 116 117void StartPageHandler::OnRecommendedAppsChanged() { 118 SendRecommendedApps(); 119} 120 121void StartPageHandler::SendRecommendedApps() { 122 const RecommendedApps::Apps& recommends = recommended_apps_->apps(); 123 124 base::ListValue recommended_list; 125 for (size_t i = 0; i < recommends.size(); ++i) { 126 recommended_list.Append(CreateAppInfo(recommends[i].get()).release()); 127 } 128 129 web_ui()->CallJavascriptFunction("appList.startPage.setRecommendedApps", 130 recommended_list); 131} 132 133#if defined(OS_CHROMEOS) 134void StartPageHandler::OnHotwordEnabledChanged() { 135 // If the hotword extension is new enough, we should use the new 136 // hotwordPrivate API to provide the feature. 137 // TODO(mukai): remove this after everything gets stable. 138 Profile* profile = Profile::FromWebUI(web_ui()); 139 140 extensions::ExtensionRegistry* registry = 141 extensions::ExtensionRegistry::Get(profile); 142 const extensions::Extension* hotword_extension = 143 registry->GetExtensionById(extension_misc::kHotwordExtensionId, 144 extensions::ExtensionRegistry::ENABLED); 145 if (hotword_extension && 146 hotword_extension->version()->CompareTo( 147 base::Version(kOldHotwordExtensionVersionString)) <= 0) { 148 StartPageService* service = StartPageService::Get(profile); 149 web_ui()->CallJavascriptFunction( 150 "appList.startPage.setHotwordEnabled", 151 base::FundamentalValue(service->HotwordEnabled())); 152 } 153} 154#endif 155 156void StartPageHandler::HandleInitialize(const base::ListValue* args) { 157 Profile* profile = Profile::FromWebUI(web_ui()); 158 StartPageService* service = StartPageService::Get(profile); 159 if (!service) 160 return; 161 162 recommended_apps_ = service->recommended_apps(); 163 recommended_apps_->AddObserver(this); 164 165 SendRecommendedApps(); 166 167#if defined(OS_CHROMEOS) 168 if (app_list::switches::IsVoiceSearchEnabled() && 169 HotwordService::DoesHotwordSupportLanguage(profile)) { 170 OnHotwordEnabledChanged(); 171 pref_change_registrar_.Init(profile->GetPrefs()); 172 pref_change_registrar_.Add( 173 prefs::kHotwordSearchEnabled, 174 base::Bind(&StartPageHandler::OnHotwordEnabledChanged, 175 base::Unretained(this))); 176 177 extension_registry_observer_.Add( 178 extensions::ExtensionRegistry::Get(profile)); 179 } 180#endif 181 182 web_ui()->CallJavascriptFunction( 183 "appList.startPage.setNaclArch", 184 base::StringValue(chrome::OmahaQueryParams::GetNaclArch())); 185 186 if (!app_list::switches::IsExperimentalAppListEnabled()) { 187 web_ui()->CallJavascriptFunction( 188 "appList.startPage.onAppListShown", 189 base::FundamentalValue(service->HotwordEnabled())); 190 } 191} 192 193void StartPageHandler::HandleLaunchApp(const base::ListValue* args) { 194 std::string app_id; 195 CHECK(args->GetString(0, &app_id)); 196 197 Profile* profile = Profile::FromWebUI(web_ui()); 198 const extensions::Extension* app = 199 extensions::ExtensionRegistry::Get(profile) 200 ->GetExtensionById(app_id, extensions::ExtensionRegistry::EVERYTHING); 201 if (!app) { 202 NOTREACHED(); 203 return; 204 } 205 206 AppListControllerDelegate* controller = AppListService::Get( 207 chrome::GetHostDesktopTypeForNativeView( 208 web_ui()->GetWebContents()->GetNativeView()))-> 209 GetControllerDelegate(); 210 controller->ActivateApp(profile, 211 app, 212 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, 213 ui::EF_NONE); 214} 215 216void StartPageHandler::HandleSpeechResult(const base::ListValue* args) { 217 base::string16 query; 218 bool is_final = false; 219 CHECK(args->GetString(0, &query)); 220 CHECK(args->GetBoolean(1, &is_final)); 221 222 StartPageService::Get(Profile::FromWebUI(web_ui()))->OnSpeechResult( 223 query, is_final); 224} 225 226void StartPageHandler::HandleSpeechSoundLevel(const base::ListValue* args) { 227 double level; 228 CHECK(args->GetDouble(0, &level)); 229 230 StartPageService* service = 231 StartPageService::Get(Profile::FromWebUI(web_ui())); 232 if (service) 233 service->OnSpeechSoundLevelChanged(static_cast<int16>(level)); 234} 235 236void StartPageHandler::HandleSpeechRecognition(const base::ListValue* args) { 237 std::string state_string; 238 CHECK(args->GetString(0, &state_string)); 239 240 SpeechRecognitionState new_state = SPEECH_RECOGNITION_OFF; 241 if (state_string == "READY") 242 new_state = SPEECH_RECOGNITION_READY; 243 else if (state_string == "HOTWORD_RECOGNIZING") 244 new_state = SPEECH_RECOGNITION_HOTWORD_LISTENING; 245 else if (state_string == "RECOGNIZING") 246 new_state = SPEECH_RECOGNITION_RECOGNIZING; 247 else if (state_string == "IN_SPEECH") 248 new_state = SPEECH_RECOGNITION_IN_SPEECH; 249 else if (state_string == "STOPPING") 250 new_state = SPEECH_RECOGNITION_STOPPING; 251 252 StartPageService* service = 253 StartPageService::Get(Profile::FromWebUI(web_ui())); 254 if (service) 255 service->OnSpeechRecognitionStateChanged(new_state); 256} 257 258} // namespace app_list 259