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 17namespace remoting { 18 19static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']"; 20 21SetupFlowLoginStep::SetupFlowLoginStep() { } 22 23SetupFlowLoginStep::SetupFlowLoginStep(const string16& error_message) 24 : error_message_(error_message) { 25} 26 27SetupFlowLoginStep::~SetupFlowLoginStep() { } 28 29void 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 63void SetupFlowLoginStep::Cancel() { 64 if (authenticator_.get()) 65 authenticator_->CancelRequest(); 66} 67 68void 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 91void 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 102void SetupFlowLoginStep::OnClientLoginFailure( 103 const GoogleServiceAuthError& error) { 104 ShowGaiaFailed(error); 105 authenticator_.reset(); 106} 107 108void 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 117void SetupFlowLoginStep::OnIssueAuthTokenFailure(const std::string& service, 118 const GoogleServiceAuthError& error) { 119 ShowGaiaFailed(error); 120 authenticator_.reset(); 121} 122 123void 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 133void 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 146void 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