| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/base64.h" |
| 6 #include "base/strings/string_util.h" |
| 7 #if !defined(ANDROID) |
| 8 // channel_common.proto defines ANDROID constant that conflicts with Android |
| 9 // build. At the same time TiclInvalidationService is not used on Android so it |
| 10 // is safe to exclude these protos from Android build. |
| 11 #include "google/cacheinvalidation/android_channel.pb.h" |
| 12 #include "google/cacheinvalidation/channel_common.pb.h" |
| 13 #endif |
| 5 #include "google_apis/gaia/google_service_auth_error.h" | 14 #include "google_apis/gaia/google_service_auth_error.h" |
| 6 #include "net/http/http_status_code.h" | 15 #include "net/http/http_status_code.h" |
| 7 #include "net/url_request/url_fetcher.h" | 16 #include "net/url_request/url_fetcher.h" |
| 8 #include "net/url_request/url_request_status.h" | 17 #include "net/url_request/url_request_status.h" |
| 9 #include "sync/notifier/gcm_network_channel.h" | 18 #include "sync/notifier/gcm_network_channel.h" |
| 10 #include "sync/notifier/gcm_network_channel_delegate.h" | 19 #include "sync/notifier/gcm_network_channel_delegate.h" |
| 11 | 20 |
| 12 namespace syncer { | 21 namespace syncer { |
| 13 | 22 |
| 14 namespace { | 23 namespace { |
| 15 | 24 |
| 25 const char kCacheInvalidationEndpointUrl[] = |
| 26 "https://clients4.google.com/invalidation/android/request/"; |
| 27 const char kCacheInvalidationPackageName[] = "com.google.chrome.invalidations"; |
| 28 |
| 16 // Register backoff policy. | 29 // Register backoff policy. |
| 17 const net::BackoffEntry::Policy kRegisterBackoffPolicy = { | 30 const net::BackoffEntry::Policy kRegisterBackoffPolicy = { |
| 18 // Number of initial errors (in sequence) to ignore before applying | 31 // Number of initial errors (in sequence) to ignore before applying |
| 19 // exponential back-off rules. | 32 // exponential back-off rules. |
| 20 0, | 33 0, |
| 21 | 34 |
| 22 // Initial delay for exponential back-off in ms. | 35 // Initial delay for exponential back-off in ms. |
| 23 2000, // 2 seconds. | 36 2000, // 2 seconds. |
| 24 | 37 |
| 25 // Factor by which the waiting time will be multiplied. | 38 // Factor by which the waiting time will be multiplied. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 // token service. Just drop this request, cacheinvalidations will retry | 149 // token service. Just drop this request, cacheinvalidations will retry |
| 137 // sending message and at that time we'll retry requesting access token. | 150 // sending message and at that time we'll retry requesting access token. |
| 138 DVLOG(1) << "RequestAccessToken failed: " << error.ToString(); | 151 DVLOG(1) << "RequestAccessToken failed: " << error.ToString(); |
| 139 return; | 152 return; |
| 140 } | 153 } |
| 141 DCHECK(!token.empty()); | 154 DCHECK(!token.empty()); |
| 142 // Save access token in case POST fails and we need to invalidate it. | 155 // Save access token in case POST fails and we need to invalidate it. |
| 143 access_token_ = token; | 156 access_token_ = token; |
| 144 | 157 |
| 145 DVLOG(2) << "Got access token, sending message"; | 158 DVLOG(2) << "Got access token, sending message"; |
| 146 | 159 fetcher_.reset(net::URLFetcher::Create( |
| 147 fetcher_.reset(net::URLFetcher::Create(BuildUrl(), net::URLFetcher::POST, | 160 BuildUrl(registration_id_), net::URLFetcher::POST, this)); |
| 148 this)); | |
| 149 fetcher_->SetRequestContext(request_context_getter_); | 161 fetcher_->SetRequestContext(request_context_getter_); |
| 150 const std::string auth_header("Authorization: Bearer " + access_token_); | 162 const std::string auth_header("Authorization: Bearer " + access_token_); |
| 151 fetcher_->AddExtraRequestHeader(auth_header); | 163 fetcher_->AddExtraRequestHeader(auth_header); |
| 152 fetcher_->SetUploadData("application/x-protobuffer", cached_message_); | 164 fetcher_->SetUploadData("application/x-protobuffer", cached_message_); |
| 153 fetcher_->Start(); | 165 fetcher_->Start(); |
| 154 // Clear message to prevent accidentally resending it in the future. | 166 // Clear message to prevent accidentally resending it in the future. |
| 155 cached_message_.clear(); | 167 cached_message_.clear(); |
| 156 } | 168 } |
| 157 | 169 |
| 158 void GCMNetworkChannel::OnURLFetchComplete(const net::URLFetcher* source) { | 170 void GCMNetworkChannel::OnURLFetchComplete(const net::URLFetcher* source) { |
| 159 DCHECK(CalledOnValidThread()); | 171 DCHECK(CalledOnValidThread()); |
| 160 DCHECK_EQ(fetcher_, source); | 172 DCHECK_EQ(fetcher_, source); |
| 161 // Free fetcher at the end of function. | 173 // Free fetcher at the end of function. |
| 162 scoped_ptr<net::URLFetcher> fetcher = fetcher_.Pass(); | 174 scoped_ptr<net::URLFetcher> fetcher = fetcher_.Pass(); |
| 163 | 175 |
| 164 net::URLRequestStatus status = fetcher->GetStatus(); | 176 net::URLRequestStatus status = fetcher->GetStatus(); |
| 165 if (!status.is_success()) { | 177 if (!status.is_success()) { |
| 166 DVLOG(1) << "URLFetcher failure"; | 178 DVLOG(1) << "URLFetcher failure"; |
| 167 return; | 179 return; |
| 168 } | 180 } |
| 169 | 181 |
| 170 if (fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) { | 182 if (fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) { |
| 171 DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED"; | 183 DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED"; |
| 172 delegate_->InvalidateToken(access_token_); | 184 delegate_->InvalidateToken(access_token_); |
| 173 return; | 185 return; |
| 174 } | 186 } |
| 175 DVLOG(2) << "URLFetcher success"; | 187 DVLOG(2) << "URLFetcher success"; |
| 176 } | 188 } |
| 177 | 189 |
| 178 GURL GCMNetworkChannel::BuildUrl() { | 190 GURL GCMNetworkChannel::BuildUrl(const std::string& registration_id) { |
| 179 DCHECK(!registration_id_.empty()); | 191 DCHECK(!registration_id.empty()); |
| 180 // Prepare NetworkEndpointId using registration_id | 192 |
| 181 // Serialize NetworkEndpointId into byte array and base64 encode. | 193 #if !defined(ANDROID) |
| 182 // Format url using encoded NetworkEndpointId. | 194 ipc::invalidation::EndpointId endpoint_id; |
| 183 // TODO(pavely): implement all of the above. | 195 endpoint_id.set_c2dm_registration_id(registration_id); |
| 184 return GURL("http://invalid.url.com"); | 196 endpoint_id.set_client_key(std::string()); |
| 197 endpoint_id.set_package_name(kCacheInvalidationPackageName); |
| 198 endpoint_id.mutable_channel_version()->set_major_version( |
| 199 ipc::invalidation::INITIAL); |
| 200 std::string endpoint_id_buffer; |
| 201 endpoint_id.SerializeToString(&endpoint_id_buffer); |
| 202 |
| 203 ipc::invalidation::NetworkEndpointId network_endpoint_id; |
| 204 network_endpoint_id.set_network_address( |
| 205 ipc::invalidation::NetworkEndpointId_NetworkAddress_ANDROID); |
| 206 network_endpoint_id.set_client_address(endpoint_id_buffer); |
| 207 std::string network_endpoint_id_buffer; |
| 208 network_endpoint_id.SerializeToString(&network_endpoint_id_buffer); |
| 209 |
| 210 std::string base64URLPiece; |
| 211 Base64EncodeURLSafe(network_endpoint_id_buffer, &base64URLPiece); |
| 212 |
| 213 std::string url(kCacheInvalidationEndpointUrl); |
| 214 url += base64URLPiece; |
| 215 return GURL(url); |
| 216 #else |
| 217 // This code shouldn't be invoked on Android. |
| 218 NOTREACHED(); |
| 219 return GURL(); |
| 220 #endif |
| 221 } |
| 222 |
| 223 void GCMNetworkChannel::Base64EncodeURLSafe(const std::string& input, |
| 224 std::string* output) { |
| 225 base::Base64Encode(input, output); |
| 226 // Covert to url safe alphabet. |
| 227 base::ReplaceChars(*output, "+", "-", output); |
| 228 base::ReplaceChars(*output, "/", "_", output); |
| 229 // Trim padding. |
| 230 size_t padding_size = 0; |
| 231 for (size_t i = output->size(); i > 0 && (*output)[i - 1] == '='; --i) |
| 232 ++padding_size; |
| 233 output->resize(output->size() - padding_size); |
| 234 } |
| 235 |
| 236 bool GCMNetworkChannel::Base64DecodeURLSafe(const std::string& input, |
| 237 std::string* output) { |
| 238 // Add padding. |
| 239 size_t padded_size = (input.size() + 3) - (input.size() + 3) % 4; |
| 240 std::string padded_input(input); |
| 241 padded_input.resize(padded_size, '='); |
| 242 // Convert to standard base64 alphabet. |
| 243 base::ReplaceChars(padded_input, "-", "+", &padded_input); |
| 244 base::ReplaceChars(padded_input, "_", "/", &padded_input); |
| 245 return base::Base64Decode(padded_input, output); |
| 185 } | 246 } |
| 186 | 247 |
| 187 } // namespace syncer | 248 } // namespace syncer |
| OLD | NEW |