| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/extensions/echo_private_api.h" |
| |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "base/file_util.h" |
| #include "base/location.h" |
| #include "base/prefs/pref_registry_simple.h" |
| #include "base/prefs/pref_service.h" |
| #include "base/prefs/scoped_user_pref_update.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" |
| #include "chrome/browser/chromeos/settings/cros_settings.h" |
| #include "chrome/browser/chromeos/ui/echo_dialog_view.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_window.h" |
| #include "chrome/common/extensions/api/echo_private.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/pref_names.h" |
| #include "chromeos/system/statistics_provider.h" |
| #include "content/public/browser/browser_thread.h" |
| |
| namespace echo_api = extensions::api::echo_private; |
| |
| using content::BrowserThread; |
| |
| namespace { |
| |
| // URL of "More info" link shown in echo dialog in GetUserConsent function. |
| const char kMoreInfoLink[] = |
| "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html?" |
| "answer=2677280"; |
| |
| } // namespace |
| |
| namespace chromeos { |
| |
| namespace echo_offer { |
| |
| void RegisterPrefs(PrefRegistrySimple* registry) { |
| registry->RegisterDictionaryPref(prefs::kEchoCheckedOffers); |
| } |
| |
| } // namespace echo_offer |
| |
| } // namespace chromeos |
| |
| EchoPrivateGetRegistrationCodeFunction:: |
| EchoPrivateGetRegistrationCodeFunction() {} |
| |
| EchoPrivateGetRegistrationCodeFunction:: |
| ~EchoPrivateGetRegistrationCodeFunction() {} |
| |
| void EchoPrivateGetRegistrationCodeFunction::GetRegistrationCode( |
| const std::string& type) { |
| if (!chromeos::KioskModeSettings::Get()->is_initialized()) { |
| chromeos::KioskModeSettings::Get()->Initialize(base::Bind( |
| &EchoPrivateGetRegistrationCodeFunction::GetRegistrationCode, |
| this, type)); |
| return; |
| } |
| // Possible ECHO code type and corresponding key name in StatisticsProvider. |
| const std::string kCouponType = "COUPON_CODE"; |
| const std::string kGroupType = "GROUP_CODE"; |
| |
| chromeos::system::StatisticsProvider* provider = |
| chromeos::system::StatisticsProvider::GetInstance(); |
| std::string result; |
| if (!chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) { |
| // In Kiosk mode, we effectively disable the registration API |
| // by always returning an empty code. |
| if (type == kCouponType) { |
| provider->GetMachineStatistic(chromeos::system::kOffersCouponCodeKey, |
| &result); |
| } else if (type == kGroupType) { |
| provider->GetMachineStatistic(chromeos::system::kOffersGroupCodeKey, |
| &result); |
| } |
| } |
| |
| results_ = echo_api::GetRegistrationCode::Results::Create(result); |
| SendResponse(true); |
| } |
| |
| bool EchoPrivateGetRegistrationCodeFunction::RunImpl() { |
| scoped_ptr<echo_api::GetRegistrationCode::Params> params = |
| echo_api::GetRegistrationCode::Params::Create(*args_); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| GetRegistrationCode(params->type); |
| return true; |
| } |
| |
| EchoPrivateSetOfferInfoFunction::EchoPrivateSetOfferInfoFunction() {} |
| |
| EchoPrivateSetOfferInfoFunction::~EchoPrivateSetOfferInfoFunction() {} |
| |
| bool EchoPrivateSetOfferInfoFunction::RunImpl() { |
| scoped_ptr<echo_api::SetOfferInfo::Params> params = |
| echo_api::SetOfferInfo::Params::Create(*args_); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| const std::string& service_id = params->id; |
| base::DictionaryValue* dict = params->offer_info. |
| additional_properties.DeepCopyWithoutEmptyChildren(); |
| |
| PrefService* local_state = g_browser_process->local_state(); |
| DictionaryPrefUpdate offer_update(local_state, prefs::kEchoCheckedOffers); |
| offer_update->SetWithoutPathExpansion("echo." + service_id, dict); |
| return true; |
| } |
| |
| EchoPrivateGetOfferInfoFunction::EchoPrivateGetOfferInfoFunction() {} |
| |
| EchoPrivateGetOfferInfoFunction::~EchoPrivateGetOfferInfoFunction() {} |
| |
| bool EchoPrivateGetOfferInfoFunction::RunImpl() { |
| scoped_ptr<echo_api::GetOfferInfo::Params> params = |
| echo_api::GetOfferInfo::Params::Create(*args_); |
| EXTENSION_FUNCTION_VALIDATE(params); |
| |
| const std::string& service_id = params->id; |
| PrefService* local_state = g_browser_process->local_state(); |
| const base::DictionaryValue* offer_infos = local_state-> |
| GetDictionary(prefs::kEchoCheckedOffers); |
| |
| const base::DictionaryValue* offer_info = NULL; |
| if (!offer_infos->GetDictionaryWithoutPathExpansion( |
| "echo." + service_id, &offer_info)) { |
| error_ = "Not found"; |
| return false; |
| } |
| |
| echo_api::GetOfferInfo::Results::Result result; |
| result.additional_properties.MergeDictionary(offer_info); |
| results_ = echo_api::GetOfferInfo::Results::Create(result); |
| return true; |
| } |
| |
| EchoPrivateGetOobeTimestampFunction::EchoPrivateGetOobeTimestampFunction() { |
| } |
| |
| EchoPrivateGetOobeTimestampFunction::~EchoPrivateGetOobeTimestampFunction() { |
| } |
| |
| bool EchoPrivateGetOobeTimestampFunction::RunImpl() { |
| BrowserThread::PostTaskAndReplyWithResult( |
| BrowserThread::FILE, FROM_HERE, |
| base::Bind( |
| &EchoPrivateGetOobeTimestampFunction::GetOobeTimestampOnFileThread, |
| this), |
| base::Bind( |
| &EchoPrivateGetOobeTimestampFunction::SendResponse, this)); |
| return true; |
| } |
| |
| // Get the OOBE timestamp from file /home/chronos/.oobe_completed. |
| // The timestamp is used to determine when the user first activates the device. |
| // If we can get the timestamp info, return it as yyyy-mm-dd, otherwise, return |
| // an empty string. |
| bool EchoPrivateGetOobeTimestampFunction::GetOobeTimestampOnFileThread() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| |
| const char kOobeTimestampFile[] = "/home/chronos/.oobe_completed"; |
| std::string timestamp = ""; |
| base::PlatformFileInfo fileInfo; |
| if (file_util::GetFileInfo(base::FilePath(kOobeTimestampFile), &fileInfo)) { |
| base::Time::Exploded ctime; |
| fileInfo.creation_time.UTCExplode(&ctime); |
| timestamp += base::StringPrintf("%u-%u-%u", |
| ctime.year, |
| ctime.month, |
| ctime.day_of_month); |
| } |
| results_ = echo_api::GetOobeTimestamp::Results::Create(timestamp); |
| return true; |
| } |
| |
| EchoPrivateGetUserConsentFunction::EchoPrivateGetUserConsentFunction() |
| : redeem_offers_allowed_(false) { |
| } |
| |
| // static |
| scoped_refptr<EchoPrivateGetUserConsentFunction> |
| EchoPrivateGetUserConsentFunction::CreateForTest( |
| const DialogShownTestCallback& dialog_shown_callback) { |
| scoped_refptr<EchoPrivateGetUserConsentFunction> function( |
| new EchoPrivateGetUserConsentFunction()); |
| function->dialog_shown_callback_ = dialog_shown_callback; |
| return function; |
| } |
| |
| EchoPrivateGetUserConsentFunction::~EchoPrivateGetUserConsentFunction() {} |
| |
| bool EchoPrivateGetUserConsentFunction::RunImpl() { |
| CheckRedeemOffersAllowed(); |
| return true; |
| } |
| |
| void EchoPrivateGetUserConsentFunction::OnAccept() { |
| Finalize(true); |
| } |
| |
| void EchoPrivateGetUserConsentFunction::OnCancel() { |
| Finalize(false); |
| } |
| |
| void EchoPrivateGetUserConsentFunction::OnMoreInfoLinkClicked() { |
| chrome::NavigateParams params( |
| GetProfile(), GURL(kMoreInfoLink), content::PAGE_TRANSITION_LINK); |
| // Open the link in a new window. The echo dialog is modal, so the current |
| // window is useless until the dialog is closed. |
| params.disposition = NEW_WINDOW; |
| chrome::Navigate(¶ms); |
| } |
| |
| void EchoPrivateGetUserConsentFunction::CheckRedeemOffersAllowed() { |
| chromeos::CrosSettingsProvider::TrustedStatus status = |
| chromeos::CrosSettings::Get()->PrepareTrustedValues(base::Bind( |
| &EchoPrivateGetUserConsentFunction::CheckRedeemOffersAllowed, |
| this)); |
| if (status == chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED) |
| return; |
| |
| bool allow = true; |
| chromeos::CrosSettings::Get()->GetBoolean( |
| chromeos::kAllowRedeemChromeOsRegistrationOffers, &allow); |
| |
| OnRedeemOffersAllowedChecked(allow); |
| } |
| |
| void EchoPrivateGetUserConsentFunction::OnRedeemOffersAllowedChecked( |
| bool is_allowed) { |
| redeem_offers_allowed_ = is_allowed; |
| |
| scoped_ptr<echo_api::GetUserConsent::Params> params = |
| echo_api::GetUserConsent::Params::Create(*args_); |
| |
| // Verify that the passed origin URL is valid. |
| GURL service_origin = GURL(params->consent_requester.origin); |
| if (!service_origin.is_valid()) { |
| error_ = "Invalid origin."; |
| SendResponse(false); |
| return; |
| } |
| |
| // Add ref to ensure the function stays around until the dialog listener is |
| // called. The reference is release in |Finalize|. |
| AddRef(); |
| |
| // Create and show the dialog. |
| chromeos::EchoDialogView* dialog = new chromeos::EchoDialogView(this); |
| if (redeem_offers_allowed_) { |
| dialog->InitForEnabledEcho( |
| UTF8ToUTF16(params->consent_requester.service_name), |
| UTF8ToUTF16(params->consent_requester.origin)); |
| } else { |
| dialog->InitForDisabledEcho(); |
| } |
| dialog->Show(GetCurrentBrowser()->window()->GetNativeWindow()); |
| |
| // If there is a dialog_shown_callback_, invoke it with the created dialog. |
| if (!dialog_shown_callback_.is_null()) |
| dialog_shown_callback_.Run(dialog); |
| } |
| |
| void EchoPrivateGetUserConsentFunction::Finalize(bool consent) { |
| // Consent should not be true if offers redeeming is disabled. |
| CHECK(redeem_offers_allowed_ || !consent); |
| results_ = echo_api::GetUserConsent::Results::Create(consent); |
| SendResponse(true); |
| |
| // Release the reference added in |OnRedeemOffersAllowedChecked|, before |
| // showing the dialog. |
| Release(); |
| } |