Chromium Code Reviews| 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..757f18080a852aca23bbfc1dc4396bbb1b6c1afb 100644 |
| --- a/sync/notifier/gcm_network_channel.cc |
| +++ b/sync/notifier/gcm_network_channel.cc |
| @@ -2,21 +2,121 @@ |
| // 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, |
|
rlarocque
2014/01/16 18:52:48
nit: either put this parameter on the next line, o
pavely
2014/01/17 00:44:39
Done.
|
| + gcm::GCMClient::Result result) { |
| + 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 |
| + // anything for now. |
| + } |
| +} |
| + |
| void GCMNetworkChannel::SendEncodedMessage(const std::string& encoded_message) { |
| + DCHECK(!encoded_message.empty()); |
| + DVLOG(2) << "SendEncodedMessage"; |
| + encoded_message_ = encoded_message; |
| + |
| + if (!registration_id_.empty()) { |
| + RequestAccessToken(); |
| + } |
| } |
| -void GCMNetworkChannel::UpdateCredentials(const std::string& email, |
| - const std::string& token) { |
| +void GCMNetworkChannel::RequestAccessToken() { |
| + delegate_->RequestToken(base::Bind(&GCMNetworkChannel::OnGetTokenComplete, |
| + weak_factory_.GetWeakPtr())); |
|
rlarocque
2014/01/16 18:52:48
another indentation nit: I think the second line s
pavely
2014/01/17 00:44:39
Done.
|
| +} |
| + |
| +void GCMNetworkChannel::OnGetTokenComplete( |
| + const GoogleServiceAuthError& error, const std::string& token) { |
| + if (encoded_message_.empty()) { |
| + // Nothing to do. |
| + return; |
| + } |
| + |
| + if (!(error == GoogleServiceAuthError::AuthErrorNone())) { |
| + // 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)); |
|
rlarocque
2014/01/16 18:52:48
more nits: I recommend indenting the 'this' parame
pavely
2014/01/17 00:44:39
Done.
|
| + fetcher_->SetRequestContext(request_context_getter_); |
| + std::string auth_header; |
|
rlarocque
2014/01/16 18:52:48
I think it's slightly better to declare and initia
pavely
2014/01/17 00:44:39
Done.
|
| + 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_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 |