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. 4 5 #include "chrome/browser/chromeos/extensions/echo_private_api.h" 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/file_util.h" 11 #include "base/location.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "base/time/time.h" 15 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" 16 #include "chrome/browser/chromeos/settings/cros_settings.h" 17 #include "chrome/browser/chromeos/system/statistics_provider.h" 18 #include "chrome/browser/chromeos/ui/echo_dialog_view.h" 19 #include "chrome/browser/ui/browser.h" 20 #include "chrome/browser/ui/browser_window.h" 21 #include "chrome/common/extensions/api/echo_private.h" 22 #include "chrome/common/extensions/extension.h" 23 #include "content/public/browser/browser_thread.h" 24 25 namespace echo_api = extensions::api::echo_private; 26 27 using content::BrowserThread; 28 29 namespace { 30 31 // URL of "More info" link shown in echo dialog in GetUserConsent function. 32 const char kMoreInfoLink[] = 33 "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html?" 34 "answer=2677280"; 35 36 } // namespace 37 38 EchoPrivateGetRegistrationCodeFunction:: 39 EchoPrivateGetRegistrationCodeFunction() {} 40 41 EchoPrivateGetRegistrationCodeFunction:: 42 ~EchoPrivateGetRegistrationCodeFunction() {} 43 44 void EchoPrivateGetRegistrationCodeFunction::GetRegistrationCode( 45 const std::string& type) { 46 if (!chromeos::KioskModeSettings::Get()->is_initialized()) { 47 chromeos::KioskModeSettings::Get()->Initialize(base::Bind( 48 &EchoPrivateGetRegistrationCodeFunction::GetRegistrationCode, 49 this, type)); 50 return; 51 } 52 // Possible ECHO code type and corresponding key name in StatisticsProvider. 53 const std::string kCouponType = "COUPON_CODE"; 54 const std::string kGroupType = "GROUP_CODE"; 55 56 chromeos::system::StatisticsProvider* provider = 57 chromeos::system::StatisticsProvider::GetInstance(); 58 std::string result; 59 if (!chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) { 60 // In Kiosk mode, we effectively disable the registration API 61 // by always returning an empty code. 62 if (type == kCouponType) { 63 provider->GetMachineStatistic(chromeos::system::kOffersCouponCodeKey, 64 &result); 65 } else if (type == kGroupType) { 66 provider->GetMachineStatistic(chromeos::system::kOffersGroupCodeKey, 67 &result); 68 } 69 } 70 71 results_ = echo_api::GetRegistrationCode::Results::Create(result); 72 SendResponse(true); 73 } 74 75 bool EchoPrivateGetRegistrationCodeFunction::RunImpl() { 76 scoped_ptr<echo_api::GetRegistrationCode::Params> params = 77 echo_api::GetRegistrationCode::Params::Create(*args_); 78 EXTENSION_FUNCTION_VALIDATE(params); 79 GetRegistrationCode(params->type); 80 return true; 81 } 82 83 EchoPrivateGetOobeTimestampFunction::EchoPrivateGetOobeTimestampFunction() { 84 } 85 86 EchoPrivateGetOobeTimestampFunction::~EchoPrivateGetOobeTimestampFunction() { 87 } 88 89 bool EchoPrivateGetOobeTimestampFunction::RunImpl() { 90 BrowserThread::PostTaskAndReplyWithResult( 91 BrowserThread::FILE, FROM_HERE, 92 base::Bind( 93 &EchoPrivateGetOobeTimestampFunction::GetOobeTimestampOnFileThread, 94 this), 95 base::Bind( 96 &EchoPrivateGetOobeTimestampFunction::SendResponse, this)); 97 return true; 98 } 99 100 // Get the OOBE timestamp from file /home/chronos/.oobe_completed. 101 // The timestamp is used to determine when the user first activates the device. 102 // If we can get the timestamp info, return it as yyyy-mm-dd, otherwise, return 103 // an empty string. 104 bool EchoPrivateGetOobeTimestampFunction::GetOobeTimestampOnFileThread() { 105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 106 107 const char kOobeTimestampFile[] = "/home/chronos/.oobe_completed"; 108 std::string timestamp = ""; 109 base::PlatformFileInfo fileInfo; 110 if (file_util::GetFileInfo(base::FilePath(kOobeTimestampFile), &fileInfo)) { 111 base::Time::Exploded ctime; 112 fileInfo.creation_time.UTCExplode(&ctime); 113 timestamp += base::StringPrintf("%u-%u-%u", 114 ctime.year, 115 ctime.month, 116 ctime.day_of_month); 117 } 118 results_ = echo_api::GetOobeTimestamp::Results::Create(timestamp); 119 return true; 120 } 121 122 EchoPrivateCheckAllowRedeemOffersFunction:: 123 EchoPrivateCheckAllowRedeemOffersFunction() { 124 } 125 126 EchoPrivateCheckAllowRedeemOffersFunction:: 127 ~EchoPrivateCheckAllowRedeemOffersFunction() { 128 } 129 130 void EchoPrivateCheckAllowRedeemOffersFunction::CheckAllowRedeemOffers() { 131 chromeos::CrosSettingsProvider::TrustedStatus status = 132 chromeos::CrosSettings::Get()->PrepareTrustedValues(base::Bind( 133 &EchoPrivateCheckAllowRedeemOffersFunction::CheckAllowRedeemOffers, 134 this)); 135 if (status == chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED) 136 return; 137 138 bool allow = true; 139 chromeos::CrosSettings::Get()->GetBoolean( 140 chromeos::kAllowRedeemChromeOsRegistrationOffers, &allow); 141 results_ = echo_api::CheckAllowRedeemOffers::Results::Create(allow); 142 SendResponse(true); 143 } 144 145 // Check the enterprise policy kAllowRedeemChromeOsRegistrationOffers flag 146 // value. This policy is used to control whether user can redeem offers using 147 // enterprise device. 148 bool EchoPrivateCheckAllowRedeemOffersFunction::RunImpl() { 149 CheckAllowRedeemOffers(); 150 return true; 151 } 152 153 EchoPrivateGetUserConsentFunction::EchoPrivateGetUserConsentFunction() 154 : redeem_offers_allowed_(false) { 155 } 156 157 // static 158 scoped_refptr<EchoPrivateGetUserConsentFunction> 159 EchoPrivateGetUserConsentFunction::CreateForTest( 160 const DialogShownTestCallback& dialog_shown_callback) { 161 scoped_refptr<EchoPrivateGetUserConsentFunction> function( 162 new EchoPrivateGetUserConsentFunction()); 163 function->dialog_shown_callback_ = dialog_shown_callback; 164 return function; 165 } 166 167 EchoPrivateGetUserConsentFunction::~EchoPrivateGetUserConsentFunction() {} 168 169 bool EchoPrivateGetUserConsentFunction::RunImpl() { 170 CheckRedeemOffersAllowed(); 171 return true; 172 } 173 174 void EchoPrivateGetUserConsentFunction::OnAccept() { 175 Finalize(true); 176 } 177 178 void EchoPrivateGetUserConsentFunction::OnCancel() { 179 Finalize(false); 180 } 181 182 void EchoPrivateGetUserConsentFunction::OnMoreInfoLinkClicked() { 183 chrome::NavigateParams params(profile(), 184 GURL(kMoreInfoLink), 185 content::PAGE_TRANSITION_LINK); 186 // Open the link in a new window. The echo dialog is modal, so the current 187 // window is useless until the dialog is closed. 188 params.disposition = NEW_WINDOW; 189 chrome::Navigate(¶ms); 190 } 191 192 void EchoPrivateGetUserConsentFunction::CheckRedeemOffersAllowed() { 193 chromeos::CrosSettingsProvider::TrustedStatus status = 194 chromeos::CrosSettings::Get()->PrepareTrustedValues(base::Bind( 195 &EchoPrivateGetUserConsentFunction::CheckRedeemOffersAllowed, 196 this)); 197 if (status == chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED) 198 return; 199 200 bool allow = true; 201 chromeos::CrosSettings::Get()->GetBoolean( 202 chromeos::kAllowRedeemChromeOsRegistrationOffers, &allow); 203 204 OnRedeemOffersAllowedChecked(allow); 205 } 206 207 void EchoPrivateGetUserConsentFunction::OnRedeemOffersAllowedChecked( 208 bool is_allowed) { 209 redeem_offers_allowed_ = is_allowed; 210 211 scoped_ptr<echo_api::GetUserConsent::Params> params = 212 echo_api::GetUserConsent::Params::Create(*args_); 213 214 // Verify that the passed origin URL is valid. 215 GURL service_origin = GURL(params->consent_requester.origin); 216 if (!service_origin.is_valid()) { 217 error_ = "Invalid origin."; 218 SendResponse(false); 219 return; 220 } 221 222 // Add ref to ensure the function stays around until the dialog listener is 223 // called. The reference is release in |Finalize|. 224 AddRef(); 225 226 // Create and show the dialog. 227 chromeos::EchoDialogView* dialog = new chromeos::EchoDialogView(this); 228 if (redeem_offers_allowed_) { 229 dialog->InitForEnabledEcho( 230 UTF8ToUTF16(params->consent_requester.service_name), 231 UTF8ToUTF16(params->consent_requester.origin)); 232 } else { 233 dialog->InitForDisabledEcho(); 234 } 235 dialog->Show(GetCurrentBrowser()->window()->GetNativeWindow()); 236 237 // If there is a dialog_shown_callback_, invoke it with the created dialog. 238 if (!dialog_shown_callback_.is_null()) 239 dialog_shown_callback_.Run(dialog); 240 } 241 242 void EchoPrivateGetUserConsentFunction::Finalize(bool consent) { 243 // Consent should not be true if offers redeeming is disabled. 244 CHECK(redeem_offers_allowed_ || !consent); 245 results_ = echo_api::GetUserConsent::Results::Create(consent); 246 SendResponse(true); 247 248 // Release the reference added in |OnRedeemOffersAllowedChecked|, before 249 // showing the dialog. 250 Release(); 251 } 252