ambient_weather_controller.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright 2022 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. #include "ash/ambient/ambient_weather_controller.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/ambient/ambient_controller.h"
  8. #include "ash/ambient/model/ambient_weather_model.h"
  9. #include "ash/public/cpp/ambient/ambient_backend_controller.h"
  10. #include "ash/public/cpp/image_downloader.h"
  11. #include "ash/shell.h"
  12. #include "base/bind.h"
  13. #include "base/callback.h"
  14. #include "base/check.h"
  15. #include "net/traffic_annotation/network_traffic_annotation.h"
  16. #include "third_party/abseil-cpp/absl/types/optional.h"
  17. namespace ash {
  18. namespace {
  19. // TODO(jamescook): Rename to "ambient weather".
  20. constexpr net::NetworkTrafficAnnotationTag kAmbientPhotoControllerTag =
  21. net::DefineNetworkTrafficAnnotation("ambient_photo_controller", R"(
  22. semantics {
  23. sender: "Ambient photo"
  24. description:
  25. "Download ambient image weather icon from Google."
  26. trigger:
  27. "Triggered periodically when the battery is charged and the user "
  28. "is idle."
  29. data: "None."
  30. destination: GOOGLE_OWNED_SERVICE
  31. }
  32. policy {
  33. cookies_allowed: NO
  34. setting:
  35. "This feature is off by default and can be overridden by user."
  36. policy_exception_justification:
  37. "This feature is set by user settings.ambient_mode.enabled pref. "
  38. "The user setting is per device and cannot be overriden by admin."
  39. })");
  40. void DownloadImageFromUrl(
  41. const std::string& url,
  42. base::OnceCallback<void(const gfx::ImageSkia&)> callback) {
  43. DCHECK(!url.empty());
  44. // During shutdown, we may not have `ImageDownloader` when reach here.
  45. if (!ImageDownloader::Get())
  46. return;
  47. ImageDownloader::Get()->Download(GURL(url), kAmbientPhotoControllerTag,
  48. std::move(callback));
  49. }
  50. } // namespace
  51. AmbientWeatherController::AmbientWeatherController()
  52. : weather_model_(std::make_unique<AmbientWeatherModel>()) {}
  53. AmbientWeatherController::~AmbientWeatherController() = default;
  54. void AmbientWeatherController::FetchWeather() {
  55. Shell::Get()
  56. ->ambient_controller()
  57. ->ambient_backend_controller()
  58. ->FetchWeather(base::BindOnce(
  59. &AmbientWeatherController::StartDownloadingWeatherConditionIcon,
  60. weak_factory_.GetWeakPtr()));
  61. }
  62. void AmbientWeatherController::StartDownloadingWeatherConditionIcon(
  63. const absl::optional<WeatherInfo>& weather_info) {
  64. if (!weather_info) {
  65. LOG(WARNING) << "No weather info included in the response.";
  66. return;
  67. }
  68. if (!weather_info->temp_f.has_value()) {
  69. LOG(WARNING) << "No temperature included in weather info.";
  70. return;
  71. }
  72. if (weather_info->condition_icon_url.value_or(std::string()).empty()) {
  73. LOG(WARNING) << "No value found for condition icon url in the weather info "
  74. "response.";
  75. return;
  76. }
  77. // Ideally we should avoid downloading from the same url again to reduce the
  78. // overhead, as it's unlikely that the weather condition is changing
  79. // frequently during the day.
  80. // TODO(meilinw): avoid repeated downloading by caching the last N url hashes,
  81. // where N should depend on the icon image size.
  82. DownloadImageFromUrl(
  83. weather_info->condition_icon_url.value(),
  84. base::BindOnce(
  85. &AmbientWeatherController::OnWeatherConditionIconDownloaded,
  86. weak_factory_.GetWeakPtr(), weather_info->temp_f.value(),
  87. weather_info->show_celsius));
  88. }
  89. void AmbientWeatherController::OnWeatherConditionIconDownloaded(
  90. float temp_f,
  91. bool show_celsius,
  92. const gfx::ImageSkia& icon) {
  93. // For now we only show the weather card when both fields have values.
  94. // TODO(meilinw): optimize the behavior with more specific error handling.
  95. if (icon.isNull())
  96. return;
  97. weather_model_->UpdateWeatherInfo(icon, temp_f, show_celsius);
  98. }
  99. } // namespace ash