Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: remoting/host/gaia_oauth_client.cc

Issue 10332187: Properly handle accounts that don't have GMail. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/gaia_oauth_client.h" 5 #include "remoting/host/gaia_oauth_client.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/values.h" 11 #include "base/values.h"
12 #include "googleurl/src/gurl.h" 12 #include "googleurl/src/gurl.h"
13 #include "net/base/escape.h" 13 #include "net/base/escape.h"
14 #include "net/http/http_status_code.h" 14 #include "net/http/http_status_code.h"
15 #include "net/url_request/url_request_context_getter.h" 15 #include "net/url_request/url_request_context_getter.h"
16 #include "net/url_request/url_request_status.h" 16 #include "net/url_request/url_request_status.h"
17 #include "remoting/host/url_fetcher.h" 17 #include "remoting/host/url_fetcher.h"
18 18
19 namespace { 19 namespace {
20
21 const char kUserInfoUrl[] = "https://www.googleapis.com/oauth2/v1/userinfo";
Wez 2012/05/16 23:00:07 It seems wrong for the GaiaOAuth2Url to be a param
Sergey Ulanov 2012/05/17 00:38:11 Made them both configurable.
22
20 const char kAccessTokenValue[] = "access_token"; 23 const char kAccessTokenValue[] = "access_token";
21 const char kRefreshTokenValue[] = "refresh_token"; 24 const char kRefreshTokenValue[] = "refresh_token";
22 const char kExpiresInValue[] = "expires_in"; 25 const char kExpiresInValue[] = "expires_in";
26 const char kEmailValue[] = "email";
Wez 2012/05/16 23:00:07 nit: Keep this definition with the URL definition,
Sergey Ulanov 2012/05/17 00:38:11 Done.
27
23 } // namespace 28 } // namespace
24 29
25 namespace remoting { 30 namespace remoting {
26 31
27 class GaiaOAuthClient::Core 32 class GaiaOAuthClient::Core
28 : public base::RefCountedThreadSafe<GaiaOAuthClient::Core> { 33 : public base::RefCountedThreadSafe<GaiaOAuthClient::Core> {
29 public: 34 public:
30 Core(const std::string& gaia_url, 35 Core(const std::string& gaia_url,
31 net::URLRequestContextGetter* request_context_getter) 36 net::URLRequestContextGetter* request_context_getter)
32 : gaia_url_(gaia_url), 37 : gaia_url_(gaia_url),
33 request_context_getter_(request_context_getter), 38 request_context_getter_(request_context_getter),
34 delegate_(NULL) { 39 delegate_(NULL) {
35 } 40 }
36 41
37 void RefreshToken(const OAuthClientInfo& oauth_client_info, 42 void RefreshToken(const OAuthClientInfo& oauth_client_info,
38 const std::string& refresh_token, 43 const std::string& refresh_token,
39 GaiaOAuthClient::Delegate* delegate); 44 GaiaOAuthClient::Delegate* delegate);
40 45
41 private: 46 private:
42 friend class base::RefCountedThreadSafe<Core>; 47 friend class base::RefCountedThreadSafe<Core>;
43 virtual ~Core() {} 48 virtual ~Core() {}
44 49
45 void OnUrlFetchComplete(const net::URLRequestStatus& status, 50 void OnAuthTokenFetchComplete(const net::URLRequestStatus& status,
46 int response_code, 51 int response_code,
47 const std::string& response); 52 const std::string& response);
53 void FetchUserInfo();
54 void OnUserInfoFetchComplete(const net::URLRequestStatus& status,
55 int response_code,
56 const std::string& response);
48 57
49 GURL gaia_url_; 58 GURL gaia_url_;
50 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 59 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
51 GaiaOAuthClient::Delegate* delegate_; 60 GaiaOAuthClient::Delegate* delegate_;
52 scoped_ptr<UrlFetcher> request_; 61 scoped_ptr<UrlFetcher> request_;
62
63 std::string access_token_;
64 int expires_in_seconds_;
53 }; 65 };
54 66
55 void GaiaOAuthClient::Core::RefreshToken( 67 void GaiaOAuthClient::Core::RefreshToken(
56 const OAuthClientInfo& oauth_client_info, 68 const OAuthClientInfo& oauth_client_info,
57 const std::string& refresh_token, 69 const std::string& refresh_token,
58 GaiaOAuthClient::Delegate* delegate) { 70 GaiaOAuthClient::Delegate* delegate) {
59 DCHECK(!request_.get()) << "Tried to fetch two things at once!"; 71 DCHECK(!request_.get()) << "Tried to fetch two things at once!";
60 72
73 delegate_ = delegate;
74
75 access_token_.clear();
76 expires_in_seconds_ = 0;
77
61 std::string post_body = 78 std::string post_body =
62 "refresh_token=" + net::EscapeUrlEncodedData(refresh_token, true) + 79 "refresh_token=" + net::EscapeUrlEncodedData(refresh_token, true) +
63 "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id, 80 "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id,
64 true) + 81 true) +
65 "&client_secret=" + 82 "&client_secret=" +
66 net::EscapeUrlEncodedData(oauth_client_info.client_secret, true) + 83 net::EscapeUrlEncodedData(oauth_client_info.client_secret, true) +
67 "&grant_type=refresh_token"; 84 "&grant_type=refresh_token";
68 delegate_ = delegate;
69 request_.reset(new UrlFetcher(gaia_url_, UrlFetcher::POST)); 85 request_.reset(new UrlFetcher(gaia_url_, UrlFetcher::POST));
70 request_->SetRequestContext(request_context_getter_); 86 request_->SetRequestContext(request_context_getter_);
71 request_->SetUploadData("application/x-www-form-urlencoded", post_body); 87 request_->SetUploadData("application/x-www-form-urlencoded", post_body);
72 request_->Start(base::Bind(&GaiaOAuthClient::Core::OnUrlFetchComplete, this)); 88 request_->Start(
89 base::Bind(&GaiaOAuthClient::Core::OnAuthTokenFetchComplete, this));
73 } 90 }
74 91
75 void GaiaOAuthClient::Core::OnUrlFetchComplete( 92 void GaiaOAuthClient::Core::OnAuthTokenFetchComplete(
76 const net::URLRequestStatus& status, 93 const net::URLRequestStatus& status,
77 int response_code, 94 int response_code,
78 const std::string& response) { 95 const std::string& response) {
79 request_.reset(); 96 request_.reset();
80 97
81 if (!status.is_success()) { 98 if (!status.is_success()) {
82 delegate_->OnNetworkError(response_code); 99 delegate_->OnNetworkError(response_code);
83 return; 100 return;
84 } 101 }
85 102
86 // HTTP_BAD_REQUEST means the arguments are invalid. 103 // HTTP_BAD_REQUEST means the arguments are invalid.
87 if (response_code == net::HTTP_BAD_REQUEST) { 104 if (response_code == net::HTTP_BAD_REQUEST) {
88 LOG(ERROR) << "Gaia response: response code=net::HTTP_BAD_REQUEST."; 105 LOG(ERROR) << "Gaia response: response code=net::HTTP_BAD_REQUEST.";
89 delegate_->OnOAuthError(); 106 delegate_->OnOAuthError();
90 return; 107 return;
91 } 108 }
92 109
93 std::string access_token;
94 std::string refresh_token;
95 int expires_in_seconds = 0;
96 if (response_code == net::HTTP_OK) { 110 if (response_code == net::HTTP_OK) {
97 scoped_ptr<Value> message_value(base::JSONReader::Read(response)); 111 scoped_ptr<Value> message_value(base::JSONReader::Read(response));
98 if (message_value.get() && 112 if (message_value.get() &&
99 message_value->IsType(Value::TYPE_DICTIONARY)) { 113 message_value->IsType(Value::TYPE_DICTIONARY)) {
100 scoped_ptr<DictionaryValue> response_dict( 114 scoped_ptr<DictionaryValue> response_dict(
101 static_cast<DictionaryValue*>(message_value.release())); 115 static_cast<DictionaryValue*>(message_value.release()));
102 response_dict->GetString(kAccessTokenValue, &access_token); 116 response_dict->GetString(kAccessTokenValue, &access_token_);
103 response_dict->GetString(kRefreshTokenValue, &refresh_token); 117 response_dict->GetInteger(kExpiresInValue, &expires_in_seconds_);
104 response_dict->GetInteger(kExpiresInValue, &expires_in_seconds);
105 } 118 }
106 VLOG(1) << "Gaia response: acess_token='" << access_token 119 VLOG(1) << "Gaia response: acess_token='" << access_token_
107 << "', refresh_token='" << refresh_token 120 << "', expires in " << expires_in_seconds_ << " second(s)";
108 << "', expires in " << expires_in_seconds << " second(s)";
109 } else { 121 } else {
110 LOG(ERROR) << "Gaia response: response code=" << response_code; 122 LOG(ERROR) << "Gaia response: response code=" << response_code;
111 } 123 }
112 124
113 if (access_token.empty()) { 125 if (access_token_.empty()) {
114 delegate_->OnNetworkError(response_code); 126 delegate_->OnNetworkError(response_code);
115 } else if (refresh_token.empty()) { 127 } else {
116 // If we only have an access token, then this was a refresh request. 128 FetchUserInfo();
117 delegate_->OnRefreshTokenResponse(access_token, expires_in_seconds);
118 } 129 }
119 } 130 }
120 131
132 void GaiaOAuthClient::Core::FetchUserInfo() {
Wez 2012/05/16 23:00:07 Since this fetches the UserInfo and then notifies
Sergey Ulanov 2012/05/17 00:38:11 Renamed it to FetchUserInfoAndInvokeCallback(), bu
133 request_.reset(new UrlFetcher(GURL(kUserInfoUrl), UrlFetcher::GET));
134 request_->SetRequestContext(request_context_getter_);
135 request_->SetHeader("Authorization", "Bearer " + access_token_);
136 request_->Start(
137 base::Bind(&GaiaOAuthClient::Core::OnUserInfoFetchComplete, this));
138 }
139
140 void GaiaOAuthClient::Core::OnUserInfoFetchComplete(
141 const net::URLRequestStatus& status,
142 int response_code,
143 const std::string& response) {
144 std::string email;
145 if (response_code == net::HTTP_OK) {
146 scoped_ptr<Value> message_value(base::JSONReader::Read(response));
Wez 2012/05/16 23:00:07 nit: Indentation.
Sergey Ulanov 2012/05/17 00:38:11 Done.
147 if (message_value.get() &&
148 message_value->IsType(Value::TYPE_DICTIONARY)) {
149 scoped_ptr<DictionaryValue> response_dict(
150 static_cast<DictionaryValue*>(message_value.release()));
Wez 2012/05/16 23:00:07 Can't use AsDictionaryValue() here?
Sergey Ulanov 2012/05/17 00:38:11 Yes, I can, but it makes this code shorter only wh
151 response_dict->GetString(kEmailValue, &email);
152 }
153 }
154
155 if (email.empty()) {
156 delegate_->OnNetworkError(response_code);
157 } else {
158 delegate_->OnRefreshTokenResponse(
159 email, access_token_, expires_in_seconds_);
160 }
161 }
162
121 GaiaOAuthClient::GaiaOAuthClient(const std::string& gaia_url, 163 GaiaOAuthClient::GaiaOAuthClient(const std::string& gaia_url,
122 net::URLRequestContextGetter* context_getter) { 164 net::URLRequestContextGetter* context_getter) {
123 core_ = new Core(gaia_url, context_getter); 165 core_ = new Core(gaia_url, context_getter);
124 } 166 }
125 167
126 GaiaOAuthClient::~GaiaOAuthClient() { 168 GaiaOAuthClient::~GaiaOAuthClient() {
127 } 169 }
128 170
129 void GaiaOAuthClient::RefreshToken(const OAuthClientInfo& oauth_client_info, 171 void GaiaOAuthClient::RefreshToken(const OAuthClientInfo& oauth_client_info,
130 const std::string& refresh_token, 172 const std::string& refresh_token,
131 Delegate* delegate) { 173 Delegate* delegate) {
132 return core_->RefreshToken(oauth_client_info, 174 return core_->RefreshToken(oauth_client_info,
133 refresh_token, 175 refresh_token,
134 delegate); 176 delegate);
135 } 177 }
136 178
137 } // namespace remoting 179 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698