| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "chrome/browser/chromeos/night_light/night_light_client.h" | 5 #include "chrome/browser/chromeos/night_light/night_light_client.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 8 |
| 7 #include "ash/public/interfaces/constants.mojom.h" | 9 #include "ash/public/interfaces/constants.mojom.h" |
| 10 #include "base/time/clock.h" |
| 8 #include "content/public/common/service_manager_connection.h" | 11 #include "content/public/common/service_manager_connection.h" |
| 9 #include "services/service_manager/public/cpp/connector.h" | 12 #include "services/service_manager/public/cpp/connector.h" |
| 10 | 13 |
| 11 namespace { | 14 namespace { |
| 12 | 15 |
| 13 // Delay to wait for a response to our geolocation request, if we get a response | 16 // Delay to wait for a response to our geolocation request, if we get a response |
| 14 // after which, we will consider the request a failure. | 17 // after which, we will consider the request a failure. |
| 15 constexpr base::TimeDelta kGeolocationRequestTimeout = | 18 constexpr base::TimeDelta kGeolocationRequestTimeout = |
| 16 base::TimeDelta::FromSeconds(60); | 19 base::TimeDelta::FromSeconds(60); |
| 17 | 20 |
| 18 // Minimum delay to wait to fire a new request after a previous one failing. | 21 // Minimum delay to wait to fire a new request after a previous one failing. |
| 19 constexpr base::TimeDelta kMinimumDelayAfterFailure = | 22 constexpr base::TimeDelta kMinimumDelayAfterFailure = |
| 20 base::TimeDelta::FromSeconds(60); | 23 base::TimeDelta::FromSeconds(60); |
| 21 | 24 |
| 22 // Delay to wait to fire a new request after a previous one succeeding. | 25 // Delay to wait to fire a new request after a previous one succeeding. |
| 23 constexpr base::TimeDelta kNextRequestDelayAfterSuccess = | 26 constexpr base::TimeDelta kNextRequestDelayAfterSuccess = |
| 24 base::TimeDelta::FromDays(1); | 27 base::TimeDelta::FromDays(1); |
| 25 | 28 |
| 26 } // namespace | 29 } // namespace |
| 27 | 30 |
| 28 NightLightClient::NightLightClient( | 31 NightLightClient::NightLightClient( |
| 29 net::URLRequestContextGetter* url_context_getter) | 32 net::URLRequestContextGetter* url_context_getter) |
| 30 : provider_( | 33 : provider_( |
| 31 url_context_getter, | 34 url_context_getter, |
| 32 chromeos::SimpleGeolocationProvider::DefaultGeolocationProviderURL()), | 35 chromeos::SimpleGeolocationProvider::DefaultGeolocationProviderURL()), |
| 33 binding_(this), | 36 binding_(this), |
| 34 backoff_delay_(kMinimumDelayAfterFailure) {} | 37 backoff_delay_(kMinimumDelayAfterFailure), |
| 38 timer_(base::MakeUnique<base::OneShotTimer>()) {} |
| 35 | 39 |
| 36 NightLightClient::~NightLightClient() {} | 40 NightLightClient::~NightLightClient() {} |
| 37 | 41 |
| 38 void NightLightClient::Start() { | 42 void NightLightClient::Start() { |
| 39 if (!night_light_controller_) { | 43 if (!night_light_controller_) { |
| 40 service_manager::Connector* connector = | 44 service_manager::Connector* connector = |
| 41 content::ServiceManagerConnection::GetForProcess()->GetConnector(); | 45 content::ServiceManagerConnection::GetForProcess()->GetConnector(); |
| 42 connector->BindInterface(ash::mojom::kServiceName, | 46 connector->BindInterface(ash::mojom::kServiceName, |
| 43 &night_light_controller_); | 47 &night_light_controller_); |
| 44 } | 48 } |
| 45 ash::mojom::NightLightClientPtr client; | 49 ash::mojom::NightLightClientPtr client; |
| 46 binding_.Bind(mojo::MakeRequest(&client)); | 50 binding_.Bind(mojo::MakeRequest(&client)); |
| 47 night_light_controller_->SetClient(std::move(client)); | 51 night_light_controller_->SetClient(std::move(client)); |
| 48 } | 52 } |
| 49 | 53 |
| 50 void NightLightClient::OnScheduleTypeChanged( | 54 void NightLightClient::OnScheduleTypeChanged( |
| 51 ash::mojom::NightLightController::ScheduleType new_type) { | 55 ash::mojom::NightLightController::ScheduleType new_type) { |
| 52 if (new_type == | 56 if (new_type != |
| 53 ash::mojom::NightLightController::ScheduleType::kSunsetToSunrise) { | 57 ash::mojom::NightLightController::ScheduleType::kSunsetToSunrise) { |
| 54 // Schedule an immediate request. | |
| 55 using_geoposition_ = true; | |
| 56 ScheduleNextRequest(base::TimeDelta::FromSeconds(0)); | |
| 57 } else { | |
| 58 using_geoposition_ = false; | 58 using_geoposition_ = false; |
| 59 timer_.Stop(); | 59 timer_->Stop(); |
| 60 return; |
| 60 } | 61 } |
| 62 |
| 63 using_geoposition_ = true; |
| 64 // No need to request a new position if we already have a valid one from a |
| 65 // request less than kNextRequestDelayAfterSuccess ago. |
| 66 base::Time now = GetNow(); |
| 67 if ((now - last_successful_geo_request_time_) < |
| 68 kNextRequestDelayAfterSuccess) { |
| 69 // Use the current valid position to update NightLightController. |
| 70 SendCurrentGeoposition(); |
| 71 } |
| 72 |
| 73 // Next request is either immediate or kNextRequestDelayAfterSuccess later |
| 74 // than the last success time, whichever is greater. |
| 75 ScheduleNextRequest(std::max( |
| 76 base::TimeDelta::FromSeconds(0), |
| 77 last_successful_geo_request_time_ + kNextRequestDelayAfterSuccess - now)); |
| 78 } |
| 79 |
| 80 // static |
| 81 base::TimeDelta NightLightClient::GetNextRequestDelayAfterSuccessForTesting() { |
| 82 return kNextRequestDelayAfterSuccess; |
| 61 } | 83 } |
| 62 | 84 |
| 63 void NightLightClient::SetNightLightControllerPtrForTesting( | 85 void NightLightClient::SetNightLightControllerPtrForTesting( |
| 64 ash::mojom::NightLightControllerPtr controller) { | 86 ash::mojom::NightLightControllerPtr controller) { |
| 65 night_light_controller_ = std::move(controller); | 87 night_light_controller_ = std::move(controller); |
| 66 } | 88 } |
| 67 | 89 |
| 68 void NightLightClient::FlushNightLightControllerForTesting() { | 90 void NightLightClient::FlushNightLightControllerForTesting() { |
| 69 night_light_controller_.FlushForTesting(); | 91 night_light_controller_.FlushForTesting(); |
| 70 } | 92 } |
| 71 | 93 |
| 94 void NightLightClient::SetTimerForTesting( |
| 95 std::unique_ptr<base::OneShotTimer> timer) { |
| 96 timer_ = std::move(timer); |
| 97 } |
| 98 |
| 99 void NightLightClient::SetClockForTesting(base::Clock* clock) { |
| 100 clock_ = clock; |
| 101 } |
| 102 |
| 72 void NightLightClient::OnGeoposition(const chromeos::Geoposition& position, | 103 void NightLightClient::OnGeoposition(const chromeos::Geoposition& position, |
| 73 bool server_error, | 104 bool server_error, |
| 74 const base::TimeDelta elapsed) { | 105 const base::TimeDelta elapsed) { |
| 75 if (!using_geoposition_) { | 106 if (!using_geoposition_) { |
| 76 // A response might arrive after the schedule type is no longer "sunset to | 107 // A response might arrive after the schedule type is no longer "sunset to |
| 77 // sunrise", which means we should not push any positions to the | 108 // sunrise", which means we should not push any positions to the |
| 78 // NightLightController. | 109 // NightLightController. |
| 79 return; | 110 return; |
| 80 } | 111 } |
| 81 | 112 |
| 82 if (server_error || !position.Valid() || | 113 if (server_error || !position.Valid() || |
| 83 elapsed > kGeolocationRequestTimeout) { | 114 elapsed > kGeolocationRequestTimeout) { |
| 84 // Don't send invalid positions to ash. | 115 // Don't send invalid positions to ash. |
| 85 // On failure, we schedule another request after the current backoff delay. | 116 // On failure, we schedule another request after the current backoff delay. |
| 86 ScheduleNextRequest(backoff_delay_); | 117 ScheduleNextRequest(backoff_delay_); |
| 87 | 118 |
| 88 // If another failure occurs next, our backoff delay should double. | 119 // If another failure occurs next, our backoff delay should double. |
| 89 backoff_delay_ *= 2; | 120 backoff_delay_ *= 2; |
| 90 return; | 121 return; |
| 91 } | 122 } |
| 92 | 123 |
| 93 night_light_controller_->SetCurrentGeoposition( | 124 last_successful_geo_request_time_ = GetNow(); |
| 94 ash::mojom::SimpleGeoposition::New(position.latitude, | 125 |
| 95 position.longitude)); | 126 latitude_ = position.latitude; |
| 127 longitude_ = position.longitude; |
| 128 SendCurrentGeoposition(); |
| 96 | 129 |
| 97 // On success, reset the backoff delay to its minimum value, and schedule | 130 // On success, reset the backoff delay to its minimum value, and schedule |
| 98 // another request. | 131 // another request. |
| 99 backoff_delay_ = kMinimumDelayAfterFailure; | 132 backoff_delay_ = kMinimumDelayAfterFailure; |
| 100 ScheduleNextRequest(kNextRequestDelayAfterSuccess); | 133 ScheduleNextRequest(kNextRequestDelayAfterSuccess); |
| 101 } | 134 } |
| 102 | 135 |
| 136 base::Time NightLightClient::GetNow() const { |
| 137 return clock_ ? clock_->Now() : base::Time::Now(); |
| 138 } |
| 139 |
| 140 void NightLightClient::SendCurrentGeoposition() { |
| 141 night_light_controller_->SetCurrentGeoposition( |
| 142 ash::mojom::SimpleGeoposition::New(latitude_, longitude_)); |
| 143 } |
| 144 |
| 103 void NightLightClient::ScheduleNextRequest(base::TimeDelta delay) { | 145 void NightLightClient::ScheduleNextRequest(base::TimeDelta delay) { |
| 104 timer_.Start(FROM_HERE, delay, this, &NightLightClient::RequestGeoposition); | 146 timer_->Start(FROM_HERE, delay, this, &NightLightClient::RequestGeoposition); |
| 105 } | 147 } |
| 106 | 148 |
| 107 void NightLightClient::RequestGeoposition() { | 149 void NightLightClient::RequestGeoposition() { |
| 108 provider_.RequestGeolocation( | 150 provider_.RequestGeolocation( |
| 109 kGeolocationRequestTimeout, false /* send_wifi_access_points */, | 151 kGeolocationRequestTimeout, false /* send_wifi_access_points */, |
| 110 false /* send_cell_towers */, | 152 false /* send_cell_towers */, |
| 111 base::Bind(&NightLightClient::OnGeoposition, base::Unretained(this))); | 153 base::Bind(&NightLightClient::OnGeoposition, base::Unretained(this))); |
| 112 } | 154 } |
| OLD | NEW |