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