Migrate geoposition code in night light.

This is an intermediate step to migrating NightLightController to
ScheduledFeature. It removes all geo-related code from night light
and uses GeolocationController instead (which is what ScheduledFeature
uses). The internals of NightLightController more closely resemble
ScheduledFeature now.

There are no major differences between GeolocationController and night
light's geo-related code, so it can be substituted without any
behavioral changes.

Bug: b:289276024
Change-Id: I506579eb523be7ecf62fd4191317ee7b9e0848a5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4886897
Reviewed-by: Ahmed Fakhry <[email protected]>
Reviewed-by: Xiyuan Xia <[email protected]>
Commit-Queue: Eric Sum <[email protected]>
Reviewed-by: David Trainor <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1213950}
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index aceda87..d991495b 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -2213,10 +2213,6 @@
     "net/xdr_manager.h",
     "network_change_manager_client.cc",
     "network_change_manager_client.h",
-    "night_light/night_light_client.cc",
-    "night_light/night_light_client.h",
-    "night_light/night_light_client_impl.cc",
-    "night_light/night_light_client_impl.h",
     "note_taking_controller_client.cc",
     "note_taking_controller_client.h",
     "note_taking_helper.cc",
@@ -5608,7 +5604,6 @@
     "net/system_proxy_manager_unittest.cc",
     "net/traffic_counters_handler_unittest.cc",
     "network_change_manager_client_unittest.cc",
-    "night_light/night_light_client_impl_unittest.cc",
     "note_taking_helper_unittest.cc",
     "notifications/debugd_notification_handler_unittest.cc",
     "notifications/deprecation_notification_controller_unittest.cc",
