Index: sync/notifier/gcm_network_channel.cc |
diff --git a/sync/notifier/gcm_network_channel.cc b/sync/notifier/gcm_network_channel.cc |
index 41f288c42df37dfc48f41c61dfeaf58db1023205..4a748c213aae6f9a0694b1d8b521f92019da7546 100644 |
--- a/sync/notifier/gcm_network_channel.cc |
+++ b/sync/notifier/gcm_network_channel.cc |
@@ -2,21 +2,128 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "google_apis/gaia/google_service_auth_error.h" |
+#include "net/http/http_status_code.h" |
+#include "net/url_request/url_fetcher.h" |
+#include "net/url_request/url_request_status.h" |
#include "sync/notifier/gcm_network_channel.h" |
+#include "sync/notifier/gcm_network_channel_delegate.h" |
namespace syncer { |
-GCMNetworkChannel::GCMNetworkChannel() { |
+GCMNetworkChannel::GCMNetworkChannel( |
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter, |
+ scoped_ptr<GCMNetworkChannelDelegate> delegate) |
+ : request_context_getter_(request_context_getter), |
+ delegate_(delegate.Pass()), |
+ weak_factory_(this) { |
+ delegate_->Register(base::Bind(&GCMNetworkChannel::OnRegisterComplete, |
+ weak_factory_.GetWeakPtr())); |
} |
GCMNetworkChannel::~GCMNetworkChannel() { |
} |
+void GCMNetworkChannel::UpdateCredentials( |
+ const std::string& email, |
+ const std::string& token) { |
+ // Do nothing. We get access token by requesting it for every message. |
+} |
+ |
+void GCMNetworkChannel::OnRegisterComplete( |
+ const std::string& registration_id, |
+ gcm::GCMClient::Result result) { |
+ DCHECK(CalledOnValidThread()); |
+ if (result == gcm::GCMClient::SUCCESS) { |
+ DCHECK(!registration_id.empty()); |
+ DVLOG(2) << "Got registration_id"; |
+ registration_id_ = registration_id; |
+ if (!encoded_message_.empty()) |
+ RequestAccessToken(); |
+ } else { |
+ DVLOG(2) << "Register failed"; |
+ // TODO(pavely): Don't know what to do if registration fails. Let's not do |
tim (not reviewing)
2014/01/17 19:33:42
Consider filing a bug to associate with this (and
pavely
2014/01/17 22:52:26
Done.
|
+ // anything for now. |
+ } |
+} |
+ |
void GCMNetworkChannel::SendEncodedMessage(const std::string& encoded_message) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(!encoded_message.empty()); |
+ DVLOG(2) << "SendEncodedMessage"; |
+ encoded_message_ = encoded_message; |
+ |
+ if (!registration_id_.empty()) { |
+ RequestAccessToken(); |
+ } |
+} |
+ |
+void GCMNetworkChannel::RequestAccessToken() { |
+ DCHECK(CalledOnValidThread()); |
+ delegate_->RequestToken(base::Bind(&GCMNetworkChannel::OnGetTokenComplete, |
+ weak_factory_.GetWeakPtr())); |
} |
-void GCMNetworkChannel::UpdateCredentials(const std::string& email, |
+void GCMNetworkChannel::OnGetTokenComplete( |
+ const GoogleServiceAuthError& error, |
const std::string& token) { |
+ DCHECK(CalledOnValidThread()); |
+ if (encoded_message_.empty()) { |
+ // Nothing to do. |
+ return; |
+ } |
+ |
+ if (!(error == GoogleServiceAuthError::AuthErrorNone())) { |
tim (not reviewing)
2014/01/17 19:33:42
nit - if (error != GSAE::AuthErrorNone())
pavely
2014/01/17 22:52:26
(error != GSAE::AuthErrorNone()) doesn't compile.
|
+ // Requesting access token failed. Persistent errors will be reported by |
+ // token service. Just drop this request, cacheinvalidations will retry |
+ // sending message and at that time we'll retry requesting access token. |
+ DVLOG(1) << "RequestAccessToken failed: " << error.ToString(); |
+ return; |
+ } |
+ DCHECK(!token.empty()); |
+ // Save access token in case POST fails and we need to invalidate it. |
+ access_token_ = token; |
+ |
+ DVLOG(2) << "Got access token, sending message"; |
+ |
+ fetcher_.reset(net::URLFetcher::Create(BuildUrl(), net::URLFetcher::POST, |
+ this)); |
+ fetcher_->SetRequestContext(request_context_getter_); |
+ const std::string auth_header("Authorization: Bearer " + access_token_); |
+ fetcher_->AddExtraRequestHeader(auth_header); |
+ fetcher_->SetUploadData("application/x-protobuffer", encoded_message_); |
+ fetcher_->Start(); |
+ // Clear message to prevent accidentally resending it in the future. |
+ encoded_message_.clear(); |
+} |
+ |
+void GCMNetworkChannel::OnURLFetchComplete(const net::URLFetcher* source) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK_EQ(fetcher_, source); |
+ // Free fetcher at the end of function. |
+ scoped_ptr<net::URLFetcher> fetcher = fetcher_.Pass(); |
+ |
+ net::URLRequestStatus status = fetcher->GetStatus(); |
+ if (!status.is_success()) { |
+ DVLOG(1) << "URLFetcher failure"; |
+ return; |
+ } |
+ |
+ if (fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) { |
+ DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED"; |
+ delegate_->InvalidateToken(access_token_); |
+ return; |
+ } |
+ DVLOG(2) << "URLFetcher success"; |
+} |
+ |
+GURL GCMNetworkChannel::BuildUrl() { |
+ DCHECK(!registration_id_.empty()); |
+ // Prepare NetworkEndpointId using registration_id |
+ // Serialize NetworkEndpointId into byte array and base64 encode. |
+ // Format url using encoded NetworkEndpointId. |
+ // TODO(pavely): implement all of the above. |
+ return GURL("http://invalid.url.com"); |
} |
} // namespace syncer |