| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/webui/app_list/start_page_handler.h" | 5 #include "chrome/browser/ui/webui/app_list/start_page_handler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "base/version.h" | 13 #include "base/version.h" |
| 14 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/search/hotword_service.h" | |
| 16 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" | 15 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" |
| 17 #include "chrome/browser/ui/app_list/app_list_service.h" | 16 #include "chrome/browser/ui/app_list/app_list_service.h" |
| 18 #include "chrome/browser/ui/app_list/start_page_service.h" | 17 #include "chrome/browser/ui/app_list/start_page_service.h" |
| 19 #include "chrome/browser/ui/host_desktop.h" | 18 #include "chrome/browser/ui/host_desktop.h" |
| 20 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" | 19 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
| 21 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
| 22 #include "components/update_client/update_query_params.h" | 21 #include "components/update_client/update_query_params.h" |
| 23 #include "content/public/browser/web_ui.h" | 22 #include "content/public/browser/web_ui.h" |
| 24 #include "extensions/browser/extension_registry.h" | 23 #include "extensions/browser/extension_registry.h" |
| 25 #include "extensions/browser/extension_system.h" | 24 #include "extensions/browser/extension_system.h" |
| 26 #include "extensions/common/constants.h" | 25 #include "extensions/common/constants.h" |
| 27 #include "extensions/common/extension.h" | 26 #include "extensions/common/extension.h" |
| 28 #include "extensions/common/extension_icon_set.h" | 27 #include "extensions/common/extension_icon_set.h" |
| 29 #include "ui/app_list/app_list_switches.h" | 28 #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" | 29 #include "ui/events/event_constants.h" |
| 32 | 30 |
| 33 namespace app_list { | 31 namespace app_list { |
| 34 | 32 |
| 35 namespace { | 33 namespace { |
| 36 | 34 |
| 37 const char kAppListDoodleActionHistogram[] = "Apps.AppListDoodleAction"; | 35 const char kAppListDoodleActionHistogram[] = "Apps.AppListDoodleAction"; |
| 38 | 36 |
| 39 // Interactions a user has with the app list doodle. This enum must not have its | 37 // Interactions a user has with the app list doodle. This enum must not have its |
| 40 // order altered as it is used in histograms. | 38 // order altered as it is used in histograms. |
| 41 enum DoodleAction { | 39 enum DoodleAction { |
| 42 DOODLE_SHOWN = 0, | 40 DOODLE_SHOWN = 0, |
| 43 DOODLE_CLICKED, | 41 DOODLE_CLICKED, |
| 44 // Add values here. | 42 // Add values here. |
| 45 | 43 |
| 46 DOODLE_ACTION_LAST, | 44 DOODLE_ACTION_LAST, |
| 47 }; | 45 }; |
| 48 | 46 |
| 49 #if defined(OS_CHROMEOS) | |
| 50 const char kOldHotwordExtensionVersionString[] = "0.1.1.5023"; | |
| 51 #endif | |
| 52 | |
| 53 } // namespace | 47 } // namespace |
| 54 | 48 |
| 55 StartPageHandler::StartPageHandler() : extension_registry_observer_(this) { | 49 StartPageHandler::StartPageHandler() { |
| 56 } | 50 } |
| 57 | 51 |
| 58 StartPageHandler::~StartPageHandler() { | 52 StartPageHandler::~StartPageHandler() { |
| 59 } | 53 } |
| 60 | 54 |
| 61 void StartPageHandler::RegisterMessages() { | 55 void StartPageHandler::RegisterMessages() { |
| 62 web_ui()->RegisterMessageCallback( | 56 web_ui()->RegisterMessageCallback( |
| 63 "appListShown", base::Bind(&StartPageHandler::HandleAppListShown, | 57 "appListShown", base::Bind(&StartPageHandler::HandleAppListShown, |
| 64 base::Unretained(this))); | 58 base::Unretained(this))); |
| 65 web_ui()->RegisterMessageCallback( | 59 web_ui()->RegisterMessageCallback( |
| 66 "doodleClicked", base::Bind(&StartPageHandler::HandleDoodleClicked, | 60 "doodleClicked", base::Bind(&StartPageHandler::HandleDoodleClicked, |
| 67 base::Unretained(this))); | 61 base::Unretained(this))); |
| 68 web_ui()->RegisterMessageCallback( | 62 web_ui()->RegisterMessageCallback( |
| 69 "initialize", | 63 "initialize", |
| 70 base::Bind(&StartPageHandler::HandleInitialize, base::Unretained(this))); | 64 base::Bind(&StartPageHandler::HandleInitialize, base::Unretained(this))); |
| 71 web_ui()->RegisterMessageCallback( | 65 web_ui()->RegisterMessageCallback( |
| 72 "launchApp", | 66 "launchApp", |
| 73 base::Bind(&StartPageHandler::HandleLaunchApp, base::Unretained(this))); | 67 base::Bind(&StartPageHandler::HandleLaunchApp, base::Unretained(this))); |
| 74 web_ui()->RegisterMessageCallback( | |
| 75 "speechResult", | |
| 76 base::Bind(&StartPageHandler::HandleSpeechResult, | |
| 77 base::Unretained(this))); | |
| 78 web_ui()->RegisterMessageCallback( | |
| 79 "speechSoundLevel", | |
| 80 base::Bind(&StartPageHandler::HandleSpeechSoundLevel, | |
| 81 base::Unretained(this))); | |
| 82 web_ui()->RegisterMessageCallback( | |
| 83 "setSpeechRecognitionState", | |
| 84 base::Bind(&StartPageHandler::HandleSpeechRecognition, | |
| 85 base::Unretained(this))); | |
| 86 } | 68 } |
| 87 | 69 |
| 88 void StartPageHandler::OnExtensionLoaded( | |
| 89 content::BrowserContext* browser_context, | |
| 90 const extensions::Extension* extension) { | |
| 91 #if defined(OS_CHROMEOS) | |
| 92 DCHECK_EQ(Profile::FromWebUI(web_ui()), | |
| 93 Profile::FromBrowserContext(browser_context)); | |
| 94 if (extension->id() == extension_misc::kHotwordExtensionId) | |
| 95 OnHotwordEnabledChanged(); | |
| 96 #endif | |
| 97 } | |
| 98 | |
| 99 void StartPageHandler::OnExtensionUnloaded( | |
| 100 content::BrowserContext* browser_context, | |
| 101 const extensions::Extension* extension, | |
| 102 extensions::UnloadedExtensionInfo::Reason reason) { | |
| 103 #if defined(OS_CHROMEOS) | |
| 104 DCHECK_EQ(Profile::FromWebUI(web_ui()), | |
| 105 Profile::FromBrowserContext(browser_context)); | |
| 106 if (extension->id() == extension_misc::kHotwordExtensionId) | |
| 107 OnHotwordEnabledChanged(); | |
| 108 #endif | |
| 109 } | |
| 110 | |
| 111 #if defined(OS_CHROMEOS) | |
| 112 void StartPageHandler::OnHotwordEnabledChanged() { | |
| 113 // If the hotword extension is new enough, we should use the new | |
| 114 // hotwordPrivate API to provide the feature. | |
| 115 // TODO(mukai): remove this after everything gets stable. | |
| 116 Profile* profile = Profile::FromWebUI(web_ui()); | |
| 117 | |
| 118 extensions::ExtensionRegistry* registry = | |
| 119 extensions::ExtensionRegistry::Get(profile); | |
| 120 const extensions::Extension* hotword_extension = | |
| 121 registry->GetExtensionById(extension_misc::kHotwordExtensionId, | |
| 122 extensions::ExtensionRegistry::ENABLED); | |
| 123 if (hotword_extension && | |
| 124 hotword_extension->version()->CompareTo( | |
| 125 base::Version(kOldHotwordExtensionVersionString)) <= 0 && | |
| 126 !HotwordService::IsExperimentalHotwordingEnabled()) { | |
| 127 StartPageService* service = StartPageService::Get(profile); | |
| 128 web_ui()->CallJavascriptFunction( | |
| 129 "appList.startPage.setHotwordEnabled", | |
| 130 base::FundamentalValue(service && service->HotwordEnabled())); | |
| 131 } | |
| 132 } | |
| 133 #endif | |
| 134 | |
| 135 void StartPageHandler::HandleAppListShown(const base::ListValue* args) { | 70 void StartPageHandler::HandleAppListShown(const base::ListValue* args) { |
| 136 bool doodle_shown = false; | 71 bool doodle_shown = false; |
| 137 if (args->GetBoolean(0, &doodle_shown) && doodle_shown) { | 72 if (args->GetBoolean(0, &doodle_shown) && doodle_shown) { |
| 138 UMA_HISTOGRAM_ENUMERATION(kAppListDoodleActionHistogram, DOODLE_SHOWN, | 73 UMA_HISTOGRAM_ENUMERATION(kAppListDoodleActionHistogram, DOODLE_SHOWN, |
| 139 DOODLE_ACTION_LAST); | 74 DOODLE_ACTION_LAST); |
| 140 } | 75 } |
| 141 } | 76 } |
| 142 | 77 |
| 143 void StartPageHandler::HandleDoodleClicked(const base::ListValue* args) { | 78 void StartPageHandler::HandleDoodleClicked(const base::ListValue* args) { |
| 144 UMA_HISTOGRAM_ENUMERATION(kAppListDoodleActionHistogram, DOODLE_CLICKED, | 79 UMA_HISTOGRAM_ENUMERATION(kAppListDoodleActionHistogram, DOODLE_CLICKED, |
| 145 DOODLE_ACTION_LAST); | 80 DOODLE_ACTION_LAST); |
| 146 } | 81 } |
| 147 | 82 |
| 148 void StartPageHandler::HandleInitialize(const base::ListValue* args) { | 83 void StartPageHandler::HandleInitialize(const base::ListValue* args) { |
| 149 Profile* profile = Profile::FromWebUI(web_ui()); | 84 Profile* profile = Profile::FromWebUI(web_ui()); |
| 150 StartPageService* service = StartPageService::Get(profile); | 85 StartPageService* service = StartPageService::Get(profile); |
| 151 if (!service) | 86 if (!service) |
| 152 return; | 87 return; |
| 153 | 88 |
| 154 service->WebUILoaded(); | 89 service->WebUILoaded(); |
| 155 | |
| 156 #if defined(OS_CHROMEOS) | |
| 157 if (app_list::switches::IsVoiceSearchEnabled() && | |
| 158 HotwordService::DoesHotwordSupportLanguage(profile)) { | |
| 159 OnHotwordEnabledChanged(); | |
| 160 pref_change_registrar_.Init(profile->GetPrefs()); | |
| 161 pref_change_registrar_.RemoveAll(); | |
| 162 pref_change_registrar_.Add( | |
| 163 prefs::kHotwordSearchEnabled, | |
| 164 base::Bind(&StartPageHandler::OnHotwordEnabledChanged, | |
| 165 base::Unretained(this))); | |
| 166 | |
| 167 extension_registry_observer_.RemoveAll(); | |
| 168 extension_registry_observer_.Add( | |
| 169 extensions::ExtensionRegistry::Get(profile)); | |
| 170 } | |
| 171 | |
| 172 extensions::ExtensionRegistry* registry = | |
| 173 extensions::ExtensionRegistry::Get(profile); | |
| 174 const extensions::Extension* hotword_extension = | |
| 175 registry->GetExtensionById(extension_misc::kHotwordExtensionId, | |
| 176 extensions::ExtensionRegistry::ENABLED); | |
| 177 if (hotword_extension && | |
| 178 hotword_extension->version()->CompareTo( | |
| 179 base::Version(kOldHotwordExtensionVersionString)) <= 0) { | |
| 180 web_ui()->CallJavascriptFunction( | |
| 181 "appList.startPage.setNaclArch", | |
| 182 base::StringValue(update_client::UpdateQueryParams::GetNaclArch())); | |
| 183 } | |
| 184 #endif | |
| 185 | |
| 186 // If v2 hotwording is enabled, don't tell the start page that the app list is | |
| 187 // being shown. V2 hotwording doesn't use the start page for anything. | |
| 188 if (!app_list::switches::IsExperimentalAppListEnabled() && | |
| 189 !HotwordService::IsExperimentalHotwordingEnabled()) { | |
| 190 web_ui()->CallJavascriptFunction( | |
| 191 "appList.startPage.onAppListShown", | |
| 192 base::FundamentalValue(service->HotwordEnabled())); | |
| 193 } | |
| 194 } | 90 } |
| 195 | 91 |
| 196 void StartPageHandler::HandleLaunchApp(const base::ListValue* args) { | 92 void StartPageHandler::HandleLaunchApp(const base::ListValue* args) { |
| 197 std::string app_id; | 93 std::string app_id; |
| 198 CHECK(args->GetString(0, &app_id)); | 94 CHECK(args->GetString(0, &app_id)); |
| 199 | 95 |
| 200 Profile* profile = Profile::FromWebUI(web_ui()); | 96 Profile* profile = Profile::FromWebUI(web_ui()); |
| 201 const extensions::Extension* app = | 97 const extensions::Extension* app = |
| 202 extensions::ExtensionRegistry::Get(profile) | 98 extensions::ExtensionRegistry::Get(profile) |
| 203 ->GetExtensionById(app_id, extensions::ExtensionRegistry::EVERYTHING); | 99 ->GetExtensionById(app_id, extensions::ExtensionRegistry::EVERYTHING); |
| 204 if (!app) { | 100 if (!app) { |
| 205 NOTREACHED(); | 101 NOTREACHED(); |
| 206 return; | 102 return; |
| 207 } | 103 } |
| 208 | 104 |
| 209 AppListControllerDelegate* controller = AppListService::Get( | 105 AppListControllerDelegate* controller = AppListService::Get( |
| 210 chrome::GetHostDesktopTypeForNativeView( | 106 chrome::GetHostDesktopTypeForNativeView( |
| 211 web_ui()->GetWebContents()->GetNativeView()))-> | 107 web_ui()->GetWebContents()->GetNativeView()))-> |
| 212 GetControllerDelegate(); | 108 GetControllerDelegate(); |
| 213 controller->ActivateApp(profile, | 109 controller->ActivateApp(profile, |
| 214 app, | 110 app, |
| 215 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, | 111 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, |
| 216 ui::EF_NONE); | 112 ui::EF_NONE); |
| 217 } | 113 } |
| 218 | 114 |
| 219 void StartPageHandler::HandleSpeechResult(const base::ListValue* args) { | |
| 220 base::string16 query; | |
| 221 bool is_final = false; | |
| 222 CHECK(args->GetString(0, &query)); | |
| 223 CHECK(args->GetBoolean(1, &is_final)); | |
| 224 | |
| 225 StartPageService::Get(Profile::FromWebUI(web_ui()))->OnSpeechResult( | |
| 226 query, is_final); | |
| 227 } | |
| 228 | |
| 229 void StartPageHandler::HandleSpeechSoundLevel(const base::ListValue* args) { | |
| 230 double level; | |
| 231 CHECK(args->GetDouble(0, &level)); | |
| 232 | |
| 233 StartPageService* service = | |
| 234 StartPageService::Get(Profile::FromWebUI(web_ui())); | |
| 235 if (service) | |
| 236 service->OnSpeechSoundLevelChanged(static_cast<int16>(level)); | |
| 237 } | |
| 238 | |
| 239 void StartPageHandler::HandleSpeechRecognition(const base::ListValue* args) { | |
| 240 std::string state_string; | |
| 241 CHECK(args->GetString(0, &state_string)); | |
| 242 | |
| 243 SpeechRecognitionState new_state = SPEECH_RECOGNITION_OFF; | |
| 244 if (state_string == "READY") | |
| 245 new_state = SPEECH_RECOGNITION_READY; | |
| 246 else if (state_string == "HOTWORD_RECOGNIZING") | |
| 247 new_state = SPEECH_RECOGNITION_HOTWORD_LISTENING; | |
| 248 else if (state_string == "RECOGNIZING") | |
| 249 new_state = SPEECH_RECOGNITION_RECOGNIZING; | |
| 250 else if (state_string == "IN_SPEECH") | |
| 251 new_state = SPEECH_RECOGNITION_IN_SPEECH; | |
| 252 else if (state_string == "STOPPING") | |
| 253 new_state = SPEECH_RECOGNITION_STOPPING; | |
| 254 else if (state_string == "NETWORK_ERROR") | |
| 255 new_state = SPEECH_RECOGNITION_NETWORK_ERROR; | |
| 256 | |
| 257 StartPageService* service = | |
| 258 StartPageService::Get(Profile::FromWebUI(web_ui())); | |
| 259 if (service) | |
| 260 service->OnSpeechRecognitionStateChanged(new_state); | |
| 261 } | |
| 262 | |
| 263 } // namespace app_list | 115 } // namespace app_list |
| OLD | NEW |