1 // Copyright 2015 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/extensions/api/search_engines_private/search_engines_private_api.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/extensions/chrome_extension_function.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/search/hotword_audio_history_handler.h"
13 #include "chrome/browser/search/hotword_service.h"
14 #include "chrome/browser/search/hotword_service_factory.h"
15 #include "chrome/browser/search_engines/template_url_service_factory.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "components/search_engines/template_url_service.h"
21 #include "components/signin/core/browser/signin_manager.h"
22 #include "components/signin/core/browser/signin_manager_base.h"
23 #include "extensions/browser/extension_function_registry.h"
24 #include "ui/base/l10n/l10n_util.h"
26 namespace extensions
{
28 namespace search_engines_private
= api::search_engines_private
;
30 const char kHotwordServiceMissing
[] = "Cannot retrieve hotword service";
31 const char kRetrainWithoutAlwaysOnEnabledError
[] =
32 "Cannot retrain without always search and audio logging enabled";
33 const char kOptInWithAudioLoggingError
[] =
34 "Cannot opt in with audio logging but also with always on enabled";
35 const char kAlreadyOptedInError
[] = "Cannot opt in if already opted in";
37 ////////////////////////////////////////////////////////////////////////////////
38 // SearchEnginesPrivateGetSearchEnginesFunction
40 SearchEnginesPrivateGetSearchEnginesFunction::
41 SearchEnginesPrivateGetSearchEnginesFunction()
42 : chrome_details_(this) {
45 SearchEnginesPrivateGetSearchEnginesFunction::
46 ~SearchEnginesPrivateGetSearchEnginesFunction() {
49 ExtensionFunction::ResponseAction
50 SearchEnginesPrivateGetSearchEnginesFunction::Run() {
51 TemplateURLService
* template_url_service
=
52 TemplateURLServiceFactory::GetForProfile(chrome_details_
.GetProfile());
53 base::ListValue
* engines
= new base::ListValue();
55 const TemplateURL
* default_url
=
56 template_url_service
->GetDefaultSearchProvider();
57 std::vector
<TemplateURL
*> urls
= template_url_service
->GetTemplateURLs();
58 for (size_t i
= 0; i
< urls
.size(); i
++) {
59 search_engines_private::SearchEngine engine
;
60 engine
.guid
= urls
[i
]->sync_guid();
61 engine
.name
= base::UTF16ToUTF8(urls
[i
]->short_name());
62 engine
.keyword
= base::UTF16ToUTF8(urls
[i
]->keyword());
63 engine
.url
= urls
[i
]->url();
64 engine
.type
= urls
[i
]->show_in_default_list()
65 ? search_engines_private::SearchEngineType::SEARCH_ENGINE_TYPE_DEFAULT
66 : search_engines_private::SearchEngineType::SEARCH_ENGINE_TYPE_OTHER
;
68 if (urls
[i
] == default_url
)
69 engine
.is_selected
= scoped_ptr
<bool>(new bool(true));
71 engines
->Append(engine
.ToValue().release());
74 return RespondNow(OneArgument(engines
));
77 ////////////////////////////////////////////////////////////////////////////////
78 // SearchEnginesPrivateSetSelectedSearchEngineFunction
80 SearchEnginesPrivateSetSelectedSearchEngineFunction::
81 SearchEnginesPrivateSetSelectedSearchEngineFunction()
82 : chrome_details_(this) {
85 SearchEnginesPrivateSetSelectedSearchEngineFunction::
86 ~SearchEnginesPrivateSetSelectedSearchEngineFunction() {
89 ExtensionFunction::ResponseAction
90 SearchEnginesPrivateSetSelectedSearchEngineFunction::Run() {
91 scoped_ptr
<search_engines_private::SetSelectedSearchEngine::Params
>
93 search_engines_private::SetSelectedSearchEngine::Params::Create(
95 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
97 TemplateURLService
* template_url_service
=
98 TemplateURLServiceFactory::GetForProfile(chrome_details_
.GetProfile());
99 template_url_service
->SetUserSelectedDefaultSearchProvider(
100 template_url_service
->GetTemplateURLForGUID(parameters
->guid
));
101 return RespondNow(NoArguments());
104 ////////////////////////////////////////////////////////////////////////////////
105 // SearchEnginesPrivateAddOtherSearchEngineFunction
107 SearchEnginesPrivateAddOtherSearchEngineFunction::
108 SearchEnginesPrivateAddOtherSearchEngineFunction()
109 : chrome_details_(this) {
112 SearchEnginesPrivateAddOtherSearchEngineFunction::
113 ~SearchEnginesPrivateAddOtherSearchEngineFunction() {
116 ExtensionFunction::ResponseAction
117 SearchEnginesPrivateAddOtherSearchEngineFunction::Run() {
118 scoped_ptr
<search_engines_private::AddOtherSearchEngine::Params
> parameters
=
119 search_engines_private::AddOtherSearchEngine::Params::Create(*args_
);
120 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
122 TemplateURLData data
;
123 data
.SetShortName(base::UTF8ToUTF16(parameters
->name
));
124 data
.SetKeyword(base::UTF8ToUTF16(parameters
->keyword
));
125 data
.SetURL(parameters
->url
);
126 TemplateURL
* turl
= new TemplateURL(data
);
128 TemplateURLService
* template_url_service
=
129 TemplateURLServiceFactory::GetForProfile(chrome_details_
.GetProfile());
130 template_url_service
->Add(turl
);
131 return RespondNow(NoArguments());
134 ////////////////////////////////////////////////////////////////////////////////
135 // SearchEnginesPrivateUpdateSearchEngineFunction
137 SearchEnginesPrivateUpdateSearchEngineFunction::
138 SearchEnginesPrivateUpdateSearchEngineFunction()
139 : chrome_details_(this) {
142 SearchEnginesPrivateUpdateSearchEngineFunction::
143 ~SearchEnginesPrivateUpdateSearchEngineFunction() {
146 ExtensionFunction::ResponseAction
147 SearchEnginesPrivateUpdateSearchEngineFunction::Run() {
148 scoped_ptr
<search_engines_private::UpdateSearchEngine::Params
> parameters
=
149 search_engines_private::UpdateSearchEngine::Params::Create(*args_
);
150 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
152 TemplateURLService
* template_url_service
=
153 TemplateURLServiceFactory::GetForProfile(chrome_details_
.GetProfile());
155 template_url_service
->GetTemplateURLForGUID(parameters
->guid
);
157 template_url_service
->ResetTemplateURL(
158 turl
, base::UTF8ToUTF16(parameters
->name
),
159 base::UTF8ToUTF16(parameters
->keyword
), parameters
->url
);
161 return RespondNow(NoArguments());
164 ////////////////////////////////////////////////////////////////////////////////
165 // SearchEnginesPrivateRemoveSearchEngineFunction
167 SearchEnginesPrivateRemoveSearchEngineFunction::
168 SearchEnginesPrivateRemoveSearchEngineFunction()
169 : chrome_details_(this) {
172 SearchEnginesPrivateRemoveSearchEngineFunction::
173 ~SearchEnginesPrivateRemoveSearchEngineFunction() {
176 ExtensionFunction::ResponseAction
177 SearchEnginesPrivateRemoveSearchEngineFunction::Run() {
178 scoped_ptr
<search_engines_private::RemoveSearchEngine::Params
> parameters
=
179 search_engines_private::RemoveSearchEngine::Params::Create(*args_
);
180 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
182 TemplateURLService
* template_url_service
=
183 TemplateURLServiceFactory::GetForProfile(chrome_details_
.GetProfile());
185 template_url_service
->GetTemplateURLForGUID(parameters
->guid
);
186 template_url_service
->Remove(turl
);
187 return RespondNow(NoArguments());
190 ////////////////////////////////////////////////////////////////////////////////
191 // SearchEnginesPrivateGetHotwordStateFunction
193 SearchEnginesPrivateGetHotwordStateFunction::
194 SearchEnginesPrivateGetHotwordStateFunction()
195 : chrome_details_(this), weak_ptr_factory_(this) {
198 SearchEnginesPrivateGetHotwordStateFunction::
199 ~SearchEnginesPrivateGetHotwordStateFunction() {
202 ExtensionFunction::ResponseAction
203 SearchEnginesPrivateGetHotwordStateFunction::Run() {
204 Profile
* profile
= chrome_details_
.GetProfile();
205 TemplateURLService
* template_url_service
=
206 TemplateURLServiceFactory::GetForProfile(profile
);
208 scoped_ptr
<search_engines_private::HotwordState
> state(
209 new search_engines_private::HotwordState());
211 if (template_url_service
&& template_url_service
->loaded()) {
212 const TemplateURL
* default_url
=
213 template_url_service
->GetDefaultSearchProvider();
215 !default_url
->HasGoogleBaseURLs(
216 template_url_service
->search_terms_data()) ||
217 !HotwordServiceFactory::IsHotwordAllowed(profile
)) {
218 return RespondNow(OneArgument(state
->ToValue().release()));
222 state
->availability
.push_back(
223 search_engines_private::HotwordFeature::HOTWORD_FEATURE_SEARCH
);
225 SigninManagerBase
* signin
= SigninManagerFactory::GetForProfile(profile
);
226 bool authenticated
= signin
&& signin
->IsAuthenticated();
228 HotwordServiceFactory::IsAlwaysOnAvailable() && authenticated
;
231 state
->availability
.push_back(
232 search_engines_private::HotwordFeature::HOTWORD_FEATURE_ALWAYS_ON
);
233 if (profile
->GetPrefs()->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled
)) {
234 state
->availability
.push_back(
235 search_engines_private::HotwordFeature::HOTWORD_FEATURE_RETRAIN_LINK
);
239 int error
= HotwordServiceFactory::GetCurrentError(profile
);
241 std::string
error_message(l10n_util::GetStringUTF8(error
));
242 if (error
== IDS_HOTWORD_GENERIC_ERROR_MESSAGE
) {
243 error_message
= l10n_util::GetStringFUTF8(
244 error
, base::UTF8ToUTF16(chrome::kHotwordLearnMoreURL
));
246 state
->error_msg
.reset(new std::string(error_message
));
249 // Audio history should be displayed if it's enabled regardless of the
250 // hotword error state if the user is signed in. If the user is not signed
251 // in, audio history is meaningless. This is only displayed if always-on
252 // hotwording is available.
253 if (authenticated
&& always_on
) {
254 std::string user_display_name
= signin
->GetAuthenticatedAccountInfo().email
;
255 HotwordService
* hotword_service
=
256 HotwordServiceFactory::GetForProfile(profile
);
257 if (hotword_service
) {
258 hotword_service
->GetAudioHistoryHandler()->GetAudioHistoryEnabled(
259 base::Bind(&SearchEnginesPrivateGetHotwordStateFunction::
260 OnAudioHistoryChecked
,
261 weak_ptr_factory_
.GetWeakPtr(), base::Passed(&state
),
262 l10n_util::GetStringFUTF16(
263 IDS_HOTWORD_AUDIO_HISTORY_ENABLED
,
264 base::UTF8ToUTF16(user_display_name
))));
265 return RespondLater();
269 return RespondNow(OneArgument(state
->ToValue().release()));
272 void SearchEnginesPrivateGetHotwordStateFunction::OnAudioHistoryChecked(
273 scoped_ptr
<search_engines_private::HotwordState
> state
,
274 const base::string16
& audio_history_state
,
276 bool logging_enabled
) {
277 if (success
&& logging_enabled
) {
278 state
->availability
.push_back(
279 search_engines_private::HotwordFeature::HOTWORD_FEATURE_AUDIO_HISTORY
);
280 state
->audio_history_state
.reset(new std::string(
281 base::UTF16ToUTF8(audio_history_state
)));
283 Respond(OneArgument(state
->ToValue().release()));
286 ////////////////////////////////////////////////////////////////////////////////
287 // SearchEnginesPrivateOptIntoHotwordingFunction
289 SearchEnginesPrivateOptIntoHotwordingFunction::
290 SearchEnginesPrivateOptIntoHotwordingFunction()
291 : chrome_details_(this) {
294 SearchEnginesPrivateOptIntoHotwordingFunction::
295 ~SearchEnginesPrivateOptIntoHotwordingFunction() {
298 ExtensionFunction::ResponseAction
299 SearchEnginesPrivateOptIntoHotwordingFunction::Run() {
300 scoped_ptr
<search_engines_private::OptIntoHotwording::Params
> parameters
=
301 search_engines_private::OptIntoHotwording::Params::Create(*args_
);
302 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
304 Profile
* profile
= chrome_details_
.GetProfile();
306 HotwordService::LaunchMode launch_mode
=
307 HotwordService::HOTWORD_AND_AUDIO_HISTORY
;
309 PrefService
* prefs
= profile
->GetPrefs();
311 HotwordService
* hotword_service
=
312 HotwordServiceFactory::GetForProfile(profile
);
313 if (!hotword_service
)
314 return RespondNow(Error(kHotwordServiceMissing
));
316 if (parameters
->retrain
) {
317 if (!prefs
->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled
) ||
318 !prefs
->GetBoolean(prefs::kHotwordAudioLoggingEnabled
)) {
319 return RespondNow(Error(kRetrainWithoutAlwaysOnEnabledError
));
322 launch_mode
= HotwordService::RETRAIN
;
323 } else if (prefs
->GetBoolean(prefs::kHotwordAudioLoggingEnabled
)) {
324 if (prefs
->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled
)) {
325 return RespondNow(Error(kOptInWithAudioLoggingError
));
328 launch_mode
= HotwordService::HOTWORD_ONLY
;
330 if (prefs
->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled
))
331 return RespondNow(Error(kAlreadyOptedInError
));
334 hotword_service
->OptIntoHotwording(launch_mode
);
335 return RespondNow(NoArguments());
338 } // namespace extensions