Index: ios/chrome/browser/web/auto_reload_controller.mm |
diff --git a/ios/chrome/browser/web/auto_reload_controller.mm b/ios/chrome/browser/web/auto_reload_controller.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..73f0453f2ce9c21a146ea9fa5eb4ac8ecd8abfe6 |
--- /dev/null |
+++ b/ios/chrome/browser/web/auto_reload_controller.mm |
@@ -0,0 +1,137 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/chrome/browser/web/auto_reload_controller.h" |
+ |
+#include <memory> |
+ |
+#include "base/ios/weak_nsobject.h" |
+#include "base/mac/bind_objc_block.h" |
+#include "base/mac/scoped_nsobject.h" |
+#include "base/timer/timer.h" |
+ |
+namespace { |
+ |
+base::TimeDelta GetAutoReloadTime(size_t reload_count) { |
+ static const int kDelaysMs[] = { |
+ 0, 5000, 30000, 60000, 300000, 600000, 1800000, |
+ }; |
+ if (reload_count >= arraysize(kDelaysMs)) |
+ reload_count = arraysize(kDelaysMs) - 1; |
+ return base::TimeDelta::FromMilliseconds(kDelaysMs[reload_count]); |
+} |
+ |
+} // namespace |
+ |
+@interface AutoReloadController () { |
+ GURL _failedUrl; |
+ int _reloadCount; |
+ BOOL _shouldReload; |
+ BOOL _online; |
+ id<AutoReloadDelegate> _delegate; |
+ std::unique_ptr<base::Timer> _timer; |
+} |
+ |
+// This method is called when the system transitions to offline from online, |
+// possibly causing a paused reload timer to start. |
+- (void)transitionedToOffline; |
+ |
+// This method is called when the system transitions from online to offline, |
+// possibly pausing the reload timer. |
+- (void)transitionedToOnline; |
+ |
+// This method is called to actually start the reload timer. |
+- (void)startTimer; |
+ |
+// This method is called back from the reload timer when it fires. |
+- (void)timerFired; |
+ |
+@end |
+ |
+@implementation AutoReloadController |
+ |
+- (id)initWithDelegate:(id<AutoReloadDelegate>)delegate |
+ onlineStatus:(BOOL)online { |
+ if ((self = [super init])) { |
+ _delegate = delegate; |
+ _timer.reset(new base::Timer(false /* don't retain user task */, |
+ false /* don't repeat automatically */)); |
+ _online = online; |
+ } |
+ return self; |
+} |
+ |
+- (void)loadStartedForURL:(const GURL&)url { |
+ if (_timer->IsRunning()) { |
+ // Stop the timer, since the starting load was not started by this class and |
+ // it would be bad to replace another load. |
+ _timer->Stop(); |
+ } |
+ if (url != _failedUrl) { |
+ // Changed URLs, reset the backoff counter. |
+ _reloadCount = 0; |
+ } |
+} |
+ |
+- (void)loadFinishedForURL:(const GURL&)url wasPost:(BOOL)wasPost { |
+ DCHECK(!_timer->IsRunning()); |
+} |
+ |
+- (void)loadFailedForURL:(const GURL&)url wasPost:(BOOL)wasPost { |
+ DCHECK(!_timer->IsRunning()); |
+ if (wasPost) |
+ return; |
+ _failedUrl = url; |
+ if (_online) |
+ [self startTimer]; |
+ else |
+ _shouldReload = true; |
+} |
+ |
+- (void)networkStateChangedToOnline:(BOOL)online { |
+ if (!online && _online) |
+ [self transitionedToOffline]; |
+ else if (online && !_online) |
+ [self transitionedToOnline]; |
+ _online = online; |
+} |
+ |
+- (void)setTimerForTesting:(std::unique_ptr<base::Timer>)timer { |
+ _timer.reset(timer.release()); |
+} |
+ |
+- (void)startTimer { |
+ base::WeakNSObject<AutoReloadController> weakSelf(self); |
+ base::TimeDelta delay = GetAutoReloadTime(_reloadCount); |
+ _timer->Start(FROM_HERE, delay, base::BindBlock(^{ |
+ base::scoped_nsobject<AutoReloadController> strongSelf( |
+ [weakSelf retain]); |
+ // self owns the timer owns this closure, so self must outlive |
+ // this closure. |
+ DCHECK(strongSelf); |
+ [strongSelf timerFired]; |
+ })); |
+} |
+ |
+- (void)transitionedToOffline { |
+ DCHECK(!_shouldReload); |
+ if (_timer->IsRunning()) { |
+ _shouldReload = true; |
+ _timer->Stop(); |
+ } |
+} |
+ |
+- (void)transitionedToOnline { |
+ if (_shouldReload) { |
+ _shouldReload = false; |
+ [self startTimer]; |
+ } |
+} |
+ |
+- (void)timerFired { |
+ _reloadCount++; |
+ [_delegate reload]; |
+} |
+ |
+@end |