Upstream version 5.34.104.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 "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"
31
32 using base::RecordAction;
33 using base::UserMetricsAction;
34
35 namespace app_list {
36
37 namespace {
38
39 bool InSpeechRecognition(SpeechRecognitionState state) {
40   return state == SPEECH_RECOGNITION_RECOGNIZING ||
41       state == SPEECH_RECOGNITION_IN_SPEECH;
42 }
43
44 }
45
46 class StartPageService::ProfileDestroyObserver
47     : public content::NotificationObserver {
48  public:
49   explicit ProfileDestroyObserver(StartPageService* service)
50       : service_(service) {
51     registrar_.Add(this,
52                    chrome::NOTIFICATION_PROFILE_DESTROYED,
53                    content::Source<Profile>(service_->profile()));
54   }
55   virtual ~ProfileDestroyObserver() {}
56
57  private:
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());
64     service_->Shutdown();
65   }
66
67   StartPageService* service_;  // Owner of this class.
68   content::NotificationRegistrar registrar_;
69
70   DISALLOW_COPY_AND_ASSIGN(ProfileDestroyObserver);
71 };
72
73 class StartPageService::StartPageWebContentsDelegate
74     : public content::WebContentsDelegate {
75  public:
76   StartPageWebContentsDelegate() {}
77   virtual ~StartPageWebContentsDelegate() {}
78
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";
85   }
86
87  private:
88   DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate);
89 };
90
91 // static
92 StartPageService* StartPageService::Get(Profile* profile) {
93   return StartPageServiceFactory::GetForProfile(profile);
94 }
95
96 StartPageService::StartPageService(Profile* profile)
97     : 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;
109 #endif
110
111   contents_.reset(content::WebContents::Create(
112       content::WebContents::CreateParams(profile_)));
113   contents_delegate_.reset(new StartPageWebContentsDelegate());
114   contents_->SetDelegate(contents_delegate_.get());
115
116   GURL url(chrome::kChromeUIAppListStartPageURL);
117   CommandLine* command_line = CommandLine::ForCurrentProcess();
118   if (command_line->HasSwitch(::switches::kAppListStartPageURL)) {
119     url = GURL(
120         command_line->GetSwitchValueASCII(::switches::kAppListStartPageURL));
121   }
122
123   contents_->GetController().LoadURL(
124       url,
125       content::Referrer(),
126       content::PAGE_TRANSITION_AUTO_TOPLEVEL,
127       std::string());
128 }
129
130 StartPageService::~StartPageService() {}
131
132 void StartPageService::AddObserver(StartPageObserver* observer) {
133   observers_.AddObserver(observer);
134 }
135
136 void StartPageService::RemoveObserver(StartPageObserver* observer) {
137   observers_.RemoveObserver(observer);
138 }
139
140 void StartPageService::ToggleSpeechRecognition() {
141   speech_button_toggled_manually_ = true;
142   contents_->GetWebUI()->CallJavascriptFunction(
143       "appList.startPage.toggleSpeechRecognition");
144 }
145
146 content::WebContents* StartPageService::GetStartPageContents() {
147   return CommandLine::ForCurrentProcess()->HasSwitch(
148       ::switches::kShowAppListStartPage) ? contents_.get() : NULL;
149 }
150
151 content::WebContents* StartPageService::GetSpeechRecognitionContents() {
152   return app_list::switches::IsVoiceSearchEnabled() ? contents_.get() : NULL;
153 }
154
155 void StartPageService::OnSpeechResult(
156     const base::string16& query, bool is_final) {
157   if (is_final) {
158     speech_result_obtained_ = true;
159     RecordAction(UserMetricsAction("AppList_SearchedBySpeech"));
160   }
161   FOR_EACH_OBSERVER(StartPageObserver,
162                     observers_,
163                     OnSpeechResult(query, is_final));
164 }
165
166 void StartPageService::OnSpeechSoundLevelChanged(int16 level) {
167   FOR_EACH_OBSERVER(StartPageObserver,
168                     observers_,
169                     OnSpeechSoundLevelChanged(level));
170 }
171
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"));
178     } else {
179       RecordAction(UserMetricsAction("AppList_VoiceSearchStartedManually"));
180     }
181   } else if (InSpeechRecognition(state_) && !InSpeechRecognition(new_state) &&
182              !speech_result_obtained_) {
183     RecordAction(UserMetricsAction("AppList_VoiceSearchCanceled"));
184   }
185   speech_button_toggled_manually_ = false;
186   speech_result_obtained_ = false;
187   state_ = new_state;
188   FOR_EACH_OBSERVER(StartPageObserver,
189                     observers_,
190                     OnSpeechRecognitionStateChanged(new_state));
191 }
192
193 void StartPageService::Shutdown() {
194   contents_.reset();
195 }
196
197 }  // namespace app_list