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

Side by Side Diff: google_apis/gcm/engine/connection_factory_impl.cc

Issue 336473003: [GCM] Suppress connection attempts when there is no valid connection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Self review Created 6 years, 6 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "google_apis/gcm/engine/connection_factory_impl.h" 5 #include "google_apis/gcm/engine/connection_factory_impl.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/metrics/sparse_histogram.h" 9 #include "base/metrics/sparse_histogram.h"
10 #include "google_apis/gcm/engine/connection_handler_impl.h" 10 #include "google_apis/gcm/engine/connection_handler_impl.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 : mcs_endpoints_(mcs_endpoints), 50 : mcs_endpoints_(mcs_endpoints),
51 next_endpoint_(0), 51 next_endpoint_(0),
52 last_successful_endpoint_(0), 52 last_successful_endpoint_(0),
53 backoff_policy_(backoff_policy), 53 backoff_policy_(backoff_policy),
54 network_session_(network_session), 54 network_session_(network_session),
55 bound_net_log_( 55 bound_net_log_(
56 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), 56 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)),
57 pac_request_(NULL), 57 pac_request_(NULL),
58 connecting_(false), 58 connecting_(false),
59 waiting_for_backoff_(false), 59 waiting_for_backoff_(false),
60 waiting_for_network_change_(false),
60 logging_in_(false), 61 logging_in_(false),
61 recorder_(recorder), 62 recorder_(recorder),
62 listener_(NULL), 63 listener_(NULL),
63 weak_ptr_factory_(this) { 64 weak_ptr_factory_(this) {
64 DCHECK_GE(mcs_endpoints_.size(), 1U); 65 DCHECK_GE(mcs_endpoints_.size(), 1U);
65 } 66 }
66 67
67 ConnectionFactoryImpl::~ConnectionFactoryImpl() { 68 ConnectionFactoryImpl::~ConnectionFactoryImpl() {
68 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 69 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
69 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
70 if (pac_request_) { 70 if (pac_request_) {
71 network_session_->proxy_service()->CancelPacRequest(pac_request_); 71 network_session_->proxy_service()->CancelPacRequest(pac_request_);
72 pac_request_ = NULL; 72 pac_request_ = NULL;
73 } 73 }
74 } 74 }
75 75
76 void ConnectionFactoryImpl::Initialize( 76 void ConnectionFactoryImpl::Initialize(
77 const BuildLoginRequestCallback& request_builder, 77 const BuildLoginRequestCallback& request_builder,
78 const ConnectionHandler::ProtoReceivedCallback& read_callback, 78 const ConnectionHandler::ProtoReceivedCallback& read_callback,
79 const ConnectionHandler::ProtoSentCallback& write_callback) { 79 const ConnectionHandler::ProtoSentCallback& write_callback) {
80 DCHECK(!connection_handler_); 80 DCHECK(!connection_handler_);
81 81
82 previous_backoff_ = CreateBackoffEntry(&backoff_policy_); 82 previous_backoff_ = CreateBackoffEntry(&backoff_policy_);
83 backoff_entry_ = CreateBackoffEntry(&backoff_policy_); 83 backoff_entry_ = CreateBackoffEntry(&backoff_policy_);
84 request_builder_ = request_builder; 84 request_builder_ = request_builder;
85 85
86 net::NetworkChangeNotifier::AddIPAddressObserver(this); 86 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
87 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); 87 waiting_for_network_change_ = net::NetworkChangeNotifier::IsOffline();
88 connection_handler_ = CreateConnectionHandler( 88 connection_handler_ = CreateConnectionHandler(
89 base::TimeDelta::FromMilliseconds(kReadTimeoutMs), 89 base::TimeDelta::FromMilliseconds(kReadTimeoutMs),
90 read_callback, 90 read_callback,
91 write_callback, 91 write_callback,
92 base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback, 92 base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback,
93 weak_ptr_factory_.GetWeakPtr())).Pass(); 93 weak_ptr_factory_.GetWeakPtr())).Pass();
94 } 94 }
95 95
96 ConnectionHandler* ConnectionFactoryImpl::GetConnectionHandler() const { 96 ConnectionHandler* ConnectionFactoryImpl::GetConnectionHandler() const {
97 return connection_handler_.get(); 97 return connection_handler_.get();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 143
144 std::string ConnectionFactoryImpl::GetConnectionStateString() const { 144 std::string ConnectionFactoryImpl::GetConnectionStateString() const {
145 if (IsEndpointReachable()) 145 if (IsEndpointReachable())
146 return "CONNECTED"; 146 return "CONNECTED";
147 if (logging_in_) 147 if (logging_in_)
148 return "LOGGING IN"; 148 return "LOGGING IN";
149 if (connecting_) 149 if (connecting_)
150 return "CONNECTING"; 150 return "CONNECTING";
151 if (waiting_for_backoff_) 151 if (waiting_for_backoff_)
152 return "WAITING FOR BACKOFF"; 152 return "WAITING FOR BACKOFF";
153 if (waiting_for_network_change_)
154 return "WAITING FOR NETWORK CHANGE";
153 return "NOT CONNECTED"; 155 return "NOT CONNECTED";
154 } 156 }
155 157
156 void ConnectionFactoryImpl::SignalConnectionReset( 158 void ConnectionFactoryImpl::SignalConnectionReset(
157 ConnectionResetReason reason) { 159 ConnectionResetReason reason) {
158 // A failure can trigger multiple resets, so no need to do anything if a 160 // A failure can trigger multiple resets, so no need to do anything if a
159 // connection is already in progress. 161 // connection is already in progress.
160 if (connecting_) { 162 if (connecting_) {
161 DVLOG(1) << "Connection in progress, ignoring reset."; 163 DVLOG(1) << "Connection in progress, ignoring reset.";
162 return; 164 return;
(...skipping 12 matching lines...) Expand all
175 base::TimeDelta::FromSeconds(1), 177 base::TimeDelta::FromSeconds(1),
176 base::TimeDelta::FromHours(24), 178 base::TimeDelta::FromHours(24),
177 50); 179 50);
178 // |last_login_time_| will be reset below, before attempting the new 180 // |last_login_time_| will be reset below, before attempting the new
179 // connection. 181 // connection.
180 } 182 }
181 183
182 CloseSocket(); 184 CloseSocket();
183 DCHECK(!IsEndpointReachable()); 185 DCHECK(!IsEndpointReachable());
184 186
187 if (waiting_for_network_change_)
188 return;
189
185 // Network changes get special treatment as they can trigger a one-off canary 190 // Network changes get special treatment as they can trigger a one-off canary
186 // request that bypasses backoff (but does nothing if a connection is in 191 // request that bypasses backoff (but does nothing if a connection is in
187 // progress). Other connection reset events can be ignored as a connection 192 // progress). Other connection reset events can be ignored as a connection
188 // is already awaiting backoff expiration. 193 // is already awaiting backoff expiration.
189 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) { 194 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) {
190 DVLOG(1) << "Backoff expiration pending, ignoring reset."; 195 DVLOG(1) << "Backoff expiration pending, ignoring reset.";
191 return; 196 return;
192 } 197 }
193 198
194 if (logging_in_) { 199 if (logging_in_) {
195 // Failures prior to login completion just reuse the existing backoff entry. 200 // Failures prior to login completion just reuse the existing backoff entry.
196 logging_in_ = false; 201 logging_in_ = false;
197 backoff_entry_->InformOfRequest(false); 202 backoff_entry_->InformOfRequest(false);
198 } else if (reason == LOGIN_FAILURE || 203 } else if (reason == LOGIN_FAILURE ||
199 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { 204 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) {
200 // Failures due to login, or within the reset window of a login, restore 205 // Failures due to login, or within the reset window of a login, restore
201 // the backoff entry that was saved off at login completion time. 206 // the backoff entry that was saved off at login completion time.
202 backoff_entry_.swap(previous_backoff_); 207 backoff_entry_.swap(previous_backoff_);
203 backoff_entry_->InformOfRequest(false); 208 backoff_entry_->InformOfRequest(false);
204 } else if (reason == NETWORK_CHANGE) { 209 } else if (reason == NETWORK_CHANGE) {
205 ConnectImpl(); // Canary attempts bypass backoff without resetting it. 210 ConnectImpl(); // Canary attempts bypass backoff without resetting it.
206 return; 211 return;
207 } else { 212 } else {
208 // We shouldn't be in backoff in thise case. 213 // We shouldn't be in backoff in thise case.
209 DCHECK_EQ(0, backoff_entry_->failure_count()); 214 DCHECK_EQ(0, backoff_entry_->failure_count());
210 } 215 }
211 DCHECK(!connecting_);
212 DCHECK(!waiting_for_backoff_);
213 216
214 // At this point the last login time has been consumed or deemed irrelevant, 217 // At this point the last login time has been consumed or deemed irrelevant,
215 // reset it. 218 // reset it.
216 last_login_time_ = base::TimeTicks(); 219 last_login_time_ = base::TimeTicks();
217 220
218 Connect(); 221 Connect();
219 } 222 }
220 223
221 void ConnectionFactoryImpl::SetConnectionListener( 224 void ConnectionFactoryImpl::SetConnectionListener(
222 ConnectionListener* listener) { 225 ConnectionListener* listener) {
223 listener_ = listener; 226 listener_ = listener;
224 } 227 }
225 228
226 base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const { 229 base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const {
227 if (!backoff_entry_) 230 if (!backoff_entry_)
228 return base::TimeTicks(); 231 return base::TimeTicks();
229 return backoff_entry_->GetReleaseTime(); 232 return backoff_entry_->GetReleaseTime();
230 } 233 }
231 234
232 void ConnectionFactoryImpl::OnConnectionTypeChanged( 235 void ConnectionFactoryImpl::OnNetworkChanged(
233 net::NetworkChangeNotifier::ConnectionType type) { 236 net::NetworkChangeNotifier::ConnectionType type) {
234 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) 237 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) {
238 DVLOG(1) << "Network lost, resettion connection.";
239 waiting_for_network_change_ = true;
240
241 // Will do nothing due to |waiting_for_network_change_ == true|.
242 SignalConnectionReset(NETWORK_CHANGE);
235 return; 243 return;
244 }
236 245
237 DVLOG(1) << "Connection type changed to " << type << ", reconnecting."; 246 DVLOG(1) << "Connection type changed to " << type << ", reconnecting.";
238 247 waiting_for_network_change_ = false;
239 // The connection may have been silently dropped, attempt to reconnect.
240 SignalConnectionReset(NETWORK_CHANGE); 248 SignalConnectionReset(NETWORK_CHANGE);
241 } 249 }
242 250
243 void ConnectionFactoryImpl::OnIPAddressChanged() {
244 DVLOG(1) << "IP Address changed, reconnecting.";
245
246 // The connection may have been silently dropped, attempt to reconnect.
247 SignalConnectionReset(NETWORK_CHANGE);
248 }
249
250 GURL ConnectionFactoryImpl::GetCurrentEndpoint() const { 251 GURL ConnectionFactoryImpl::GetCurrentEndpoint() const {
251 // Note that IsEndpointReachable() returns false anytime connecting_ is true, 252 // Note that IsEndpointReachable() returns false anytime connecting_ is true,
252 // so while connecting this always uses |next_endpoint_|. 253 // so while connecting this always uses |next_endpoint_|.
253 if (IsEndpointReachable()) 254 if (IsEndpointReachable())
254 return mcs_endpoints_[last_successful_endpoint_]; 255 return mcs_endpoints_[last_successful_endpoint_];
255 return mcs_endpoints_[next_endpoint_]; 256 return mcs_endpoints_[next_endpoint_];
256 } 257 }
257 258
258 net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() { 259 net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() {
259 if (!socket_handle_.socket()) 260 if (!socket_handle_.socket())
260 return net::IPEndPoint(); 261 return net::IPEndPoint();
261 262
262 net::IPEndPoint ip_endpoint; 263 net::IPEndPoint ip_endpoint;
263 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); 264 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint);
264 if (result != net::OK) 265 if (result != net::OK)
265 return net::IPEndPoint(); 266 return net::IPEndPoint();
266 267
267 return ip_endpoint; 268 return ip_endpoint;
268 } 269 }
269 270
270 void ConnectionFactoryImpl::ConnectImpl() { 271 void ConnectionFactoryImpl::ConnectImpl() {
271 DCHECK(!IsEndpointReachable()); 272 DCHECK(!IsEndpointReachable());
272 DCHECK(!socket_handle_.socket()); 273 DCHECK(!socket_handle_.socket());
273 274
275 if (waiting_for_network_change_)
276 return;
277
274 connecting_ = true; 278 connecting_ = true;
275 GURL current_endpoint = GetCurrentEndpoint(); 279 GURL current_endpoint = GetCurrentEndpoint();
276 recorder_->RecordConnectionInitiated(current_endpoint.host()); 280 recorder_->RecordConnectionInitiated(current_endpoint.host());
277 int status = network_session_->proxy_service()->ResolveProxy( 281 int status = network_session_->proxy_service()->ResolveProxy(
278 current_endpoint, 282 current_endpoint,
279 &proxy_info_, 283 &proxy_info_,
280 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, 284 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
281 weak_ptr_factory_.GetWeakPtr()), 285 weak_ptr_factory_.GetWeakPtr()),
282 &pac_request_, 286 &pac_request_,
283 bound_net_log_); 287 bound_net_log_);
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 // the destroyed socket. 533 // the destroyed socket.
530 if (connection_handler_) 534 if (connection_handler_)
531 connection_handler_->Reset(); 535 connection_handler_->Reset();
532 536
533 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) 537 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected())
534 socket_handle_.socket()->Disconnect(); 538 socket_handle_.socket()->Disconnect();
535 socket_handle_.Reset(); 539 socket_handle_.Reset();
536 } 540 }
537 541
538 } // namespace gcm 542 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698