1 // Copyright (c) 2012 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/chromeos/extensions/echo_private_api.h"
10 #include "base/files/file_util.h"
11 #include "base/location.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/scoped_user_pref_update.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/time/time.h"
18 #include "base/values.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
21 #include "chrome/browser/chromeos/settings/cros_settings.h"
22 #include "chrome/browser/chromeos/ui/echo_dialog_view.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_window.h"
25 #include "chrome/common/extensions/api/echo_private.h"
26 #include "chrome/common/pref_names.h"
27 #include "chromeos/system/statistics_provider.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "extensions/common/extension.h"
31 namespace echo_api
= extensions::api::echo_private
;
33 using content::BrowserThread
;
37 // URL of "More info" link shown in echo dialog in GetUserConsent function.
38 const char kMoreInfoLink
[] =
39 "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html?"
46 namespace echo_offer
{
48 void RegisterPrefs(PrefRegistrySimple
* registry
) {
49 registry
->RegisterDictionaryPref(prefs::kEchoCheckedOffers
);
52 } // namespace echo_offer
54 } // namespace chromeos
56 EchoPrivateGetRegistrationCodeFunction::
57 EchoPrivateGetRegistrationCodeFunction() {}
59 EchoPrivateGetRegistrationCodeFunction::
60 ~EchoPrivateGetRegistrationCodeFunction() {}
62 void EchoPrivateGetRegistrationCodeFunction::GetRegistrationCode(
63 const std::string
& type
) {
64 if (!chromeos::KioskModeSettings::Get()->is_initialized()) {
65 chromeos::KioskModeSettings::Get()->Initialize(base::Bind(
66 &EchoPrivateGetRegistrationCodeFunction::GetRegistrationCode
,
70 // Possible ECHO code type and corresponding key name in StatisticsProvider.
71 const std::string kCouponType
= "COUPON_CODE";
72 const std::string kGroupType
= "GROUP_CODE";
74 chromeos::system::StatisticsProvider
* provider
=
75 chromeos::system::StatisticsProvider::GetInstance();
77 if (!chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) {
78 // In Kiosk mode, we effectively disable the registration API
79 // by always returning an empty code.
80 if (type
== kCouponType
) {
81 provider
->GetMachineStatistic(chromeos::system::kOffersCouponCodeKey
,
83 } else if (type
== kGroupType
) {
84 provider
->GetMachineStatistic(chromeos::system::kOffersGroupCodeKey
,
89 results_
= echo_api::GetRegistrationCode::Results::Create(result
);
93 bool EchoPrivateGetRegistrationCodeFunction::RunSync() {
94 scoped_ptr
<echo_api::GetRegistrationCode::Params
> params
=
95 echo_api::GetRegistrationCode::Params::Create(*args_
);
96 EXTENSION_FUNCTION_VALIDATE(params
);
97 GetRegistrationCode(params
->type
);
101 EchoPrivateSetOfferInfoFunction::EchoPrivateSetOfferInfoFunction() {}
103 EchoPrivateSetOfferInfoFunction::~EchoPrivateSetOfferInfoFunction() {}
105 bool EchoPrivateSetOfferInfoFunction::RunSync() {
106 scoped_ptr
<echo_api::SetOfferInfo::Params
> params
=
107 echo_api::SetOfferInfo::Params::Create(*args_
);
108 EXTENSION_FUNCTION_VALIDATE(params
);
110 const std::string
& service_id
= params
->id
;
111 base::DictionaryValue
* dict
= params
->offer_info
.
112 additional_properties
.DeepCopyWithoutEmptyChildren();
114 PrefService
* local_state
= g_browser_process
->local_state();
115 DictionaryPrefUpdate
offer_update(local_state
, prefs::kEchoCheckedOffers
);
116 offer_update
->SetWithoutPathExpansion("echo." + service_id
, dict
);
120 EchoPrivateGetOfferInfoFunction::EchoPrivateGetOfferInfoFunction() {}
122 EchoPrivateGetOfferInfoFunction::~EchoPrivateGetOfferInfoFunction() {}
124 bool EchoPrivateGetOfferInfoFunction::RunSync() {
125 scoped_ptr
<echo_api::GetOfferInfo::Params
> params
=
126 echo_api::GetOfferInfo::Params::Create(*args_
);
127 EXTENSION_FUNCTION_VALIDATE(params
);
129 const std::string
& service_id
= params
->id
;
130 PrefService
* local_state
= g_browser_process
->local_state();
131 const base::DictionaryValue
* offer_infos
= local_state
->
132 GetDictionary(prefs::kEchoCheckedOffers
);
134 const base::DictionaryValue
* offer_info
= NULL
;
135 if (!offer_infos
->GetDictionaryWithoutPathExpansion(
136 "echo." + service_id
, &offer_info
)) {
137 error_
= "Not found";
141 echo_api::GetOfferInfo::Results::Result result
;
142 result
.additional_properties
.MergeDictionary(offer_info
);
143 results_
= echo_api::GetOfferInfo::Results::Create(result
);
147 EchoPrivateGetOobeTimestampFunction::EchoPrivateGetOobeTimestampFunction() {
150 EchoPrivateGetOobeTimestampFunction::~EchoPrivateGetOobeTimestampFunction() {
153 bool EchoPrivateGetOobeTimestampFunction::RunAsync() {
154 BrowserThread::PostTaskAndReplyWithResult(
155 BrowserThread::FILE, FROM_HERE
,
157 &EchoPrivateGetOobeTimestampFunction::GetOobeTimestampOnFileThread
,
160 &EchoPrivateGetOobeTimestampFunction::SendResponse
, this));
164 // Get the OOBE timestamp from file /home/chronos/.oobe_completed.
165 // The timestamp is used to determine when the user first activates the device.
166 // If we can get the timestamp info, return it as yyyy-mm-dd, otherwise, return
168 bool EchoPrivateGetOobeTimestampFunction::GetOobeTimestampOnFileThread() {
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
171 const char kOobeTimestampFile
[] = "/home/chronos/.oobe_completed";
172 std::string timestamp
= "";
173 base::File::Info fileInfo
;
174 if (base::GetFileInfo(base::FilePath(kOobeTimestampFile
), &fileInfo
)) {
175 base::Time::Exploded ctime
;
176 fileInfo
.creation_time
.UTCExplode(&ctime
);
177 timestamp
+= base::StringPrintf("%u-%u-%u",
182 results_
= echo_api::GetOobeTimestamp::Results::Create(timestamp
);
186 EchoPrivateGetUserConsentFunction::EchoPrivateGetUserConsentFunction()
187 : redeem_offers_allowed_(false) {
191 scoped_refptr
<EchoPrivateGetUserConsentFunction
>
192 EchoPrivateGetUserConsentFunction::CreateForTest(
193 const DialogShownTestCallback
& dialog_shown_callback
) {
194 scoped_refptr
<EchoPrivateGetUserConsentFunction
> function(
195 new EchoPrivateGetUserConsentFunction());
196 function
->dialog_shown_callback_
= dialog_shown_callback
;
200 EchoPrivateGetUserConsentFunction::~EchoPrivateGetUserConsentFunction() {}
202 bool EchoPrivateGetUserConsentFunction::RunAsync() {
203 CheckRedeemOffersAllowed();
207 void EchoPrivateGetUserConsentFunction::OnAccept() {
211 void EchoPrivateGetUserConsentFunction::OnCancel() {
215 void EchoPrivateGetUserConsentFunction::OnMoreInfoLinkClicked() {
216 chrome::NavigateParams
params(
217 GetProfile(), GURL(kMoreInfoLink
), ui::PAGE_TRANSITION_LINK
);
218 // Open the link in a new window. The echo dialog is modal, so the current
219 // window is useless until the dialog is closed.
220 params
.disposition
= NEW_WINDOW
;
221 chrome::Navigate(¶ms
);
224 void EchoPrivateGetUserConsentFunction::CheckRedeemOffersAllowed() {
225 chromeos::CrosSettingsProvider::TrustedStatus status
=
226 chromeos::CrosSettings::Get()->PrepareTrustedValues(base::Bind(
227 &EchoPrivateGetUserConsentFunction::CheckRedeemOffersAllowed
,
229 if (status
== chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED
)
233 chromeos::CrosSettings::Get()->GetBoolean(
234 chromeos::kAllowRedeemChromeOsRegistrationOffers
, &allow
);
236 OnRedeemOffersAllowedChecked(allow
);
239 void EchoPrivateGetUserConsentFunction::OnRedeemOffersAllowedChecked(
241 redeem_offers_allowed_
= is_allowed
;
243 scoped_ptr
<echo_api::GetUserConsent::Params
> params
=
244 echo_api::GetUserConsent::Params::Create(*args_
);
246 // Verify that the passed origin URL is valid.
247 GURL service_origin
= GURL(params
->consent_requester
.origin
);
248 if (!service_origin
.is_valid()) {
249 error_
= "Invalid origin.";
254 // Add ref to ensure the function stays around until the dialog listener is
255 // called. The reference is release in |Finalize|.
258 // Create and show the dialog.
259 chromeos::EchoDialogView
* dialog
= new chromeos::EchoDialogView(this);
260 if (redeem_offers_allowed_
) {
261 dialog
->InitForEnabledEcho(
262 base::UTF8ToUTF16(params
->consent_requester
.service_name
),
263 base::UTF8ToUTF16(params
->consent_requester
.origin
));
265 dialog
->InitForDisabledEcho();
267 dialog
->Show(GetCurrentBrowser()->window()->GetNativeWindow());
269 // If there is a dialog_shown_callback_, invoke it with the created dialog.
270 if (!dialog_shown_callback_
.is_null())
271 dialog_shown_callback_
.Run(dialog
);
274 void EchoPrivateGetUserConsentFunction::Finalize(bool consent
) {
275 // Consent should not be true if offers redeeming is disabled.
276 CHECK(redeem_offers_allowed_
|| !consent
);
277 results_
= echo_api::GetUserConsent::Results::Create(consent
);
280 // Release the reference added in |OnRedeemOffersAllowedChecked|, before
281 // showing the dialog.