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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/net/network_portal_detector_strategy.h" 6 7 #include "base/logging.h" 8 #include "chromeos/network/network_handler.h" 9 #include "chromeos/network/network_state.h" 10 #include "chromeos/network/network_state_handler.h" 11 12 namespace chromeos { 13 14 namespace { 15 16 const NetworkState* DefaultNetwork() { 17 return NetworkHandler::Get()->network_state_handler()->DefaultNetwork(); 18 } 19 20 // TODO (ygorshenin@): reuse net::BackoffEntry for strategies. 21 22 class LoginScreenStrategy : public PortalDetectorStrategy { 23 public: 24 static const int kMaxAttempts = 3; 25 static const int kDelayBetweenAttemptsSec = 3; 26 static const int kBaseAttemptTimeoutSec = 5; 27 28 LoginScreenStrategy() {} 29 virtual ~LoginScreenStrategy() {} 30 31 protected: 32 // PortalDetectorStrategy overrides: 33 virtual StrategyId Id() const OVERRIDE { return STRATEGY_ID_LOGIN_SCREEN; } 34 virtual bool CanPerformAttemptImpl() OVERRIDE { 35 return delegate_->AttemptCount() < kMaxAttempts; 36 } 37 virtual base::TimeDelta GetDelayTillNextAttemptImpl() OVERRIDE { 38 return AdjustDelay(base::TimeDelta::FromSeconds(kDelayBetweenAttemptsSec)); 39 } 40 virtual base::TimeDelta GetNextAttemptTimeoutImpl() OVERRIDE { 41 int timeout = DefaultNetwork() 42 ? (delegate_->AttemptCount() + 1) * kBaseAttemptTimeoutSec 43 : kBaseAttemptTimeoutSec; 44 return base::TimeDelta::FromSeconds(timeout); 45 } 46 47 private: 48 DISALLOW_COPY_AND_ASSIGN(LoginScreenStrategy); 49 }; 50 51 class ErrorScreenStrategy : public PortalDetectorStrategy { 52 public: 53 static const int kDelayBetweenAttemptsSec = 3; 54 static const int kAttemptTimeoutSec = 15; 55 56 ErrorScreenStrategy() {} 57 virtual ~ErrorScreenStrategy() {} 58 59 protected: 60 // PortalDetectorStrategy overrides: 61 virtual StrategyId Id() const OVERRIDE { return STRATEGY_ID_ERROR_SCREEN; } 62 virtual bool CanPerformAttemptImpl() OVERRIDE { return true; } 63 virtual bool CanPerformAttemptAfterDetectionImpl() OVERRIDE { return true; } 64 virtual base::TimeDelta GetDelayTillNextAttemptImpl() OVERRIDE { 65 return AdjustDelay(base::TimeDelta::FromSeconds(kDelayBetweenAttemptsSec)); 66 } 67 virtual base::TimeDelta GetNextAttemptTimeoutImpl() OVERRIDE { 68 return base::TimeDelta::FromSeconds(kAttemptTimeoutSec); 69 } 70 71 private: 72 DISALLOW_COPY_AND_ASSIGN(ErrorScreenStrategy); 73 }; 74 75 class SessionStrategy : public PortalDetectorStrategy { 76 public: 77 static const int kFastDelayBetweenAttemptsSec = 1; 78 static const int kFastAttemptTimeoutSec = 3; 79 static const int kMaxFastAttempts = 3; 80 81 static const int kNormalDelayBetweenAttemptsSec = 10; 82 static const int kNormalAttemptTimeoutSec = 5; 83 static const int kMaxNormalAttempts = 3; 84 85 static const int kSlowDelayBetweenAttemptsSec = 2 * 60; 86 static const int kSlowAttemptTimeoutSec = 5; 87 88 SessionStrategy() {} 89 virtual ~SessionStrategy() {} 90 91 protected: 92 virtual StrategyId Id() const OVERRIDE { return STRATEGY_ID_SESSION; } 93 virtual bool CanPerformAttemptImpl() OVERRIDE { return true; } 94 virtual bool CanPerformAttemptAfterDetectionImpl() OVERRIDE { return true; } 95 virtual base::TimeDelta GetDelayTillNextAttemptImpl() OVERRIDE { 96 int delay; 97 if (IsFastAttempt()) 98 delay = kFastDelayBetweenAttemptsSec; 99 else if (IsNormalAttempt()) 100 delay = kNormalDelayBetweenAttemptsSec; 101 else 102 delay = kSlowDelayBetweenAttemptsSec; 103 return AdjustDelay(base::TimeDelta::FromSeconds(delay)); 104 } 105 virtual base::TimeDelta GetNextAttemptTimeoutImpl() OVERRIDE { 106 int timeout; 107 if (IsFastAttempt()) 108 timeout = kFastAttemptTimeoutSec; 109 else if (IsNormalAttempt()) 110 timeout = kNormalAttemptTimeoutSec; 111 else 112 timeout = kSlowAttemptTimeoutSec; 113 return base::TimeDelta::FromSeconds(timeout); 114 } 115 116 private: 117 bool IsFastAttempt() { 118 return delegate_->AttemptCount() < kMaxFastAttempts; 119 } 120 121 bool IsNormalAttempt() { 122 return delegate_->AttemptCount() < kMaxFastAttempts + kMaxNormalAttempts; 123 } 124 125 DISALLOW_COPY_AND_ASSIGN(SessionStrategy); 126 }; 127 128 } // namespace 129 130 // PortalDetectorStrategy ----------------------------------------------------- 131 132 // static 133 base::TimeDelta PortalDetectorStrategy::delay_till_next_attempt_for_testing_; 134 135 // static 136 bool PortalDetectorStrategy::delay_till_next_attempt_for_testing_initialized_ = 137 false; 138 139 // static 140 base::TimeDelta PortalDetectorStrategy::next_attempt_timeout_for_testing_; 141 142 // static 143 bool PortalDetectorStrategy::next_attempt_timeout_for_testing_initialized_ = 144 false; 145 146 PortalDetectorStrategy::PortalDetectorStrategy() : delegate_(NULL) {} 147 148 PortalDetectorStrategy::~PortalDetectorStrategy() {} 149 150 // statc 151 scoped_ptr<PortalDetectorStrategy> PortalDetectorStrategy::CreateById( 152 StrategyId id) { 153 switch (id) { 154 case STRATEGY_ID_LOGIN_SCREEN: 155 return scoped_ptr<PortalDetectorStrategy>(new LoginScreenStrategy()); 156 case STRATEGY_ID_ERROR_SCREEN: 157 return scoped_ptr<PortalDetectorStrategy>(new ErrorScreenStrategy()); 158 case STRATEGY_ID_SESSION: 159 return scoped_ptr<PortalDetectorStrategy>(new SessionStrategy()); 160 default: 161 NOTREACHED(); 162 return scoped_ptr<PortalDetectorStrategy>( 163 static_cast<PortalDetectorStrategy*>(NULL)); 164 } 165 } 166 167 bool PortalDetectorStrategy::CanPerformAttempt() { 168 return CanPerformAttemptImpl(); 169 } 170 171 bool PortalDetectorStrategy::CanPerformAttemptAfterDetection() { 172 return CanPerformAttemptAfterDetectionImpl(); 173 } 174 175 base::TimeDelta PortalDetectorStrategy::GetDelayTillNextAttempt() { 176 if (delay_till_next_attempt_for_testing_initialized_) 177 return delay_till_next_attempt_for_testing_; 178 return GetDelayTillNextAttemptImpl(); 179 } 180 181 base::TimeDelta PortalDetectorStrategy::GetNextAttemptTimeout() { 182 if (next_attempt_timeout_for_testing_initialized_) 183 return next_attempt_timeout_for_testing_; 184 return GetNextAttemptTimeoutImpl(); 185 } 186 187 bool PortalDetectorStrategy::CanPerformAttemptImpl() { return false; } 188 189 bool PortalDetectorStrategy::CanPerformAttemptAfterDetectionImpl() { 190 return false; 191 } 192 193 base::TimeDelta PortalDetectorStrategy::GetDelayTillNextAttemptImpl() { 194 return base::TimeDelta(); 195 } 196 197 base::TimeDelta PortalDetectorStrategy::GetNextAttemptTimeoutImpl() { 198 return base::TimeDelta(); 199 } 200 201 base::TimeDelta PortalDetectorStrategy::AdjustDelay( 202 const base::TimeDelta& delay) { 203 if (!delegate_->AttemptCount()) 204 return base::TimeDelta(); 205 206 base::TimeTicks now = delegate_->GetCurrentTimeTicks(); 207 base::TimeDelta elapsed; 208 if (now > delegate_->AttemptStartTime()) 209 elapsed = now - delegate_->AttemptStartTime(); 210 if (delay > elapsed) 211 return delay - elapsed; 212 return base::TimeDelta(); 213 } 214 215 } // namespace chromeos 216