13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
23f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
33f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// found in the LICENSE file.
43f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
53f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/remoting/setup_flow_login_step.h"
63f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
73f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/json/json_reader.h"
83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/json/json_writer.h"
93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/string_util.h"
103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/utf_string_conversions.h"
113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/values.h"
123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/profiles/profile.h"
133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/remoting/setup_flow_get_status_step.h"
143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/common/net/gaia/gaia_constants.h"
153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/common/net/gaia/google_service_auth_error.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace remoting {
183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenstatic const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']";
203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
213f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenSetupFlowLoginStep::SetupFlowLoginStep() { }
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSetupFlowLoginStep::SetupFlowLoginStep(const string16& error_message)
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : error_message_(error_message) {
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
273f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenSetupFlowLoginStep::~SetupFlowLoginStep() { }
283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::HandleMessage(const std::string& message,
303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                       const Value* arg) {
313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (message == "SubmitAuth") {
323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(arg);
333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    std::string json;
353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    if (!arg->GetAsString(&json) || json.empty()) {
363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      NOTREACHED();
373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      return;
383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    }
393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) {
423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      NOTREACHED() << "Unable to parse auth data";
433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      return;
443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    }
453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    CHECK(parsed_value->IsType(Value::TYPE_DICTIONARY));
473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string username, password, captcha, access_code;
493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const DictionaryValue* result =
503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        static_cast<const DictionaryValue*>(parsed_value.get());
513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    if (!result->GetString("user", &username) ||
523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        !result->GetString("pass", &password) ||
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        !result->GetString("captcha", &captcha) ||
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        !result->GetString("access_code", &access_code)) {
553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      NOTREACHED() << "Unable to parse auth data";
563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      return;
573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    }
583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    OnUserSubmittedAuth(username, password, captcha, access_code);
603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::Cancel() {
643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (authenticator_.get())
653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    authenticator_->CancelRequest();
663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::OnUserSubmittedAuth(const std::string& user,
693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                             const std::string& password,
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             const std::string& captcha,
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             const std::string& access_code) {
723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  flow()->context()->login = user;
733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Start the authenticator.
753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  authenticator_.reset(
763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                          flow()->profile()->GetRequestContext()));
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string remoting_password;
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!access_code.empty())
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    remoting_password = access_code;
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  else
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    remoting_password = password;
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  authenticator_->StartClientLogin(user, remoting_password,
863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                   GaiaConstants::kRemotingService,
873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                   "", captcha,
883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                   GaiaAuthFetcher::HostedAccountsAllowed);
893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::OnClientLoginSuccess(
923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const GaiaAuthConsumer::ClientLoginResult& credentials) {
933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Save the token for remoting.
943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  flow()->context()->remoting_token = credentials.token;
953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // After login has succeeded try to fetch the token for sync.
973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // We need the token for sync to connect to the talk network.
983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  authenticator_->StartIssueAuthToken(credentials.sid, credentials.lsid,
993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                      GaiaConstants::kSyncService);
1003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::OnClientLoginFailure(
1033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const GoogleServiceAuthError& error) {
1043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ShowGaiaFailed(error);
1053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  authenticator_.reset();
1063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::OnIssueAuthTokenSuccess(
1093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const std::string& service, const std::string& auth_token) {
1103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Save the sync token.
1113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  flow()->context()->talk_token = auth_token;
1123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  authenticator_.reset();
1133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  FinishStep(new SetupFlowGetStatusStep());
1153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::OnIssueAuthTokenFailure(const std::string& service,
1183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const GoogleServiceAuthError& error) {
1193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ShowGaiaFailed(error);
1203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  authenticator_.reset();
1213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::DoStart() {
1243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DictionaryValue args;
1253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // TODO(sergeyu): Supply current login name if the service was started before.
1263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  args.SetString("user", "");
1273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  args.SetBoolean("editable_user", true);
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!error_message_.empty())
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.SetString("error_message", error_message_);
1303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ShowGaiaLogin(args);
1313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::ShowGaiaLogin(const DictionaryValue& args) {
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  WebUI* web_ui = flow()->web_ui();
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(web_ui);
1363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui->CallJavascriptFunction("showLogin");
1383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  std::string json;
1403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::JSONWriter::Write(&args, false, &json);
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::wstring javascript = std::wstring(L"showGaiaLogin(") +
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      UTF8ToWide(json) + L");";
1433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
1443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SetupFlowLoginStep::ShowGaiaFailed(const GoogleServiceAuthError& error) {
1473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DictionaryValue args;
1483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  args.SetInteger("error", error.state());
1493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  args.SetBoolean("editable_user", true);
1503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  args.SetString("captchaUrl", error.captcha().image_url.spec());
1513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ShowGaiaLogin(args);
1523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
1533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}  // namespace remoting
155