Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / start_page_service.cc
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/app_list/start_page_service.h"
6
7 #include <string>
8
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_factory.h"
17 #include "chrome/browser/ui/app_list/recommended_apps.h"
18 #include "chrome/browser/ui/app_list/start_page_observer.h"
19 #include "chrome/browser/ui/app_list/start_page_service_factory.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/url_constants.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_observer.h"
25 #include "content/public/browser/notification_registrar.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_contents_delegate.h"
30 #include "extensions/browser/extension_system_provider.h"
31 #include "extensions/browser/extensions_browser_client.h"
32 #include "extensions/common/extension.h"
33 #include "ui/app_list/app_list_switches.h"
34
35 using base::RecordAction;
36 using base::UserMetricsAction;
37
38 namespace app_list {
39
40 namespace {
41
42 bool InSpeechRecognition(SpeechRecognitionState state) {
43   return state == SPEECH_RECOGNITION_RECOGNIZING ||
44       state == SPEECH_RECOGNITION_IN_SPEECH;
45 }
46
47 }
48
49 class StartPageService::ProfileDestroyObserver
50     : public content::NotificationObserver {
51  public:
52   explicit ProfileDestroyObserver(StartPageService* service)
53       : service_(service) {
54     registrar_.Add(this,
55                    chrome::NOTIFICATION_PROFILE_DESTROYED,
56                    content::Source<Profile>(service_->profile()));
57   }
58   virtual ~ProfileDestroyObserver() {}
59
60  private:
61   // content::NotificationObserver
62   virtual void Observe(int type,
63                        const content::NotificationSource& source,
64                        const content::NotificationDetails& details) OVERRIDE {
65     DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
66     DCHECK_EQ(service_->profile(), content::Source<Profile>(source).ptr());
67     service_->Shutdown();
68   }
69
70   StartPageService* service_;  // Owner of this class.
71   content::NotificationRegistrar registrar_;
72
73   DISALLOW_COPY_AND_ASSIGN(ProfileDestroyObserver);
74 };
75
76 class StartPageService::StartPageWebContentsDelegate
77     : public content::WebContentsDelegate {
78  public:
79   StartPageWebContentsDelegate() {}
80   virtual ~StartPageWebContentsDelegate() {}
81
82   virtual void RequestMediaAccessPermission(
83       content::WebContents* web_contents,
84       const content::MediaStreamRequest& request,
85       const content::MediaResponseCallback& callback) OVERRIDE {
86     if (MediaStreamInfoBarDelegate::Create(web_contents, request, callback))
87       NOTREACHED() << "Media stream not allowed for WebUI";
88   }
89
90  private:
91   DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate);
92 };
93
94 // static
95 StartPageService* StartPageService::Get(Profile* profile) {
96   return StartPageServiceFactory::GetForProfile(profile);
97 }
98
99 StartPageService::StartPageService(Profile* profile)
100     : profile_(profile),
101       profile_destroy_observer_(new ProfileDestroyObserver(this)),
102       recommended_apps_(new RecommendedApps(profile)),
103       state_(app_list::SPEECH_RECOGNITION_OFF),
104       speech_button_toggled_manually_(false),
105       speech_result_obtained_(false) {
106   if (app_list::switches::IsExperimentalAppListEnabled())
107     LoadContents();
108 }
109
110 StartPageService::~StartPageService() {}
111
112 void StartPageService::AddObserver(StartPageObserver* observer) {
113   observers_.AddObserver(observer);
114 }
115
116 void StartPageService::RemoveObserver(StartPageObserver* observer) {
117   observers_.RemoveObserver(observer);
118 }
119
120 void StartPageService::AppListShown() {
121   if (!contents_) {
122     LoadContents();
123   } else {
124     contents_->GetWebUI()->CallJavascriptFunction(
125         "appList.startPage.onAppListShown",
126         base::FundamentalValue(HotwordEnabled()));
127   }
128 }
129
130 void StartPageService::AppListHidden() {
131   contents_->GetWebUI()->CallJavascriptFunction(
132       "appList.startPage.onAppListHidden");
133   if (!app_list::switches::IsExperimentalAppListEnabled())
134     UnloadContents();
135 }
136
137 void StartPageService::ToggleSpeechRecognition() {
138   speech_button_toggled_manually_ = true;
139   contents_->GetWebUI()->CallJavascriptFunction(
140       "appList.startPage.toggleSpeechRecognition");
141 }
142
143 bool StartPageService::HotwordEnabled() {
144 #if defined(OS_CHROMEOS)
145   return HotwordServiceFactory::IsServiceAvailable(profile_) &&
146       profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled);
147 #else
148   return false;
149 #endif
150 }
151
152 content::WebContents* StartPageService::GetStartPageContents() {
153   return app_list::switches::IsExperimentalAppListEnabled() ? contents_.get()
154                                                             : NULL;
155 }
156
157 content::WebContents* StartPageService::GetSpeechRecognitionContents() {
158   if (app_list::switches::IsVoiceSearchEnabled()) {
159     if (!contents_)
160       LoadContents();
161     return contents_.get();
162   }
163   return NULL;
164 }
165
166 void StartPageService::OnSpeechResult(
167     const base::string16& query, bool is_final) {
168   if (is_final) {
169     speech_result_obtained_ = true;
170     RecordAction(UserMetricsAction("AppList_SearchedBySpeech"));
171   }
172   FOR_EACH_OBSERVER(StartPageObserver,
173                     observers_,
174                     OnSpeechResult(query, is_final));
175 }
176
177 void StartPageService::OnSpeechSoundLevelChanged(int16 level) {
178   FOR_EACH_OBSERVER(StartPageObserver,
179                     observers_,
180                     OnSpeechSoundLevelChanged(level));
181 }
182
183 void StartPageService::OnSpeechRecognitionStateChanged(
184     SpeechRecognitionState new_state) {
185   if (!InSpeechRecognition(state_) && InSpeechRecognition(new_state)) {
186     if (!speech_button_toggled_manually_ &&
187         state_ == SPEECH_RECOGNITION_HOTWORD_LISTENING) {
188       RecordAction(UserMetricsAction("AppList_HotwordRecognized"));
189     } else {
190       RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually"));
191     }
192   } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) &&
193              !speech_result_obtained_) {
194     RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled"));
195   }
196   speech_button_toggled_manually_ = false;
197   speech_result_obtained_ = false;
198   state_ = new_state;
199   FOR_EACH_OBSERVER(StartPageObserver,
200                     observers_,
201                     OnSpeechRecognitionStateChanged(new_state));
202 }
203
204 void StartPageService::Shutdown() {
205   UnloadContents();
206 }
207
208 void StartPageService::LoadContents() {
209   contents_.reset(content::WebContents::Create(
210       content::WebContents::CreateParams(profile_)));
211   contents_delegate_.reset(new StartPageWebContentsDelegate());
212   contents_->SetDelegate(contents_delegate_.get());
213
214   GURL url(chrome::kChromeUIAppListStartPageURL);
215   CommandLine* command_line = CommandLine::ForCurrentProcess();
216   if (command_line->HasSwitch(::switches::kAppListStartPageURL)) {
217     url = GURL(
218         command_line->GetSwitchValueASCII(::switches::kAppListStartPageURL));
219   }
220
221   contents_->GetController().LoadURL(
222       url,
223       content::Referrer(),
224       content::PAGE_TRANSITION_AUTO_TOPLEVEL,
225       std::string());
226 }
227
228 void StartPageService::UnloadContents() {
229   contents_.reset();
230 }
231
232 }  // namespace app_list