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.
5 #include "chrome/browser/ui/app_list/start_page_service.h"
9 #include "base/command_line.h"
10 #include "base/memory/singleton.h"
11 #include "base/metrics/user_metrics.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/media/media_stream_infobar_delegate.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/app_list/recommended_apps.h"
16 #include "chrome/browser/ui/app_list/start_page_observer.h"
17 #include "chrome/browser/ui/app_list/start_page_service_factory.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/url_constants.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_contents_delegate.h"
27 #include "extensions/browser/extension_system_provider.h"
28 #include "extensions/browser/extensions_browser_client.h"
29 #include "extensions/common/extension.h"
30 #include "ui/app_list/app_list_switches.h"
32 using base::RecordAction
;
33 using base::UserMetricsAction
;
39 bool InSpeechRecognition(SpeechRecognitionState state
) {
40 return state
== SPEECH_RECOGNITION_RECOGNIZING
||
41 state
== SPEECH_RECOGNITION_IN_SPEECH
;
46 class StartPageService::ProfileDestroyObserver
47 : public content::NotificationObserver
{
49 explicit ProfileDestroyObserver(StartPageService
* service
)
52 chrome::NOTIFICATION_PROFILE_DESTROYED
,
53 content::Source
<Profile
>(service_
->profile()));
55 virtual ~ProfileDestroyObserver() {}
58 // content::NotificationObserver
59 virtual void Observe(int type
,
60 const content::NotificationSource
& source
,
61 const content::NotificationDetails
& details
) OVERRIDE
{
62 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED
, type
);
63 DCHECK_EQ(service_
->profile(), content::Source
<Profile
>(source
).ptr());
67 StartPageService
* service_
; // Owner of this class.
68 content::NotificationRegistrar registrar_
;
70 DISALLOW_COPY_AND_ASSIGN(ProfileDestroyObserver
);
73 class StartPageService::StartPageWebContentsDelegate
74 : public content::WebContentsDelegate
{
76 StartPageWebContentsDelegate() {}
77 virtual ~StartPageWebContentsDelegate() {}
79 virtual void RequestMediaAccessPermission(
80 content::WebContents
* web_contents
,
81 const content::MediaStreamRequest
& request
,
82 const content::MediaResponseCallback
& callback
) OVERRIDE
{
83 if (MediaStreamInfoBarDelegate::Create(web_contents
, request
, callback
))
84 NOTREACHED() << "Media stream not allowed for WebUI";
88 DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate
);
92 StartPageService
* StartPageService::Get(Profile
* profile
) {
93 return StartPageServiceFactory::GetForProfile(profile
);
96 StartPageService::StartPageService(Profile
* profile
)
98 profile_destroy_observer_(new ProfileDestroyObserver(this)),
99 recommended_apps_(new RecommendedApps(profile
)),
100 state_(app_list::SPEECH_RECOGNITION_OFF
),
101 speech_button_toggled_manually_(false),
102 speech_result_obtained_(false) {
103 #if defined(OS_CHROMEOS)
104 // Updates the default state to hotword listening, because this is
105 // the default behavior. This will be updated when the page is loaded and
106 // the nacl module is loaded.
107 if (app_list::switches::IsVoiceSearchEnabled())
108 state_
= app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING
;
111 contents_
.reset(content::WebContents::Create(
112 content::WebContents::CreateParams(profile_
)));
113 contents_delegate_
.reset(new StartPageWebContentsDelegate());
114 contents_
->SetDelegate(contents_delegate_
.get());
116 GURL
url(chrome::kChromeUIAppListStartPageURL
);
117 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
118 if (command_line
->HasSwitch(::switches::kAppListStartPageURL
)) {
120 command_line
->GetSwitchValueASCII(::switches::kAppListStartPageURL
));
123 contents_
->GetController().LoadURL(
126 content::PAGE_TRANSITION_AUTO_TOPLEVEL
,
130 StartPageService::~StartPageService() {}
132 void StartPageService::AddObserver(StartPageObserver
* observer
) {
133 observers_
.AddObserver(observer
);
136 void StartPageService::RemoveObserver(StartPageObserver
* observer
) {
137 observers_
.RemoveObserver(observer
);
140 void StartPageService::ToggleSpeechRecognition() {
141 speech_button_toggled_manually_
= true;
142 contents_
->GetWebUI()->CallJavascriptFunction(
143 "appList.startPage.toggleSpeechRecognition");
146 content::WebContents
* StartPageService::GetStartPageContents() {
147 return CommandLine::ForCurrentProcess()->HasSwitch(
148 ::switches::kShowAppListStartPage
) ? contents_
.get() : NULL
;
151 content::WebContents
* StartPageService::GetSpeechRecognitionContents() {
152 return app_list::switches::IsVoiceSearchEnabled() ? contents_
.get() : NULL
;
155 void StartPageService::OnSpeechResult(
156 const base::string16
& query
, bool is_final
) {
158 speech_result_obtained_
= true;
159 RecordAction(UserMetricsAction("AppList_SearchedBySpeech"));
161 FOR_EACH_OBSERVER(StartPageObserver
,
163 OnSpeechResult(query
, is_final
));
166 void StartPageService::OnSpeechSoundLevelChanged(int16 level
) {
167 FOR_EACH_OBSERVER(StartPageObserver
,
169 OnSpeechSoundLevelChanged(level
));
172 void StartPageService::OnSpeechRecognitionStateChanged(
173 SpeechRecognitionState new_state
) {
174 if (!InSpeechRecognition(state_
) && InSpeechRecognition(new_state
)) {
175 if (!speech_button_toggled_manually_
&&
176 state_
== SPEECH_RECOGNITION_HOTWORD_LISTENING
) {
177 RecordAction(UserMetricsAction("AppList_HotwordRecognized"));
179 RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually"));
181 } else if (InSpeechRecognition(state_
) && !InSpeechRecognition(new_state
) &&
182 !speech_result_obtained_
) {
183 RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled"));
185 speech_button_toggled_manually_
= false;
186 speech_result_obtained_
= false;
188 FOR_EACH_OBSERVER(StartPageObserver
,
190 OnSpeechRecognitionStateChanged(new_state
));
193 void StartPageService::Shutdown() {
197 } // namespace app_list