setup_flow_login_step.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2011 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/remoting/setup_flow_login_step.h"
6
7#include "base/json/json_reader.h"
8#include "base/json/json_writer.h"
9#include "base/string_util.h"
10#include "base/utf_string_conversions.h"
11#include "base/values.h"
12#include "chrome/browser/dom_ui/web_ui_util.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/browser/remoting/setup_flow_get_status_step.h"
15#include "chrome/common/net/gaia/gaia_constants.h"
16#include "chrome/common/net/gaia/google_service_auth_error.h"
17
18namespace remoting {
19
20static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']";
21
22SetupFlowLoginStep::SetupFlowLoginStep() { }
23
24SetupFlowLoginStep::SetupFlowLoginStep(const string16& error_message)
25    : error_message_(error_message) {
26}
27
28SetupFlowLoginStep::~SetupFlowLoginStep() { }
29
30void SetupFlowLoginStep::HandleMessage(const std::string& message,
31                                       const Value* arg) {
32  if (message == "SubmitAuth") {
33    DCHECK(arg);
34
35    std::string json;
36    if (!arg->GetAsString(&json) || json.empty()) {
37      NOTREACHED();
38      return;
39    }
40
41    scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
42    if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) {
43      NOTREACHED() << "Unable to parse auth data";
44      return;
45    }
46
47    CHECK(parsed_value->IsType(Value::TYPE_DICTIONARY));
48
49    std::string username, password, captcha, access_code;
50    const DictionaryValue* result =
51        static_cast<const DictionaryValue*>(parsed_value.get());
52    if (!result->GetString("user", &username) ||
53        !result->GetString("pass", &password) ||
54        !result->GetString("captcha", &captcha) ||
55        !result->GetString("access_code", &access_code)) {
56      NOTREACHED() << "Unable to parse auth data";
57      return;
58    }
59
60    OnUserSubmittedAuth(username, password, captcha, access_code);
61  }
62}
63
64void SetupFlowLoginStep::Cancel() {
65  if (authenticator_.get())
66    authenticator_->CancelRequest();
67}
68
69void SetupFlowLoginStep::OnUserSubmittedAuth(const std::string& user,
70                                             const std::string& password,
71                                             const std::string& captcha,
72                                             const std::string& access_code) {
73  flow()->context()->login = user;
74
75  // Start the authenticator.
76  authenticator_.reset(
77      new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
78                          flow()->profile()->GetRequestContext()));
79
80  std::string remoting_password;
81  if (!access_code.empty())
82    remoting_password = access_code;
83  else
84    remoting_password = password;
85
86  authenticator_->StartClientLogin(user, remoting_password,
87                                   GaiaConstants::kRemotingService,
88                                   "", captcha,
89                                   GaiaAuthFetcher::HostedAccountsAllowed);
90}
91
92void SetupFlowLoginStep::OnClientLoginSuccess(
93    const GaiaAuthConsumer::ClientLoginResult& credentials) {
94  // Save the token for remoting.
95  flow()->context()->remoting_token = credentials.token;
96
97  // After login has succeeded try to fetch the token for sync.
98  // We need the token for sync to connect to the talk network.
99  authenticator_->StartIssueAuthToken(credentials.sid, credentials.lsid,
100                                      GaiaConstants::kSyncService);
101}
102
103void SetupFlowLoginStep::OnClientLoginFailure(
104    const GoogleServiceAuthError& error) {
105  ShowGaiaFailed(error);
106  authenticator_.reset();
107}
108
109void SetupFlowLoginStep::OnIssueAuthTokenSuccess(
110    const std::string& service, const std::string& auth_token) {
111  // Save the sync token.
112  flow()->context()->talk_token = auth_token;
113  authenticator_.reset();
114
115  FinishStep(new SetupFlowGetStatusStep());
116}
117
118void SetupFlowLoginStep::OnIssueAuthTokenFailure(const std::string& service,
119    const GoogleServiceAuthError& error) {
120  ShowGaiaFailed(error);
121  authenticator_.reset();
122}
123
124void SetupFlowLoginStep::DoStart() {
125  DictionaryValue args;
126  // TODO(sergeyu): Supply current login name if the service was started before.
127  args.SetString("user", "");
128  args.SetBoolean("editable_user", true);
129  if (!error_message_.empty())
130    args.SetString("error_message", error_message_);
131  ShowGaiaLogin(args);
132}
133
134void SetupFlowLoginStep::ShowGaiaLogin(const DictionaryValue& args) {
135  WebUI* web_ui = flow()->web_ui();
136  DCHECK(web_ui);
137
138  web_ui->CallJavascriptFunction(L"showLogin");
139
140  std::string json;
141  base::JSONWriter::Write(&args, false, &json);
142  std::wstring javascript = std::wstring(L"showGaiaLogin(") +
143      UTF8ToWide(json) + L");";
144  ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
145}
146
147void SetupFlowLoginStep::ShowGaiaFailed(const GoogleServiceAuthError& error) {
148  DictionaryValue args;
149  args.SetInteger("error", error.state());
150  args.SetBoolean("editable_user", true);
151  args.SetString("captchaUrl", error.captcha().image_url.spec());
152  ShowGaiaLogin(args);
153}
154
155}  // namespace remoting
156