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