diff --git a/chrome/browser/ash/night_light/OWNERS b/chrome/browser/ash/night_light/OWNERS
deleted file mode 100644
index 111b3ba..0000000
--- a/chrome/browser/ash/night_light/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
[email protected]
diff --git a/chrome/browser/ash/night_light/night_light_client.cc b/chrome/browser/ash/night_light/night_light_client.cc
deleted file mode 100644
index e94e46af..0000000
--- a/chrome/browser/ash/night_light/night_light_client.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ash/night_light/night_light_client.h"
-#include "base/check_op.h"
-
-namespace ash {
-
-static NightLightClient* g_night_light_client = nullptr;
-
-NightLightClient::NightLightClient() {
-  CHECK_EQ(g_night_light_client, nullptr);
-  g_night_light_client = this;
-}
-
-NightLightClient::~NightLightClient() {
-  CHECK_NE(g_night_light_client, nullptr);
-  g_night_light_client = nullptr;
-}
-
-NightLightClient* NightLightClient::Get() {
-  CHECK_NE(g_night_light_client, nullptr);
-  return g_night_light_client;
-}
-
-}  // namespace ash
diff --git a/chrome/browser/ash/night_light/night_light_client.h b/chrome/browser/ash/night_light/night_light_client.h
deleted file mode 100644
index 4da0e95..0000000
--- a/chrome/browser/ash/night_light/night_light_client.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ASH_NIGHT_LIGHT_NIGHT_LIGHT_CLIENT_H_
-#define CHROME_BROWSER_ASH_NIGHT_LIGHT_NIGHT_LIGHT_CLIENT_H_
-
-namespace ash {
-
-// Periodically requests the IP-based geolocation and provides it to the
-// NightLightController running in ash.
-class NightLightClient {
- public:
-  virtual ~NightLightClient();
-
-  // Starts watching changes in the Night Light schedule type in order to begin
-  // periodically pushing user's IP-based geoposition to NightLightController as
-  // long as the type is set to "sunset to sunrise" or "custom".
-  virtual void Start() = 0;
-
-  // This class should respect the system geolocation permission. When the
-  // permission is disabled, no requests should be dispatched.
-  // Called from `ash::Preferences::ApplyPreferences()`.
-  virtual void OnSystemGeolocationPermissionChanged(bool enabled) = 0;
-
-  // Returns global NightLightClient if created or nullptr.
-  static NightLightClient* Get();
-
- protected:
-  NightLightClient();
-
- private:
-  // Virtual so that it can be overriden by a fake implementation in unit tests
-  // that doesn't request actual geopositions.
-  virtual void RequestGeoposition() = 0;
-};
-
-}  // namespace ash
-
-#endif  // CHROME_BROWSER_ASH_NIGHT_LIGHT_NIGHT_LIGHT_CLIENT_H_
diff --git a/chrome/browser/ash/night_light/night_light_client_impl.cc b/chrome/browser/ash/night_light/night_light_client_impl.cc
deleted file mode 100644
index f952d3d..0000000
--- a/chrome/browser/ash/night_light/night_light_client_impl.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ash/night_light/night_light_client_impl.h"
-
-#include <algorithm>
-
-#include "ash/public/cpp/schedule_enums.h"
-#include "ash/system/geolocation/geolocation_controller.h"
-#include "base/functional/bind.h"
-#include "base/logging.h"
-#include "base/time/clock.h"
-#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-namespace ash {
-
-namespace {
-
-// Delay to wait for a response to our geolocation request, if we get a response
-// after which, we will consider the request a failure.
-constexpr base::TimeDelta kGeolocationRequestTimeout = base::Seconds(60);
-
-// Minimum delay to wait to fire a new request after a previous one failing.
-constexpr base::TimeDelta kMinimumDelayAfterFailure = base::Seconds(60);
-
-// Delay to wait to fire a new request after a previous one succeeding.
-constexpr base::TimeDelta kNextRequestDelayAfterSuccess = base::Days(1);
-
-}  // namespace
-
-NightLightClientImpl::NightLightClientImpl(
-    const SimpleGeolocationProvider::Delegate* delegate,
-    scoped_refptr<network::SharedURLLoaderFactory> factory)
-    : provider_(
-          delegate,
-          std::move(factory),
-          ash::SimpleGeolocationProvider::DefaultGeolocationProviderURL()),
-      night_light_controller_(ash::NightLightController::GetInstance()),
-      backoff_delay_(kMinimumDelayAfterFailure),
-      timer_(std::make_unique<base::OneShotTimer>()) {}
-
-NightLightClientImpl::~NightLightClientImpl() {
-  if (night_light_controller_) {
-    night_light_controller_->RemoveObserver(this);
-  }
-  ash::system::TimezoneSettings::GetInstance()->RemoveObserver(this);
-}
-
-void NightLightClientImpl::Start() {
-  auto* timezone_settings = ash::system::TimezoneSettings::GetInstance();
-  current_timezone_id_ = timezone_settings->GetCurrentTimezoneID();
-  timezone_settings->AddObserver(this);
-  night_light_controller_->AddObserver(this);
-}
-
-void NightLightClientImpl::OnSystemGeolocationPermissionChanged(bool enabled) {
-  system_geolocation_permission_enabled_ = enabled;
-
-  if (!enabled) {
-    // Reset backoff_delay_ to it's minimum value.
-    backoff_delay_ = kMinimumDelayAfterFailure;
-    timer_->Stop();
-    return;
-  }
-
-  // Schedule immediate request when system geolocation is re-enabled.
-  if (using_geoposition_) {
-    ScheduleNextRequest(base::Seconds(0));
-  }
-}
-
-void NightLightClientImpl::OnScheduleTypeChanged(ScheduleType new_type) {
-  if (new_type == ScheduleType::kNone) {
-    using_geoposition_ = false;
-    timer_->Stop();
-    return;
-  }
-
-  using_geoposition_ = true;
-  // No need to request a new position if we already have a valid one from a
-  // request less than kNextRequestDelayAfterSuccess ago.
-  base::Time now = GetNow();
-  if ((now - last_successful_geo_request_time_) <
-      kNextRequestDelayAfterSuccess) {
-    VLOG(1) << "Already has a recent valid geoposition. Using it instead of "
-            << "requesting a new one.";
-    // Use the current valid position to update NightLightController.
-    SendCurrentGeoposition();
-  }
-
-  // Next request is either immediate or kNextRequestDelayAfterSuccess later
-  // than the last success time, whichever is greater.
-  if (system_geolocation_permission_enabled_) {
-    ScheduleNextRequest(
-        std::max(base::Seconds(0), last_successful_geo_request_time_ +
-                                       kNextRequestDelayAfterSuccess - now));
-  }
-}
-
-void NightLightClientImpl::TimezoneChanged(const icu::TimeZone& timezone) {
-  const std::u16string timezone_id =
-      ash::system::TimezoneSettings::GetTimezoneID(timezone);
-  if (current_timezone_id_ == timezone_id) {
-    return;
-  }
-
-  current_timezone_id_ = timezone_id;
-
-  // Don't schedule a new request if geolocation is not being used or the system
-  // geolocation permission is denied.
-  if (!using_geoposition_ || !system_geolocation_permission_enabled_) {
-    return;
-  }
-
-  // On timezone changes, request an immediate geoposition.
-  ScheduleNextRequest(base::Seconds(0));
-}
-
-// static
-base::TimeDelta
-NightLightClientImpl::GetNextRequestDelayAfterSuccessForTesting() {
-  return kNextRequestDelayAfterSuccess;
-}
-
-void NightLightClientImpl::SetTimerForTesting(
-    std::unique_ptr<base::OneShotTimer> timer) {
-  timer_ = std::move(timer);
-}
-
-void NightLightClientImpl::SetClockForTesting(const base::Clock* clock) {
-  clock_ = clock;
-}
-
-void NightLightClientImpl::SetCurrentTimezoneIdForTesting(
-    const std::u16string& timezone_id) {
-  current_timezone_id_ = timezone_id;
-}
-
-void NightLightClientImpl::OnGeoposition(const ash::Geoposition& position,
-                                         bool server_error,
-                                         const base::TimeDelta elapsed) {
-  if (!using_geoposition_ || !system_geolocation_permission_enabled_) {
-    // A response might arrive after:
-    //   * the schedule type is no longer "sunset to sunrise" or "custom"
-    //   * system geolocation permission is no longer enabled
-    // which means we should not push any positions to the NightLightController.
-    return;
-  }
-
-  if (server_error || !position.Valid() ||
-      elapsed > kGeolocationRequestTimeout) {
-    VLOG(1) << "Failed to get a valid geoposition. Trying again later.";
-    // Don't send invalid positions to ash.
-    // On failure, we schedule another request after the current backoff delay.
-    ScheduleNextRequest(backoff_delay_);
-
-    // If another failure occurs next, our backoff delay should double.
-    backoff_delay_ *= 2;
-    return;
-  }
-
-  last_successful_geo_request_time_ = GetNow();
-
-  latitude_ = position.latitude;
-  longitude_ = position.longitude;
-  SendCurrentGeoposition();
-
-  // On success, reset the backoff delay to its minimum value, and schedule
-  // another request.
-  backoff_delay_ = kMinimumDelayAfterFailure;
-  ScheduleNextRequest(kNextRequestDelayAfterSuccess);
-}
-
-base::Time NightLightClientImpl::GetNow() const {
-  return clock_ ? clock_->Now() : base::Time::Now();
-}
-
-void NightLightClientImpl::SendCurrentGeoposition() {
-  night_light_controller_->SetCurrentGeoposition(
-      SimpleGeoposition{latitude_, longitude_});
-}
-
-void NightLightClientImpl::ScheduleNextRequest(base::TimeDelta delay) {
-  timer_->Start(FROM_HERE, delay, this,
-                &NightLightClientImpl::RequestGeoposition);
-}
-
-void NightLightClientImpl::RequestGeoposition() {
-  VLOG(1) << "Requesting a new geoposition";
-  provider_.RequestGeolocation(
-      kGeolocationRequestTimeout, false /* send_wifi_access_points */,
-      false /* send_cell_towers */,
-      base::BindOnce(&NightLightClientImpl::OnGeoposition,
-                     base::Unretained(this)));
-}
-
-}  // namespace ash
diff --git a/chrome/browser/ash/night_light/night_light_client_impl.h b/chrome/browser/ash/night_light/night_light_client_impl.h
deleted file mode 100644
index 680e4959..0000000
--- a/chrome/browser/ash/night_light/night_light_client_impl.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ASH_NIGHT_LIGHT_NIGHT_LIGHT_CLIENT_IMPL_H_
-#define CHROME_BROWSER_ASH_NIGHT_LIGHT_NIGHT_LIGHT_CLIENT_IMPL_H_
-
-#include <memory>
-#include <string>
-
-#include "ash/public/cpp/night_light_controller.h"
-#include "base/memory/raw_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "chrome/browser/ash/night_light/night_light_client.h"
-#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
-#include "chromeos/ash/components/settings/timezone_settings.h"
-
-namespace base {
-class Clock;
-}  // namespace base
-
-namespace network {
-class SharedURLLoaderFactory;
-}
-
-namespace ash {
-
-// Periodically requests the IP-based geolocation and provides it to the
-// NightLightController running in ash.
-class NightLightClientImpl : public ash::NightLightClient,
-                             public ash::NightLightController::Observer,
-                             public ash::system::TimezoneSettings::Observer {
- public:
-  explicit NightLightClientImpl(
-      const SimpleGeolocationProvider::Delegate* delegate,
-      scoped_refptr<network::SharedURLLoaderFactory> factory);
-
-  NightLightClientImpl(const NightLightClientImpl&) = delete;
-  NightLightClientImpl& operator=(const NightLightClientImpl&) = delete;
-
-  ~NightLightClientImpl() override;
-
-  // ash::NightLightClient:
-  void Start() override;
-
-  // This class should respect the system geolocation permission. When the
-  // permission is disabled, no requests should be dispatched and no responses
-  // processed.
-  // Called from `ash::Preferences::ApplyPreferences()`.
-  void OnSystemGeolocationPermissionChanged(bool enabled) override;
-
-  // ash::NightLightController::Observer:
-  void OnScheduleTypeChanged(ScheduleType new_type) override;
-
-  // ash::system::TimezoneSettings::Observer:
-  void TimezoneChanged(const icu::TimeZone& timezone) override;
-
-  const base::OneShotTimer& timer() const { return *timer_; }
-
-  base::Time last_successful_geo_request_time() const {
-    return last_successful_geo_request_time_;
-  }
-
-  const std::u16string& current_timezone_id() const {
-    return current_timezone_id_;
-  }
-
-  bool using_geoposition() const { return using_geoposition_; }
-
-  static base::TimeDelta GetNextRequestDelayAfterSuccessForTesting();
-
-  void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer);
-
-  void SetClockForTesting(const base::Clock* clock);
-
-  void SetCurrentTimezoneIdForTesting(const std::u16string& timezone_id);
-
- protected:
-  void OnGeoposition(const ash::Geoposition& position,
-                     bool server_error,
-                     const base::TimeDelta elapsed);
-
- private:
-  base::Time GetNow() const;
-
-  // Sends the most recent valid geoposition to NightLightController in ash.
-  void SendCurrentGeoposition();
-
-  void ScheduleNextRequest(base::TimeDelta delay);
-
-  // ash::NightLightClient:
-  void RequestGeoposition() override;
-
-  // The IP-based geolocation provider.
-  ash::SimpleGeolocationProvider provider_;
-
-  raw_ptr<ash::NightLightController, ExperimentalAsh> night_light_controller_ =
-      nullptr;
-
-  // Delay after which a new request is retried after a failed one.
-  base::TimeDelta backoff_delay_;
-
-  std::unique_ptr<base::OneShotTimer> timer_;
-
-  // Optional Used in tests to override the time of "Now".
-  raw_ptr<const base::Clock, ExperimentalAsh> clock_ = nullptr;  // Not owned.
-
-  // Last successful geoposition coordinates and its timestamp.
-  base::Time last_successful_geo_request_time_;
-  double latitude_ = 0.0;
-  double longitude_ = 0.0;
-
-  // The ID of the current timezone in the format similar to "America/Chicago".
-  std::u16string current_timezone_id_;
-
-  // True as long as the schedule type is set to "sunset to sunrise" or
-  // "custom", which means this client will be retrieving the IP-based
-  // geoposition once per day.
-  bool using_geoposition_ = false;
-
-  // System geolocation permission.
-  bool system_geolocation_permission_enabled_ = false;
-};
-
-}  // namespace ash
-
-#endif  // CHROME_BROWSER_ASH_NIGHT_LIGHT_NIGHT_LIGHT_CLIENT_IMPL_H_
diff --git a/chrome/browser/ash/night_light/night_light_client_impl_unittest.cc b/chrome/browser/ash/night_light/night_light_client_impl_unittest.cc
deleted file mode 100644
index 5e9ecc4..0000000
--- a/chrome/browser/ash/night_light/night_light_client_impl_unittest.cc
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ash/night_light/night_light_client_impl.h"
-
-#include "ash/public/cpp/night_light_controller.h"
-#include "ash/public/cpp/schedule_enums.h"
-#include "ash/system/geolocation/geolocation_controller.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/task_environment.h"
-#include "base/time/clock.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-namespace ash {
-
-namespace {
-
-// Constructs a TimeZone object from the given |timezone_id|.
-std::unique_ptr<icu::TimeZone> CreateTimezone(const char* timezone_id) {
-  return base::WrapUnique(icu::TimeZone::createTimeZone(
-      icu::UnicodeString(timezone_id, -1, US_INV)));
-}
-
-std::u16string GetTimezoneId(const icu::TimeZone& timezone) {
-  return ash::system::TimezoneSettings::GetTimezoneID(timezone);
-}
-
-// A fake implementation of NightLightController for testing.
-class FakeNightLightController : public ash::NightLightController {
- public:
-  FakeNightLightController() = default;
-
-  FakeNightLightController(const FakeNightLightController&) = delete;
-  FakeNightLightController& operator=(const FakeNightLightController&) = delete;
-
-  ~FakeNightLightController() override = default;
-
-  const SimpleGeoposition& position() const { return position_; }
-
-  int position_pushes_num() const { return position_pushes_num_; }
-
-  // ash::NightLightController:
-  void SetCurrentGeoposition(const SimpleGeoposition& position) override {
-    position_ = position;
-    ++position_pushes_num_;
-  }
-
-  bool IsNightLightEnabled() const override { return false; }
-
-  void NotifyScheduleTypeChanged(ScheduleType type) {
-    for (auto& observer : observers_) {
-      observer.OnScheduleTypeChanged(type);
-    }
-  }
-
- private:
-  SimpleGeoposition position_;
-
-  // The number of times a new position is pushed to this controller.
-  int position_pushes_num_ = 0;
-};
-
-class FakeDelegate : public SimpleGeolocationProvider::Delegate {
- public:
-  bool IsSystemGeolocationAllowed() const override { return true; }
-};
-
-// A fake implementation of NightLightClient that doesn't perform any actual
-// geoposition requests.
-class FakeNightLightClient : public NightLightClientImpl {
- public:
-  explicit FakeNightLightClient(
-      const SimpleGeolocationProvider::Delegate* delegate)
-      : NightLightClientImpl(delegate, nullptr /* url_context_getter */) {}
-
-  FakeNightLightClient(const FakeNightLightClient&) = delete;
-  FakeNightLightClient& operator=(const FakeNightLightClient&) = delete;
-
-  ~FakeNightLightClient() override = default;
-
-  void set_position_to_send(const ash::Geoposition& position) {
-    position_to_send_ = position;
-  }
-
-  int geoposition_requests_num() const { return geoposition_requests_num_; }
-
- private:
-  // night_light::NightLightClient:
-  void RequestGeoposition() override {
-    OnGeoposition(position_to_send_, false, base::TimeDelta());
-    ++geoposition_requests_num_;
-  }
-
-  // The position to send to the controller the next time OnGeoposition is
-  // invoked.
-  ash::Geoposition position_to_send_;
-
-  // The number of new geoposition requests that have been triggered.
-  int geoposition_requests_num_ = 0;
-};
-
-// Base test fixture.
-class NightLightClientImplTest : public testing::TestWithParam<ScheduleType> {
- public:
-  NightLightClientImplTest() : client_(&delegate_) {}
-
-  NightLightClientImplTest(const NightLightClientImplTest&) = delete;
-  NightLightClientImplTest& operator=(const NightLightClientImplTest&) = delete;
-
-  ~NightLightClientImplTest() override = default;
-
-  void SetUp() override {
-    // Deterministic fake time that doesn't change for the sake of testing.
-    client_.SetTimerForTesting(std::make_unique<base::OneShotTimer>(
-        task_environment_.GetMockTickClock()));
-    client_.SetClockForTesting(task_environment_.GetMockClock());
-
-    // Notify system geolocation permission = Enabled.
-    client_.OnSystemGeolocationPermissionChanged(/*enabled=*/true);
-    client_.Start();
-  }
-
-  ash::Geoposition CreateValidGeoposition() {
-    ash::Geoposition position;
-    position.latitude = 32.0;
-    position.longitude = 31.0;
-    position.status = ash::Geoposition::STATUS_OK;
-    position.accuracy = 10;
-    position.timestamp = base::Time::Now();
-
-    return position;
-  }
-
-  base::test::TaskEnvironment task_environment_{
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
-
-  // NOTE: Don't reorder. Global controller instance has to be created first,
-  // client stores its reference on initialization.
-  FakeNightLightController controller_;
-  FakeNightLightClient client_;
-
- private:
-  FakeDelegate delegate_;
-};
-
-// Test that the client is retrieving geoposition periodically only when the
-// schedule type is "sunset to sunrise" or "custom".
-TEST_F(NightLightClientImplTest,
-       TestClientRunningWhenSunsetToSunriseOnCustomSchedule) {
-  EXPECT_FALSE(client_.using_geoposition());
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kNone);
-  EXPECT_FALSE(client_.using_geoposition());
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kCustom);
-  EXPECT_TRUE(client_.using_geoposition());
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise);
-  task_environment_.RunUntilIdle();
-  EXPECT_TRUE(client_.using_geoposition());
-
-  // Client should stop retrieving geopositions when schedule type changes to
-  // something else.
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kNone);
-  EXPECT_FALSE(client_.using_geoposition());
-}
-
-// Test that client only pushes valid positions.
-TEST_F(NightLightClientImplTest, TestInvalidPositions) {
-  EXPECT_EQ(0, controller_.position_pushes_num());
-  ash::Geoposition position;
-  position.latitude = 32.0;
-  position.longitude = 31.0;
-  position.status = ash::Geoposition::STATUS_TIMEOUT;
-  position.accuracy = 10;
-  position.timestamp = base::Time::Now();
-  client_.set_position_to_send(position);
-
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-  EXPECT_EQ(0, controller_.position_pushes_num());
-}
-
-// Test that successive changes of the schedule type to sunset to sunrise do not
-// trigger repeated geoposition requests.
-TEST_F(NightLightClientImplTest, TestRepeatedScheduleTypeChanges) {
-  // Start with a valid position, and expect it to be delivered to the
-  // controller.
-  EXPECT_EQ(0, controller_.position_pushes_num());
-  ash::Geoposition position1;
-  position1.latitude = 32.0;
-  position1.longitude = 31.0;
-  position1.status = ash::Geoposition::STATUS_OK;
-  position1.accuracy = 10;
-  position1.timestamp = base::Time::Now();
-  client_.set_position_to_send(position1);
-
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-  EXPECT_EQ(1, controller_.position_pushes_num());
-  EXPECT_EQ(task_environment_.GetMockClock()->Now(),
-            client_.last_successful_geo_request_time());
-
-  // A new different position just for the sake of comparison with position1 to
-  // make sure that no new requests are triggered and the same old position will
-  // be resent to the controller.
-  ash::Geoposition position2;
-  position2.latitude = 100.0;
-  position2.longitude = 200.0;
-  position2.status = ash::Geoposition::STATUS_OK;
-  position2.accuracy = 10;
-  position2.timestamp = base::Time::Now();
-  client_.set_position_to_send(position2);
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise);
-  task_environment_.RunUntilIdle();
-  // No new request has been triggered, however the same old valid position was
-  // pushed to the controller.
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-  EXPECT_EQ(2, controller_.position_pushes_num());
-  SimpleGeoposition simple_geoposition1{position1.latitude,
-                                        position1.longitude};
-  EXPECT_EQ(simple_geoposition1, controller_.position());
-
-  // The timer should be running scheduling a next request that is a
-  // kNextRequestDelayAfterSuccess from the last successful request time.
-  base::TimeDelta expected_delay =
-      client_.last_successful_geo_request_time() +
-      NightLightClientImpl::GetNextRequestDelayAfterSuccessForTesting() -
-      task_environment_.GetMockClock()->Now();
-  EXPECT_EQ(expected_delay, client_.timer().GetCurrentDelay());
-}
-
-// Tests that timezone changes result in new geoposition requests if the
-// schedule type is sunset to sunrise or custom.
-TEST_P(NightLightClientImplTest, TestTimezoneChanges) {
-  EXPECT_EQ(0, controller_.position_pushes_num());
-  client_.SetCurrentTimezoneIdForTesting(u"America/Los_Angeles");
-
-  // When schedule type is none, timezone changes do not result
-  // in geoposition requests.
-  controller_.NotifyScheduleTypeChanged(ScheduleType::kNone);
-  task_environment_.RunUntilIdle();
-  EXPECT_FALSE(client_.using_geoposition());
-  auto timezone = CreateTimezone("Africa/Cairo");
-  client_.TimezoneChanged(*timezone);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(0, controller_.position_pushes_num());
-  EXPECT_EQ(0, client_.geoposition_requests_num());
-  EXPECT_EQ(GetTimezoneId(*timezone), client_.current_timezone_id());
-
-  // Prepare a valid geoposition.
-  ash::Geoposition position;
-  position.latitude = 32.0;
-  position.longitude = 31.0;
-  position.status = ash::Geoposition::STATUS_OK;
-  position.accuracy = 10;
-  position.timestamp = base::Time::Now();
-  client_.set_position_to_send(position);
-
-  // Change the schedule type to sunset to sunrise or custom, and expect the
-  // geoposition will be pushed.
-  controller_.NotifyScheduleTypeChanged(GetParam());
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, controller_.position_pushes_num());
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-
-  // Updates with the same timezone does not result in new requests.
-  timezone = CreateTimezone("Africa/Cairo");
-  client_.TimezoneChanged(*timezone);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, controller_.position_pushes_num());
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-  EXPECT_EQ(GetTimezoneId(*timezone), client_.current_timezone_id());
-
-  // Only new timezones results in new geoposition requests.
-  timezone = CreateTimezone("Asia/Tokyo");
-  client_.TimezoneChanged(*timezone);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(2, controller_.position_pushes_num());
-  EXPECT_EQ(2, client_.geoposition_requests_num());
-  EXPECT_EQ(GetTimezoneId(*timezone), client_.current_timezone_id());
-}
-
-TEST_P(NightLightClientImplTest,
-       TestSystemGeolocationPermissionChangesForScheduleType) {
-  EXPECT_EQ(0, controller_.position_pushes_num());
-
-  // Prepare a valid geoposition.
-  ash::Geoposition position = CreateValidGeoposition();
-  client_.set_position_to_send(position);
-
-  // Disable system geolocation permission, expect that no requests will be
-  // sent, regardless of the controller setting.
-  EXPECT_FALSE(client_.timer().IsRunning());
-  client_.OnSystemGeolocationPermissionChanged(/*enabled=*/false);
-  EXPECT_FALSE(client_.timer().IsRunning());
-
-  // Set nightlightclient type to either SunsetToSunrise or Custom.
-  controller_.NotifyScheduleTypeChanged(GetParam());
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(0, controller_.position_pushes_num());
-  EXPECT_EQ(0, client_.geoposition_requests_num());
-
-  // Re-enable system geolocation permission and expect a new geolocation
-  // request.
-  client_.OnSystemGeolocationPermissionChanged(/*enabled=*/true);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, controller_.position_pushes_num());
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-
-  // Fast forward to the next request.
-  task_environment_.FastForwardBy(
-      client_.GetNextRequestDelayAfterSuccessForTesting());
-  EXPECT_EQ(2, controller_.position_pushes_num());
-  EXPECT_EQ(2, client_.geoposition_requests_num());
-
-  // Revoking the geolocation permission should stop the scheduler.
-  client_.OnSystemGeolocationPermissionChanged(/*enabled=*/false);
-  EXPECT_EQ(2, controller_.position_pushes_num());
-  EXPECT_EQ(2, client_.geoposition_requests_num());
-  EXPECT_FALSE(client_.timer().IsRunning());
-}
-
-TEST_P(NightLightClientImplTest,
-       TestSystemGeolocationPermissionChangesForTimezone) {
-  EXPECT_EQ(0, controller_.position_pushes_num());
-  client_.SetCurrentTimezoneIdForTesting(u"America/Los_Angeles");
-
-  // Prepare a valid geoposition.
-  ash::Geoposition position = CreateValidGeoposition();
-  client_.set_position_to_send(position);
-
-  // Change the schedule type to sunset to sunrise or custom, and expect the
-  // geoposition will be pushed.
-  controller_.NotifyScheduleTypeChanged(GetParam());
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, controller_.position_pushes_num());
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-
-  // Disable geolocation permission and expect scheduler to stop.
-  client_.OnSystemGeolocationPermissionChanged(/*enabled=*/false);
-  EXPECT_FALSE(client_.timer().IsRunning());
-
-  // new timezone shouldn't resume scheduling, while the geo permission is off.
-  // Current timezone should update successfully.
-  auto timezone = CreateTimezone("Asia/Tokyo");
-  client_.TimezoneChanged(*timezone);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, controller_.position_pushes_num());
-  EXPECT_EQ(1, client_.geoposition_requests_num());
-  EXPECT_EQ(GetTimezoneId(*timezone), client_.current_timezone_id());
-  EXPECT_FALSE(client_.timer().IsRunning());
-
-  // Re-enable the system geolocation permission. Should result in a new
-  // immediate request.
-  client_.OnSystemGeolocationPermissionChanged(/*enabled=*/true);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(2, controller_.position_pushes_num());
-  EXPECT_EQ(2, client_.geoposition_requests_num());
-
-  // Update the timezone again, see that the geolocation request is dispatched
-  // immediately.
-  timezone = CreateTimezone("Africa/Cairo");
-  client_.TimezoneChanged(*timezone);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(3, controller_.position_pushes_num());
-  EXPECT_EQ(3, client_.geoposition_requests_num());
-  EXPECT_EQ(GetTimezoneId(*timezone), client_.current_timezone_id());
-}
-
-INSTANTIATE_TEST_SUITE_P(All,
-                         NightLightClientImplTest,
-                         ::testing::Values(ScheduleType::kSunsetToSunrise,
-                                           ScheduleType::kCustom));
-}  // namespace
-
-}  // namespace ash
diff --git a/chrome/browser/ash/preferences.cc b/chrome/browser/ash/preferences.cc
index 90c014f2..9dd1c6a0a2 100644
--- a/chrome/browser/ash/preferences.cc
+++ b/chrome/browser/ash/preferences.cc
@@ -39,7 +39,6 @@
 #include "chrome/browser/ash/login/hid_detection_revamp_field_trial.h"
 #include "chrome/browser/ash/login/login_pref_names.h"
 #include "chrome/browser/ash/login/session/user_session_manager.h"
