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 "chromeos/network/portal_detector/network_portal_detector_strategy.h"
6 
7 #include "base/logging.h"
8 #include "base/macros.h"
9 #include "chromeos/network/network_handler.h"
10 #include "chromeos/network/network_state.h"
11 #include "chromeos/network/network_state_handler.h"
12 
13 namespace chromeos {
14 
15 namespace {
16 
DefaultNetwork()17 const NetworkState* DefaultNetwork() {
18   return NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
19 }
20 
21 class LoginScreenStrategy : public PortalDetectorStrategy {
22  public:
23   static const int kBaseAttemptTimeoutSec = 5;
24   static const int kMaxAttemptTimeoutSec = 30;
25 
LoginScreenStrategy(PortalDetectorStrategy::Delegate * delegate)26   explicit LoginScreenStrategy(PortalDetectorStrategy::Delegate* delegate)
27       : PortalDetectorStrategy(delegate) {}
28   ~LoginScreenStrategy() override = default;
29 
30  protected:
31   // PortalDetectorStrategy overrides:
Id() const32   StrategyId Id() const override { return STRATEGY_ID_LOGIN_SCREEN; }
GetNextAttemptTimeoutImpl()33   base::TimeDelta GetNextAttemptTimeoutImpl() override {
34     if (DefaultNetwork() && delegate_->NoResponseResultCount() != 0) {
35       int timeout = kMaxAttemptTimeoutSec;
36       if (kMaxAttemptTimeoutSec / (delegate_->NoResponseResultCount() + 1) >
37           kBaseAttemptTimeoutSec) {
38         timeout =
39             kBaseAttemptTimeoutSec * (delegate_->NoResponseResultCount() + 1);
40       }
41       return base::TimeDelta::FromSeconds(timeout);
42     }
43     return base::TimeDelta::FromSeconds(kBaseAttemptTimeoutSec);
44   }
45 
46  private:
47   DISALLOW_COPY_AND_ASSIGN(LoginScreenStrategy);
48 };
49 
50 class ErrorScreenStrategy : public PortalDetectorStrategy {
51  public:
52   static const int kAttemptTimeoutSec = 15;
53 
ErrorScreenStrategy(PortalDetectorStrategy::Delegate * delegate)54   explicit ErrorScreenStrategy(PortalDetectorStrategy::Delegate* delegate)
55       : PortalDetectorStrategy(delegate) {}
56   ~ErrorScreenStrategy() override = default;
57 
58  protected:
59   // PortalDetectorStrategy overrides:
Id() const60   StrategyId Id() const override { return STRATEGY_ID_ERROR_SCREEN; }
GetNextAttemptTimeoutImpl()61   base::TimeDelta GetNextAttemptTimeoutImpl() override {
62     return base::TimeDelta::FromSeconds(kAttemptTimeoutSec);
63   }
64 
65  private:
66   DISALLOW_COPY_AND_ASSIGN(ErrorScreenStrategy);
67 };
68 
69 class SessionStrategy : public PortalDetectorStrategy {
70  public:
71   static const int kMaxFastAttempts = 3;
72   static const int kFastAttemptTimeoutSec = 3;
73   static const int kSlowAttemptTimeoutSec = 5;
74 
SessionStrategy(PortalDetectorStrategy::Delegate * delegate)75   explicit SessionStrategy(PortalDetectorStrategy::Delegate* delegate)
76       : PortalDetectorStrategy(delegate) {}
77   ~SessionStrategy() override = default;
78 
79  protected:
Id() const80   StrategyId Id() const override { return STRATEGY_ID_SESSION; }
GetNextAttemptTimeoutImpl()81   base::TimeDelta GetNextAttemptTimeoutImpl() override {
82     int timeout;
83     if (delegate_->NoResponseResultCount() < kMaxFastAttempts)
84       timeout = kFastAttemptTimeoutSec;
85     else
86       timeout = kSlowAttemptTimeoutSec;
87     return base::TimeDelta::FromSeconds(timeout);
88   }
89 
90  private:
91   DISALLOW_COPY_AND_ASSIGN(SessionStrategy);
92 };
93 
94 }  // namespace
95 
96 // PortalDetectorStrategy::Delegate --------------------------------------------
97 
98 PortalDetectorStrategy::Delegate::~Delegate() = default;
99 
100 // PortalDetectorStrategy -----------------------------------------------------
101 
102 // static
103 base::TimeDelta PortalDetectorStrategy::delay_till_next_attempt_for_testing_;
104 
105 // static
106 bool PortalDetectorStrategy::delay_till_next_attempt_for_testing_initialized_ =
107     false;
108 
109 // static
110 base::TimeDelta PortalDetectorStrategy::next_attempt_timeout_for_testing_;
111 
112 // static
113 bool PortalDetectorStrategy::next_attempt_timeout_for_testing_initialized_ =
114     false;
115 
PortalDetectorStrategy(Delegate * delegate)116 PortalDetectorStrategy::PortalDetectorStrategy(Delegate* delegate)
117     : delegate_(delegate) {
118   // First |policy_.num_errors_to_ignore| attempts with the same
119   // result are performed with |policy_.initial_delay_ms| between
120   // them. Delay before every consecutive attempt is multplied by
121   // |policy_.multiply_factor_|. Also, |policy_.jitter_factor| is used
122   // for each delay.
123   policy_.num_errors_to_ignore = 3;
124   policy_.initial_delay_ms = 600;
125   policy_.multiply_factor = 2.0;
126   policy_.jitter_factor = 0.3;
127   policy_.maximum_backoff_ms = 2 * 60 * 1000;
128   policy_.entry_lifetime_ms = -1;
129   policy_.always_use_initial_delay = true;
130   backoff_entry_.reset(new net::BackoffEntry(&policy_, delegate_));
131 }
132 
133 PortalDetectorStrategy::~PortalDetectorStrategy() = default;
134 
135 // static
CreateById(StrategyId id,Delegate * delegate)136 std::unique_ptr<PortalDetectorStrategy> PortalDetectorStrategy::CreateById(
137     StrategyId id,
138     Delegate* delegate) {
139   switch (id) {
140     case STRATEGY_ID_LOGIN_SCREEN:
141       return std::make_unique<LoginScreenStrategy>(delegate);
142     case STRATEGY_ID_ERROR_SCREEN:
143       return std::make_unique<ErrorScreenStrategy>(delegate);
144     case STRATEGY_ID_SESSION:
145       return std::make_unique<SessionStrategy>(delegate);
146   }
147   NOTREACHED();
148   return nullptr;
149 }
150 
GetDelayTillNextAttempt()151 base::TimeDelta PortalDetectorStrategy::GetDelayTillNextAttempt() {
152   if (delay_till_next_attempt_for_testing_initialized_)
153     return delay_till_next_attempt_for_testing_;
154   return backoff_entry_->GetTimeUntilRelease();
155 }
156 
GetNextAttemptTimeout()157 base::TimeDelta PortalDetectorStrategy::GetNextAttemptTimeout() {
158   if (next_attempt_timeout_for_testing_initialized_)
159     return next_attempt_timeout_for_testing_;
160   return GetNextAttemptTimeoutImpl();
161 }
162 
Reset()163 void PortalDetectorStrategy::Reset() {
164   backoff_entry_->Reset();
165 }
166 
SetPolicyAndReset(const net::BackoffEntry::Policy & policy)167 void PortalDetectorStrategy::SetPolicyAndReset(
168     const net::BackoffEntry::Policy& policy) {
169   policy_ = policy;
170   backoff_entry_.reset(new net::BackoffEntry(&policy_, delegate_));
171 }
172 
OnDetectionCompleted()173 void PortalDetectorStrategy::OnDetectionCompleted() {
174   backoff_entry_->InformOfRequest(false);
175 }
176 
177 }  // namespace chromeos
178