Revert of Merge apps/pref* to extensions/browser/pref* (patchset #1 of https://codere...
[chromium-blink-merge.git] / chrome / browser / ui / app_list / start_page_service.cc
blob3615a6e85f82c10c9f1231c4372bc48696758c1d
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"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/memory/singleton.h"
11 #include "base/metrics/user_metrics.h"
12 #include "base/prefs/pref_service.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/media/media_stream_infobar_delegate.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search/hotword_service.h"
17 #include "chrome/browser/search/hotword_service_factory.h"
18 #include "chrome/browser/ui/app_list/recommended_apps.h"
19 #include "chrome/browser/ui/app_list/start_page_observer.h"
20 #include "chrome/browser/ui/app_list/start_page_service_factory.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_observer.h"
26 #include "content/public/browser/notification_registrar.h"
27 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/notification_source.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/browser/web_contents_delegate.h"
31 #include "extensions/browser/extension_system_provider.h"
32 #include "extensions/browser/extensions_browser_client.h"
33 #include "extensions/common/extension.h"
34 #include "ui/app_list/app_list_switches.h"
36 using base::RecordAction;
37 using base::UserMetricsAction;
39 namespace app_list {
41 namespace {
43 bool InSpeechRecognition(SpeechRecognitionState state) {
44 return state == SPEECH_RECOGNITION_RECOGNIZING ||
45 state == SPEECH_RECOGNITION_IN_SPEECH;
50 class StartPageService::ProfileDestroyObserver
51 : public content::NotificationObserver {
52 public:
53 explicit ProfileDestroyObserver(StartPageService* service)
54 : service_(service) {
55 registrar_.Add(this,
56 chrome::NOTIFICATION_PROFILE_DESTROYED,
57 content::Source<Profile>(service_->profile()));
59 virtual ~ProfileDestroyObserver() {}
61 private:
62 // content::NotificationObserver
63 virtual void Observe(int type,
64 const content::NotificationSource& source,
65 const content::NotificationDetails& details) OVERRIDE {
66 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
67 DCHECK_EQ(service_->profile(), content::Source<Profile>(source).ptr());
68 service_->Shutdown();
71 StartPageService* service_; // Owner of this class.
72 content::NotificationRegistrar registrar_;
74 DISALLOW_COPY_AND_ASSIGN(ProfileDestroyObserver);
77 class StartPageService::StartPageWebContentsDelegate
78 : public content::WebContentsDelegate {
79 public:
80 StartPageWebContentsDelegate() {}
81 virtual ~StartPageWebContentsDelegate() {}
83 virtual void RequestMediaAccessPermission(
84 content::WebContents* web_contents,
85 const content::MediaStreamRequest& request,
86 const content::MediaResponseCallback& callback) OVERRIDE {
87 if (MediaStreamInfoBarDelegate::Create(web_contents, request, callback))
88 NOTREACHED() << "Media stream not allowed for WebUI";
91 private:
92 DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate);
95 // static
96 StartPageService* StartPageService::Get(Profile* profile) {
97 return StartPageServiceFactory::GetForProfile(profile);
100 StartPageService::StartPageService(Profile* profile)
101 : profile_(profile),
102 profile_destroy_observer_(new ProfileDestroyObserver(this)),
103 recommended_apps_(new RecommendedApps(profile)),
104 state_(app_list::SPEECH_RECOGNITION_OFF),
105 speech_button_toggled_manually_(false),
106 speech_result_obtained_(false) {
107 // If experimental hotwording is enabled, then we're always "ready".
108 // Transitioning into the "hotword recognizing" state is handled by the
109 // hotword extension.
110 if (HotwordService::IsExperimentalHotwordingEnabled())
111 state_ = app_list::SPEECH_RECOGNITION_READY;
113 if (app_list::switches::IsExperimentalAppListEnabled())
114 LoadContents();
117 StartPageService::~StartPageService() {}
119 void StartPageService::AddObserver(StartPageObserver* observer) {
120 observers_.AddObserver(observer);
123 void StartPageService::RemoveObserver(StartPageObserver* observer) {
124 observers_.RemoveObserver(observer);
127 void StartPageService::AppListShown() {
128 if (!contents_) {
129 LoadContents();
130 } else {
131 // If experimental hotwording is enabled, don't enable hotwording in the
132 // start page, since the hotword extension is taking care of this.
133 bool hotword_enabled = HotwordEnabled() &&
134 !HotwordService::IsExperimentalHotwordingEnabled();
135 contents_->GetWebUI()->CallJavascriptFunction(
136 "appList.startPage.onAppListShown",
137 base::FundamentalValue(hotword_enabled));
141 void StartPageService::AppListHidden() {
142 contents_->GetWebUI()->CallJavascriptFunction(
143 "appList.startPage.onAppListHidden");
144 if (!app_list::switches::IsExperimentalAppListEnabled())
145 UnloadContents();
148 void StartPageService::ToggleSpeechRecognition() {
149 speech_button_toggled_manually_ = true;
150 contents_->GetWebUI()->CallJavascriptFunction(
151 "appList.startPage.toggleSpeechRecognition");
154 bool StartPageService::HotwordEnabled() {
155 if (HotwordService::IsExperimentalHotwordingEnabled()) {
156 return HotwordServiceFactory::IsServiceAvailable(profile_) &&
157 profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled);
159 #if defined(OS_CHROMEOS)
160 return HotwordServiceFactory::IsServiceAvailable(profile_) &&
161 profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled);
162 #else
163 return false;
164 #endif
167 content::WebContents* StartPageService::GetStartPageContents() {
168 return app_list::switches::IsExperimentalAppListEnabled() ? contents_.get()
169 : NULL;
172 content::WebContents* StartPageService::GetSpeechRecognitionContents() {
173 if (app_list::switches::IsVoiceSearchEnabled()) {
174 if (!contents_)
175 LoadContents();
176 return contents_.get();
178 return NULL;
181 void StartPageService::OnSpeechResult(
182 const base::string16& query, bool is_final) {
183 if (is_final) {
184 speech_result_obtained_ = true;
185 RecordAction(UserMetricsAction("AppList_SearchedBySpeech"));
187 FOR_EACH_OBSERVER(StartPageObserver,
188 observers_,
189 OnSpeechResult(query, is_final));
192 void StartPageService::OnSpeechSoundLevelChanged(int16 level) {
193 FOR_EACH_OBSERVER(StartPageObserver,
194 observers_,
195 OnSpeechSoundLevelChanged(level));
198 void StartPageService::OnSpeechRecognitionStateChanged(
199 SpeechRecognitionState new_state) {
200 if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) {
201 if (!speech_button_toggled_manually_ &&
202 state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) {
203 RecordAction(UserMetricsAction("AppList_HotwordRecognized"));
204 } else {
205 RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually"));
207 } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) &&
208 !speech_result_obtained_) {
209 RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled"));
211 speech_button_toggled_manually_ = false;
212 speech_result_obtained_ = false;
213 state_ = new_state;
214 FOR_EACH_OBSERVER(StartPageObserver,
215 observers_,
216 OnSpeechRecognitionStateChanged(new_state));
219 void StartPageService::Shutdown() {
220 UnloadContents();
223 void StartPageService::LoadContents() {
224 contents_.reset(content::WebContents::Create(
225 content::WebContents::CreateParams(profile_)));
226 contents_delegate_.reset(new StartPageWebContentsDelegate());
227 contents_->SetDelegate(contents_delegate_.get());
229 GURL url(chrome::kChromeUIAppListStartPageURL);
230 CommandLine* command_line = CommandLine::ForCurrentProcess();
231 if (command_line->HasSwitch(::switches::kAppListStartPageURL)) {
232 url = GURL(
233 command_line->GetSwitchValueASCII(::switches::kAppListStartPageURL));
236 contents_->GetController().LoadURL(
237 url,
238 content::Referrer(),
239 content::PAGE_TRANSITION_AUTO_TOPLEVEL,
240 std::string());
243 void StartPageService::UnloadContents() {
244 contents_.reset();
247 } // namespace app_list