| OLD | NEW |
| 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/signaling_connector.h" | 5 #include "remoting/host/signaling_connector.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "google_apis/google_api_keys.h" | 10 #include "google_apis/google_api_keys.h" |
| 11 #include "net/url_request/url_fetcher.h" | 11 #include "net/url_request/url_fetcher.h" |
| 12 #include "net/url_request/url_request_context_getter.h" | 12 #include "net/url_request/url_request_context_getter.h" |
| 13 #include "remoting/base/logging.h" |
| 13 #include "remoting/host/dns_blackhole_checker.h" | 14 #include "remoting/host/dns_blackhole_checker.h" |
| 14 | 15 |
| 15 namespace remoting { | 16 namespace remoting { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 // The delay between reconnect attempts will increase exponentially up | 20 // The delay between reconnect attempts will increase exponentially up |
| 20 // to the maximum specified here. | 21 // to the maximum specified here. |
| 21 const int kMaxReconnectDelaySeconds = 10 * 60; | 22 const int kMaxReconnectDelaySeconds = 10 * 60; |
| 22 | 23 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 oauth_credentials_ = oauth_credentials.Pass(); | 65 oauth_credentials_ = oauth_credentials.Pass(); |
| 65 gaia_oauth_client_.reset( | 66 gaia_oauth_client_.reset( |
| 66 new gaia::GaiaOAuthClient(url_request_context_getter_.get())); | 67 new gaia::GaiaOAuthClient(url_request_context_getter_.get())); |
| 67 } | 68 } |
| 68 | 69 |
| 69 void SignalingConnector::OnSignalStrategyStateChange( | 70 void SignalingConnector::OnSignalStrategyStateChange( |
| 70 SignalStrategy::State state) { | 71 SignalStrategy::State state) { |
| 71 DCHECK(CalledOnValidThread()); | 72 DCHECK(CalledOnValidThread()); |
| 72 | 73 |
| 73 if (state == SignalStrategy::CONNECTED) { | 74 if (state == SignalStrategy::CONNECTED) { |
| 74 LOG(INFO) << "Signaling connected."; | 75 LOG_INFO << "Signaling connected."; |
| 75 reconnect_attempts_ = 0; | 76 reconnect_attempts_ = 0; |
| 76 } else if (state == SignalStrategy::DISCONNECTED) { | 77 } else if (state == SignalStrategy::DISCONNECTED) { |
| 77 LOG(INFO) << "Signaling disconnected."; | 78 LOG_INFO << "Signaling disconnected."; |
| 78 reconnect_attempts_++; | 79 reconnect_attempts_++; |
| 79 | 80 |
| 80 // If authentication failed then we have an invalid OAuth token, | 81 // If authentication failed then we have an invalid OAuth token, |
| 81 // inform the upper layer about it. | 82 // inform the upper layer about it. |
| 82 if (signal_strategy_->GetError() == SignalStrategy::AUTHENTICATION_FAILED) { | 83 if (signal_strategy_->GetError() == SignalStrategy::AUTHENTICATION_FAILED) { |
| 83 auth_failed_callback_.Run(); | 84 auth_failed_callback_.Run(); |
| 84 } else { | 85 } else { |
| 85 ScheduleTryReconnect(); | 86 ScheduleTryReconnect(); |
| 86 } | 87 } |
| 87 } | 88 } |
| 88 } | 89 } |
| 89 | 90 |
| 90 bool SignalingConnector::OnSignalStrategyIncomingStanza( | 91 bool SignalingConnector::OnSignalStrategyIncomingStanza( |
| 91 const buzz::XmlElement* stanza) { | 92 const buzz::XmlElement* stanza) { |
| 92 return false; | 93 return false; |
| 93 } | 94 } |
| 94 | 95 |
| 95 void SignalingConnector::OnConnectionTypeChanged( | 96 void SignalingConnector::OnConnectionTypeChanged( |
| 96 net::NetworkChangeNotifier::ConnectionType type) { | 97 net::NetworkChangeNotifier::ConnectionType type) { |
| 97 DCHECK(CalledOnValidThread()); | 98 DCHECK(CalledOnValidThread()); |
| 98 if (type != net::NetworkChangeNotifier::CONNECTION_NONE && | 99 if (type != net::NetworkChangeNotifier::CONNECTION_NONE && |
| 99 signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { | 100 signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { |
| 100 LOG(INFO) << "Network state changed to online."; | 101 LOG_INFO << "Network state changed to online."; |
| 101 ResetAndTryReconnect(); | 102 ResetAndTryReconnect(); |
| 102 } | 103 } |
| 103 } | 104 } |
| 104 | 105 |
| 105 void SignalingConnector::OnIPAddressChanged() { | 106 void SignalingConnector::OnIPAddressChanged() { |
| 106 DCHECK(CalledOnValidThread()); | 107 DCHECK(CalledOnValidThread()); |
| 107 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { | 108 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { |
| 108 LOG(INFO) << "IP address has changed."; | 109 LOG_INFO << "IP address has changed."; |
| 109 ResetAndTryReconnect(); | 110 ResetAndTryReconnect(); |
| 110 } | 111 } |
| 111 } | 112 } |
| 112 | 113 |
| 113 void SignalingConnector::OnGetTokensResponse(const std::string& user_email, | 114 void SignalingConnector::OnGetTokensResponse(const std::string& user_email, |
| 114 const std::string& access_token, | 115 const std::string& access_token, |
| 115 int expires_seconds) { | 116 int expires_seconds) { |
| 116 NOTREACHED(); | 117 NOTREACHED(); |
| 117 } | 118 } |
| 118 | 119 |
| 119 void SignalingConnector::OnRefreshTokenResponse( | 120 void SignalingConnector::OnRefreshTokenResponse( |
| 120 const std::string& access_token, | 121 const std::string& access_token, |
| 121 int expires_seconds) { | 122 int expires_seconds) { |
| 122 DCHECK(CalledOnValidThread()); | 123 DCHECK(CalledOnValidThread()); |
| 123 DCHECK(oauth_credentials_.get()); | 124 DCHECK(oauth_credentials_.get()); |
| 124 LOG(INFO) << "Received OAuth token."; | 125 LOG_INFO << "Received OAuth token."; |
| 125 | 126 |
| 126 oauth_access_token_ = access_token; | 127 oauth_access_token_ = access_token; |
| 127 auth_token_expiry_time_ = base::Time::Now() + | 128 auth_token_expiry_time_ = base::Time::Now() + |
| 128 base::TimeDelta::FromSeconds(expires_seconds) - | 129 base::TimeDelta::FromSeconds(expires_seconds) - |
| 129 base::TimeDelta::FromSeconds(kTokenUpdateTimeBeforeExpirySeconds); | 130 base::TimeDelta::FromSeconds(kTokenUpdateTimeBeforeExpirySeconds); |
| 130 | 131 |
| 131 gaia_oauth_client_->GetUserEmail(access_token, 1, this); | 132 gaia_oauth_client_->GetUserEmail(access_token, 1, this); |
| 132 } | 133 } |
| 133 | 134 |
| 134 void SignalingConnector::OnGetUserEmailResponse(const std::string& user_email) { | 135 void SignalingConnector::OnGetUserEmailResponse(const std::string& user_email) { |
| 135 DCHECK(CalledOnValidThread()); | 136 DCHECK(CalledOnValidThread()); |
| 136 DCHECK(oauth_credentials_.get()); | 137 DCHECK(oauth_credentials_.get()); |
| 137 LOG(INFO) << "Received user info."; | 138 LOG_INFO << "Received user info."; |
| 138 | 139 |
| 139 if (user_email != oauth_credentials_->login) { | 140 if (user_email != oauth_credentials_->login) { |
| 140 LOG(ERROR) << "OAuth token and email address do not refer to " | 141 LOG(ERROR) << "OAuth token and email address do not refer to " |
| 141 "the same account."; | 142 "the same account."; |
| 142 auth_failed_callback_.Run(); | 143 auth_failed_callback_.Run(); |
| 143 return; | 144 return; |
| 144 } | 145 } |
| 145 | 146 |
| 146 signal_strategy_->SetAuthInfo(oauth_credentials_->login, | 147 signal_strategy_->SetAuthInfo(oauth_credentials_->login, |
| 147 oauth_access_token_, "oauth2"); | 148 oauth_access_token_, "oauth2"); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 } | 201 } |
| 201 | 202 |
| 202 void SignalingConnector::OnDnsBlackholeCheckerDone(bool allow) { | 203 void SignalingConnector::OnDnsBlackholeCheckerDone(bool allow) { |
| 203 DCHECK(CalledOnValidThread()); | 204 DCHECK(CalledOnValidThread()); |
| 204 | 205 |
| 205 // Unable to access the host talkgadget. Don't allow the connection, but | 206 // Unable to access the host talkgadget. Don't allow the connection, but |
| 206 // schedule a reconnect in case this is a transient problem rather than | 207 // schedule a reconnect in case this is a transient problem rather than |
| 207 // an outright block. | 208 // an outright block. |
| 208 if (!allow) { | 209 if (!allow) { |
| 209 reconnect_attempts_++; | 210 reconnect_attempts_++; |
| 210 LOG(INFO) << "Talkgadget check failed. Scheduling reconnect. Attempt " | 211 LOG_INFO << "Talkgadget check failed. Scheduling reconnect. Attempt " |
| 211 << reconnect_attempts_; | 212 << reconnect_attempts_; |
| 212 ScheduleTryReconnect(); | 213 ScheduleTryReconnect(); |
| 213 return; | 214 return; |
| 214 } | 215 } |
| 215 | 216 |
| 216 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { | 217 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { |
| 217 bool need_new_auth_token = oauth_credentials_.get() && | 218 bool need_new_auth_token = oauth_credentials_.get() && |
| 218 (auth_token_expiry_time_.is_null() || | 219 (auth_token_expiry_time_.is_null() || |
| 219 base::Time::Now() >= auth_token_expiry_time_); | 220 base::Time::Now() >= auth_token_expiry_time_); |
| 220 if (need_new_auth_token) { | 221 if (need_new_auth_token) { |
| 221 RefreshOAuthToken(); | 222 RefreshOAuthToken(); |
| 222 } else { | 223 } else { |
| 223 LOG(INFO) << "Attempting to connect signaling."; | 224 LOG_INFO << "Attempting to connect signaling."; |
| 224 signal_strategy_->Connect(); | 225 signal_strategy_->Connect(); |
| 225 } | 226 } |
| 226 } | 227 } |
| 227 } | 228 } |
| 228 | 229 |
| 229 void SignalingConnector::RefreshOAuthToken() { | 230 void SignalingConnector::RefreshOAuthToken() { |
| 230 DCHECK(CalledOnValidThread()); | 231 DCHECK(CalledOnValidThread()); |
| 231 LOG(INFO) << "Refreshing OAuth token."; | 232 LOG_INFO << "Refreshing OAuth token."; |
| 232 DCHECK(!refreshing_oauth_token_); | 233 DCHECK(!refreshing_oauth_token_); |
| 233 | 234 |
| 234 // Service accounts use different API keys, as they use the client app flow. | 235 // Service accounts use different API keys, as they use the client app flow. |
| 235 google_apis::OAuth2Client oauth2_client; | 236 google_apis::OAuth2Client oauth2_client; |
| 236 if (oauth_credentials_->is_service_account) { | 237 if (oauth_credentials_->is_service_account) { |
| 237 oauth2_client = google_apis::CLIENT_REMOTING_HOST; | 238 oauth2_client = google_apis::CLIENT_REMOTING_HOST; |
| 238 } else { | 239 } else { |
| 239 oauth2_client = google_apis::CLIENT_REMOTING; | 240 oauth2_client = google_apis::CLIENT_REMOTING; |
| 240 } | 241 } |
| 241 | 242 |
| 242 gaia::OAuthClientInfo client_info = { | 243 gaia::OAuthClientInfo client_info = { |
| 243 google_apis::GetOAuth2ClientID(oauth2_client), | 244 google_apis::GetOAuth2ClientID(oauth2_client), |
| 244 google_apis::GetOAuth2ClientSecret(oauth2_client), | 245 google_apis::GetOAuth2ClientSecret(oauth2_client), |
| 245 // Redirect URL is only used when getting tokens from auth code. It | 246 // Redirect URL is only used when getting tokens from auth code. It |
| 246 // is not required when getting access tokens. | 247 // is not required when getting access tokens. |
| 247 "" | 248 "" |
| 248 }; | 249 }; |
| 249 | 250 |
| 250 refreshing_oauth_token_ = true; | 251 refreshing_oauth_token_ = true; |
| 251 std::vector<std::string> empty_scope_list; // (Use scope from refresh token.) | 252 std::vector<std::string> empty_scope_list; // (Use scope from refresh token.) |
| 252 gaia_oauth_client_->RefreshToken( | 253 gaia_oauth_client_->RefreshToken( |
| 253 client_info, oauth_credentials_->refresh_token, empty_scope_list, | 254 client_info, oauth_credentials_->refresh_token, empty_scope_list, |
| 254 1, this); | 255 1, this); |
| 255 } | 256 } |
| 256 | 257 |
| 257 } // namespace remoting | 258 } // namespace remoting |
| OLD | NEW |