-#include "chrome/browser/ash/night_light/night_light_client.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/ash/system/input_device_settings.h"
@@ -1163,14 +1162,11 @@
         g_browser_process->platform_part()->GetTimezoneResolverManager();
     GeolocationController* geolocation_controller =
         ash::Shell::Get()->geolocation_controller();
-    NightLightClient* night_light_client = ash::NightLightClient::Get();
 
     timezone_resolver_manager->OnSystemGeolocationPermissionChanged(
         system_geolocation_permission_enabled);
     geolocation_controller->OnSystemGeolocationPermissionChanged(
         system_geolocation_permission_enabled);
-    night_light_client->OnSystemGeolocationPermissionChanged(
-        system_geolocation_permission_enabled);
   }
 
   if (pref_name == ::prefs::kUserTimezone &&
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index cd1f67f..fc9188e 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -943,6 +943,13 @@
 const char kSupportedLinksAppPrefsKey[] = "supported_links_infobar.apps";
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
+// Deprecated 10/2023.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+constexpr char kNightLightCachedLatitude[] = "ash.night_light.cached_latitude";
+constexpr char kNightLightCachedLongitude[] =
+    "ash.night_light.cached_longitude";
+#endif
+
 // Register local state used only for migration (clearing or moving to a new
 // key).
 void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
@@ -1327,6 +1334,12 @@
 #if BUILDFLAG(IS_CHROMEOS)
   registry->RegisterDictionaryPref(kSupportedLinksAppPrefsKey);
 #endif  // BUILDFLAG(IS_CHROMEOS)
+
+// Deprecated 10/2023.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  registry->RegisterDoublePref(kNightLightCachedLatitude, 0.0);
+  registry->RegisterDoublePref(kNightLightCachedLongitude, 0.0);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void ClearSyncRequestedPrefAndMaybeMigrate(PrefService* profile_prefs) {
@@ -2494,6 +2507,12 @@
   profile_prefs->ClearPref(kSupportedLinksAppPrefsKey);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // Added 10/2023.
+  profile_prefs->ClearPref(kNightLightCachedLatitude);
+  profile_prefs->ClearPref(kNightLightCachedLongitude);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_PROFILE_PREFS
 
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
index ff4161a..941e58a0 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/ash/game_mode/game_mode_controller.h"
 #include "chrome/browser/ash/geolocation/system_geolocation_source.h"
 #include "chrome/browser/ash/login/signin/signin_error_notifier_factory.h"
-#include "chrome/browser/ash/night_light/night_light_client_impl.h"
 #include "chrome/browser/ash/policy/display/display_resolution_handler.h"
 #include "chrome/browser/ash/policy/display/display_rotation_default_handler.h"
 #include "chrome/browser/ash/policy/display/display_settings_handler.h"
@@ -275,10 +274,9 @@
   }
 #endif
 
-  night_light_client_ = std::make_unique<ash::NightLightClientImpl>(
-      g_browser_process->platform_part()->GetTimezoneResolverManager(),
-      g_browser_process->shared_url_loader_factory());
-  night_light_client_->Start();
+  // Result is unused, but `TimezoneResolverManager` must be created here for
+  // its internal initialization to succeed.
+  g_browser_process->platform_part()->GetTimezoneResolverManager();
 
   projector_app_client_ = std::make_unique<ProjectorAppClientImpl>();
   projector_client_ = std::make_unique<ProjectorClientImpl>();
@@ -380,7 +378,6 @@
   exo_parts_.reset();
 #endif
 
-  night_light_client_.reset();
   mobile_data_notifications_.reset();
   chrome_shelf_controller_initializer_.reset();
   attestation_cleanup_manager_.reset();
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
index b41fd8fa..c6b4e8e6 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
@@ -17,7 +17,6 @@
 class ArcWindowWatcher;
 class NetworkPortalNotificationController;
 class NewWindowDelegateProvider;
-class NightLightClient;
 class RefreshRateController;
 class VideoConferenceTrayController;
 }  // namespace ash
@@ -53,7 +52,6 @@
 class MediaClientImpl;
 class MobileDataNotifications;
 class NetworkConnectDelegate;
-class NightLightClient;
 class ProjectorAppClientImpl;
 class ProjectorClientImpl;
 class ScreenOrientationDelegateChromeos;
@@ -163,7 +161,6 @@
 
   // Initialized in PostBrowserStart in all configs:
   std::unique_ptr<MobileDataNotifications> mobile_data_notifications_;
-  std::unique_ptr<ash::NightLightClient> night_light_client_;
   std::unique_ptr<AmbientClientImpl> ambient_client_;
 
   // Boolean that is set to true after PostBrowserStart() executes.