Commit 3a150d71 authored by wutao's avatar wutao Committed by Commit Bot

Reland "ambient: Use backdrop APIs"

This is a reland of 84408458

Original change's description:
> ambient: Use backdrop APIs
> 
> This cl adds a framework to use backdrop APIs to fetch photos etc for
> Ambient mode.
> 
> Bug: b/148483925
> Test: manual
> Change-Id: I777b9269148c5317a18e763e911e4893e7ecbe2b
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2026258
> Commit-Queue: Tao Wu <wutao@chromium.org>
> Reviewed-by: Xiaohui Chen <xiaohuic@chromium.org>
> Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#740069}

Bug: b/148483925
Change-Id: I6a6b6d25feeb181e00a207d5e58518533a8e263c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2053038
Commit-Queue: Tao Wu <wutao@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742823}
parent dd424d1a
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
#include "ash/assistant/assistant_controller.h" #include "ash/assistant/assistant_controller.h"
#include "ash/login/ui/lock_screen.h" #include "ash/login/ui/lock_screen.h"
#include "ash/public/cpp/ambient/ambient_mode_state.h" #include "ash/public/cpp/ambient/ambient_mode_state.h"
#include "ash/public/cpp/ambient/ambient_prefs.h"
#include "ash/public/cpp/ambient/photo_controller.h" #include "ash/public/cpp/ambient/photo_controller.h"
#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_features.h"
#include "components/prefs/pref_registry_simple.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
namespace ash { namespace ash {
...@@ -26,6 +28,14 @@ bool CanStartAmbientMode() { ...@@ -26,6 +28,14 @@ bool CanStartAmbientMode() {
} // namespace } // namespace
// static
void AmbientController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
if (chromeos::features::IsAmbientModeEnabled()) {
registry->RegisterStringPref(ash::ambient::prefs::kAmbientBackdropClientId,
std::string());
}
}
AmbientController::AmbientController(AssistantController* assistant_controller) AmbientController::AmbientController(AssistantController* assistant_controller)
: assistant_controller_(assistant_controller) { : assistant_controller_(assistant_controller) {
ambient_state_.AddObserver(this); ambient_state_.AddObserver(this);
...@@ -146,10 +156,14 @@ void AmbientController::GetNextImage() { ...@@ -146,10 +156,14 @@ void AmbientController::GetNextImage() {
&AmbientController::OnPhotoDownloaded, weak_factory_.GetWeakPtr())); &AmbientController::OnPhotoDownloaded, weak_factory_.GetWeakPtr()));
} }
void AmbientController::OnPhotoDownloaded(const gfx::ImageSkia& image) { void AmbientController::OnPhotoDownloaded(bool success,
if (!image.isNull()) const gfx::ImageSkia& image) {
model_.AddNextImage(image); // TODO(b/148485116): Implement retry logic.
if (!success)
return;
DCHECK(!image.isNull());
model_.AddNextImage(image);
ScheduleRefreshImage(); ScheduleRefreshImage();
} }
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "ui/views/widget/widget_observer.h" #include "ui/views/widget/widget_observer.h"
class PrefRegistrySimple;
namespace gfx { namespace gfx {
class ImageSkia; class ImageSkia;
} // namespace gfx } // namespace gfx
...@@ -27,6 +29,8 @@ class PhotoModelObserver; ...@@ -27,6 +29,8 @@ class PhotoModelObserver;
class ASH_EXPORT AmbientController : public views::WidgetObserver, class ASH_EXPORT AmbientController : public views::WidgetObserver,
public AmbientModeStateObserver { public AmbientModeStateObserver {
public: public:
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
explicit AmbientController(AssistantController* assistant_controller); explicit AmbientController(AssistantController* assistant_controller);
~AmbientController() override; ~AmbientController() override;
...@@ -63,7 +67,7 @@ class ASH_EXPORT AmbientController : public views::WidgetObserver, ...@@ -63,7 +67,7 @@ class ASH_EXPORT AmbientController : public views::WidgetObserver,
void RefreshImage(); void RefreshImage();
void ScheduleRefreshImage(); void ScheduleRefreshImage();
void GetNextImage(); void GetNextImage();
void OnPhotoDownloaded(const gfx::ImageSkia& image); void OnPhotoDownloaded(bool success, const gfx::ImageSkia& image);
AssistantController* const assistant_controller_; // Owned by Shell. AssistantController* const assistant_controller_; // Owned by Shell.
AmbientContainerView* container_view_ = nullptr; // Owned by view hierarchy. AmbientContainerView* container_view_ = nullptr; // Owned by view hierarchy.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/public/cpp/ash_prefs.h" #include "ash/public/cpp/ash_prefs.h"
#include "ash/accessibility/accessibility_controller_impl.h" #include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/ambient/ambient_controller.h"
#include "ash/app_list/app_list_controller_impl.h" #include "ash/app_list/app_list_controller_impl.h"
#include "ash/assistant/assistant_controller.h" #include "ash/assistant/assistant_controller.h"
#include "ash/detachable_base/detachable_base_handler.h" #include "ash/detachable_base/detachable_base_handler.h"
...@@ -39,6 +40,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test) { ...@@ -39,6 +40,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test) {
AccessibilityControllerImpl::RegisterProfilePrefs(registry); AccessibilityControllerImpl::RegisterProfilePrefs(registry);
AppListControllerImpl::RegisterProfilePrefs(registry); AppListControllerImpl::RegisterProfilePrefs(registry);
AssistantController::RegisterProfilePrefs(registry); AssistantController::RegisterProfilePrefs(registry);
AmbientController::RegisterProfilePrefs(registry);
BluetoothPowerController::RegisterProfilePrefs(registry); BluetoothPowerController::RegisterProfilePrefs(registry);
CapsLockNotificationController::RegisterProfilePrefs(registry, for_test); CapsLockNotificationController::RegisterProfilePrefs(registry, for_test);
contextual_tooltip::RegisterProfilePrefs(registry); contextual_tooltip::RegisterProfilePrefs(registry);
......
...@@ -19,6 +19,8 @@ component("cpp") { ...@@ -19,6 +19,8 @@ component("cpp") {
"accessibility_focus_ring_info.h", "accessibility_focus_ring_info.h",
"ambient/ambient_mode_state.cc", "ambient/ambient_mode_state.cc",
"ambient/ambient_mode_state.h", "ambient/ambient_mode_state.h",
"ambient/ambient_prefs.cc",
"ambient/ambient_prefs.h",
"ambient/photo_controller.cc", "ambient/photo_controller.cc",
"ambient/photo_controller.h", "ambient/photo_controller.h",
"android_intent_helper.cc", "android_intent_helper.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include "ash/public/cpp/ambient/ambient_prefs.h"
namespace ash {
namespace ambient {
namespace prefs {
constexpr char kAmbientBackdropClientId[] = "ash.ambient.backdrop.client.id";
} // namespace prefs
} // namespace ambient
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_PUBLIC_CPP_AMBIENT_AMBIENT_PREFS_H_
#define ASH_PUBLIC_CPP_AMBIENT_AMBIENT_PREFS_H_
#include "ash/public/cpp/ash_public_export.h"
namespace ash {
namespace ambient {
namespace prefs {
// A GUID for backdrop client.
ASH_PUBLIC_EXPORT extern const char kAmbientBackdropClientId[];
} // namespace prefs
} // namespace ambient
} // namespace ash
#endif // ASH_PUBLIC_CPP_AMBIENT_AMBIENT_PREFS_H_
...@@ -14,6 +14,15 @@ PhotoController* g_photo_controller = nullptr; ...@@ -14,6 +14,15 @@ PhotoController* g_photo_controller = nullptr;
} // namespace } // namespace
PhotoController::Topic::Topic() = default;
PhotoController::Topic::~Topic() = default;
PhotoController::Topic::Topic(const Topic&) = default;
PhotoController::Topic& PhotoController::Topic::operator=(const Topic&) =
default;
// static // static
PhotoController* PhotoController::Get() { PhotoController* PhotoController::Get() {
return g_photo_controller; return g_photo_controller;
......
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
#ifndef ASH_PUBLIC_CPP_AMBIENT_PHOTO_CONTROLLER_H_ #ifndef ASH_PUBLIC_CPP_AMBIENT_PHOTO_CONTROLLER_H_
#define ASH_PUBLIC_CPP_AMBIENT_PHOTO_CONTROLLER_H_ #define ASH_PUBLIC_CPP_AMBIENT_PHOTO_CONTROLLER_H_
#include <string>
#include "ash/public/cpp/ash_public_export.h" #include "ash/public/cpp/ash_public_export.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
namespace gfx { namespace gfx {
class ImageSkia; class ImageSkia;
...@@ -19,9 +22,27 @@ namespace ash { ...@@ -19,9 +22,27 @@ namespace ash {
// mode in ash. // mode in ash.
class ASH_PUBLIC_EXPORT PhotoController { class ASH_PUBLIC_EXPORT PhotoController {
public: public:
// TODO(b/148462355): Add fields of weather and time info.
// The contents shown in the Ambient mode.
// Corresponding to backdrop::ScreenUpdate::Topic.
struct Topic {
Topic();
~Topic();
Topic(const Topic&);
Topic& operator=(const Topic&);
// Image url.
std::string url;
// Optional for non-cropped portrait style images. The same image as in
// |url| but it is not cropped, which is better for portrait displaying.
base::Optional<std::string> portrait_image_url;
};
static PhotoController* Get(); static PhotoController* Get();
using PhotoDownloadCallback = base::OnceCallback<void(const gfx::ImageSkia&)>; using PhotoDownloadCallback =
base::OnceCallback<void(bool success, const gfx::ImageSkia&)>;
// Get next image. // Get next image.
virtual void GetNextImage(PhotoDownloadCallback callback) = 0; virtual void GetNextImage(PhotoDownloadCallback callback) = 0;
......
...@@ -19,7 +19,7 @@ void TestPhotoController::GetNextImage( ...@@ -19,7 +19,7 @@ void TestPhotoController::GetNextImage(
PhotoController::PhotoDownloadCallback callback) { PhotoController::PhotoDownloadCallback callback) {
gfx::ImageSkia image = gfx::ImageSkia image =
gfx::test::CreateImageSkia(/*width=*/10, /*height=*/10); gfx::test::CreateImageSkia(/*width=*/10, /*height=*/10);
std::move(callback).Run(image); std::move(callback).Run(/*success=*/true, image);
} }
} // namespace ash } // namespace ash
...@@ -1532,6 +1532,8 @@ jumbo_static_library("ui") { ...@@ -1532,6 +1532,8 @@ jumbo_static_library("ui") {
"app_list/search/launcher_search/launcher_search_result.h", "app_list/search/launcher_search/launcher_search_result.h",
"ash/accessibility/accessibility_controller_client.cc", "ash/accessibility/accessibility_controller_client.cc",
"ash/accessibility/accessibility_controller_client.h", "ash/accessibility/accessibility_controller_client.h",
"ash/ambient/photo_client.cc",
"ash/ambient/photo_client.h",
"ash/ambient/photo_controller_impl.cc", "ash/ambient/photo_controller_impl.cc",
"ash/ambient/photo_controller_impl.h", "ash/ambient/photo_controller_impl.h",
"ash/arc_chrome_actions_client.cc", "ash/arc_chrome_actions_client.cc",
...@@ -2111,6 +2113,18 @@ jumbo_static_library("ui") { ...@@ -2111,6 +2113,18 @@ jumbo_static_library("ui") {
if (use_cras) { if (use_cras) {
defines += [ "USE_CRAS" ] defines += [ "USE_CRAS" ]
} }
if (enable_cros_libassistant) {
sources += [
"ash/ambient/backdrop/photo_client_impl.cc",
"ash/ambient/backdrop/photo_client_impl.h",
]
deps += [
"//chromeos/assistant/internal/ambient",
"//chromeos/assistant/internal/proto/google3",
]
}
} }
if (is_win || is_mac || is_desktop_linux || is_chromeos) { if (is_win || is_mac || is_desktop_linux || is_chromeos) {
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h"
#include <utility>
#include "ash/public/cpp/ambient/ambient_prefs.h"
#include "base/base64.h"
#include "base/guid.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chromeos/assistant/internal/proto/google3/backdrop/backdrop.pb.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"
namespace {
constexpr char kPhotosOAuthScope[] = "https://www.googleapis.com/auth/photos";
constexpr char kProtoMimeType[] = "application/protobuf";
// Max body size in bytes to download.
constexpr int kMaxBodySizeBytes = 1 * 1024 * 1024; // 1 MiB
std::string GetClientId() {
PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
DCHECK(prefs);
std::string client_id =
prefs->GetString(ash::ambient::prefs::kAmbientBackdropClientId);
if (client_id.empty()) {
client_id = base::GenerateGUID();
prefs->SetString(ash::ambient::prefs::kAmbientBackdropClientId, client_id);
}
return client_id;
}
std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
const chromeos::ambient::BackdropClientConfig::Request& request) {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = GURL(request.url);
resource_request->method = request.method;
resource_request->load_flags =
net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
for (const auto& header : request.headers) {
std::string encoded_value;
if (header.needs_base_64_encoded)
base::Base64Encode(header.value, &encoded_value);
else
encoded_value = header.value;
resource_request->headers.SetHeader(header.name, encoded_value);
}
return resource_request;
}
ash::PhotoController::Topic CreateTopicFrom(
const backdrop::ScreenUpdate::Topic& backdrop_topic) {
ash::PhotoController::Topic topic;
topic.url = backdrop_topic.url();
if (!backdrop_topic.portrait_image_url().empty())
topic.portrait_image_url = backdrop_topic.portrait_image_url();
return topic;
}
} // namespace
// Helper class for handling Backdrop service requests.
class BackdropURLLoader {
public:
BackdropURLLoader() = default;
BackdropURLLoader(const BackdropURLLoader&) = delete;
BackdropURLLoader& operator=(const BackdropURLLoader&) = delete;
~BackdropURLLoader() = default;
// Starts downloading the proto. |request_body| is a serialized proto and
// will be used as the upload body.
void Start(std::unique_ptr<network::ResourceRequest> resource_request,
const std::string& request_body,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
network::SimpleURLLoader::BodyAsStringCallback callback) {
// No ongoing downloading task.
DCHECK(!simple_loader_);
loader_factory_ =
ProfileManager::GetActiveUserProfile()->GetURLLoaderFactory();
// TODO(b/148818448): This will reset previous request without callback
// called. Handle parallel/sequential requests to server.
simple_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
simple_loader_->AttachStringForUpload(request_body, kProtoMimeType);
// |base::Unretained| is safe because this instance outlives
// |simple_loader_|.
simple_loader_->DownloadToString(
loader_factory_.get(),
base::BindOnce(&BackdropURLLoader::OnUrlDownloaded,
base::Unretained(this), std::move(callback)),
kMaxBodySizeBytes);
}
private:
// Called when the download completes.
void OnUrlDownloaded(network::SimpleURLLoader::BodyAsStringCallback callback,
std::unique_ptr<std::string> response_body) {
loader_factory_.reset();
if (simple_loader_->NetError() == net::OK && response_body) {
simple_loader_.reset();
std::move(callback).Run(std::move(response_body));
return;
}
int response_code = -1;
if (simple_loader_->ResponseInfo() &&
simple_loader_->ResponseInfo()->headers) {
response_code = simple_loader_->ResponseInfo()->headers->response_code();
}
LOG(ERROR) << "Downloading Backdrop proto failed with error code: "
<< response_code << " with network error"
<< simple_loader_->NetError();
simple_loader_.reset();
std::move(callback).Run(std::make_unique<std::string>());
return;
}
std::unique_ptr<network::SimpleURLLoader> simple_loader_;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
};
PhotoClientImpl::PhotoClientImpl() = default;
PhotoClientImpl::~PhotoClientImpl() = default;
void PhotoClientImpl::FetchTopicInfo(OnTopicInfoFetchedCallback callback) {
// TODO(b/148463064): Access token will be requested and cached before
// entering lock screen.
RequestAccessToken(base::BindOnce(&PhotoClientImpl::StartToFetchTopicInfo,
base::Unretained(this),
std::move(callback)));
}
void PhotoClientImpl::RequestAccessToken(GetAccessTokenCallback callback) {
auto* profile = ProfileManager::GetActiveUserProfile();
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
CoreAccountInfo account_info = identity_manager->GetPrimaryAccountInfo(
signin::ConsentLevel::kNotRequired);
identity::ScopeSet scopes;
scopes.insert(kPhotosOAuthScope);
// TODO(b/148463064): Handle retry refresh token and multiple requests.
access_token_fetcher_ = identity_manager->CreateAccessTokenFetcherForAccount(
account_info.account_id, /*oauth_consumer_name=*/"ChromeOS_AmbientMode",
scopes, base::BindOnce(std::move(callback), account_info.gaia),
signin::AccessTokenFetcher::Mode::kImmediate);
}
void PhotoClientImpl::StartToFetchTopicInfo(
OnTopicInfoFetchedCallback callback,
const std::string& gaia_id,
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info) {
access_token_fetcher_.reset();
if (gaia_id.empty() || access_token_info.token.empty()) {
std::move(callback).Run(/*success=*/false, base::nullopt);
return;
}
std::string client_id = GetClientId();
chromeos::ambient::BackdropClientConfig::Request request =
backdrop_client_config_.GetFetchTopicInfoRequest(
gaia_id, access_token_info.token, client_id);
auto resource_request = CreateResourceRequest(request);
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("backdrop_fetch_topics",
R"(
semantics {
sender: "ChromeOS Ambient Mode"
description:
"The ChromeOS Ambient Mode displays a rich set of photos for "
"users to choose from."
trigger:
"When ChromeOS Ambient Mode starts"
data:
"The Backdrop protocol buffer messages. Containing user auth"
"token and a unique random client id."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: NO
setting:
"NA"
policy_exception_justification:
"Not implemented, considered not necessary."
})");
// |base::Unretained| is safe because this instance outlives
// |backdrop_url_loader_|.
DCHECK(!backdrop_url_loader_);
backdrop_url_loader_ = std::make_unique<BackdropURLLoader>();
backdrop_url_loader_->Start(
std::move(resource_request), request.body, traffic_annotation,
base::BindOnce(&PhotoClientImpl::OnTopicInfoFetched,
base::Unretained(this), std::move(callback)));
}
void PhotoClientImpl::OnTopicInfoFetched(
OnTopicInfoFetchedCallback callback,
std::unique_ptr<std::string> response) {
DCHECK(backdrop_url_loader_);
backdrop_url_loader_.reset();
using BackdropClientConfig = chromeos::ambient::BackdropClientConfig;
backdrop::ScreenUpdate::Topic backdrop_topic =
BackdropClientConfig::ParseFetchTopicInfoResponse(*response);
ash::PhotoController::Topic topic = CreateTopicFrom(backdrop_topic);
std::move(callback).Run(/*success=*/true, topic);
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_ASH_AMBIENT_BACKDROP_PHOTO_CLIENT_IMPL_H_
#define CHROME_BROWSER_UI_ASH_AMBIENT_BACKDROP_PHOTO_CLIENT_IMPL_H_
#include <memory>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/ash/ambient/photo_client.h"
#include "chromeos/assistant/internal/ambient/backdrop_client_config.h"
class BackdropURLLoader;
class GoogleServiceAuthError;
namespace signin {
class AccessTokenFetcher;
struct AccessTokenInfo;
} // namespace signin
// The photo client impl talks to Backdrop service.
class PhotoClientImpl : public PhotoClient {
public:
PhotoClientImpl();
~PhotoClientImpl() override;
PhotoClientImpl(const PhotoClientImpl&) = delete;
PhotoClientImpl& operator=(const PhotoClientImpl&) = delete;
// PhotoClient:
void FetchTopicInfo(OnTopicInfoFetchedCallback callback) override;
private:
using GetAccessTokenCallback =
base::OnceCallback<void(const std::string& gaia_id,
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info)>;
void RequestAccessToken(GetAccessTokenCallback callback);
void StartToFetchTopicInfo(OnTopicInfoFetchedCallback callback,
const std::string& gaia_id,
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info);
void OnTopicInfoFetched(OnTopicInfoFetchedCallback callback,
std::unique_ptr<std::string> response);
// The url loader for the Backdrop service request.
std::unique_ptr<BackdropURLLoader> backdrop_url_loader_;
std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_;
chromeos::ambient::BackdropClientConfig backdrop_client_config_;
base::WeakPtrFactory<PhotoClientImpl> weak_factory_{this};
};
#endif // CHROME_BROWSER_UI_ASH_AMBIENT_BACKDROP_PHOTO_CLIENT_IMPL_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/ambient/photo_client.h"
#include "build/buildflag.h"
#include "chromeos/assistant/buildflags.h"
#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#include "chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h"
#endif
// static
std::unique_ptr<PhotoClient> PhotoClient::Create() {
#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
return std::make_unique<PhotoClientImpl>();
#else
return std::make_unique<PhotoClient>();
#endif
}
void PhotoClient::FetchTopicInfo(OnTopicInfoFetchedCallback callback) {
std::move(callback).Run(/*success=*/false, base::nullopt);
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_ASH_AMBIENT_PHOTO_CLIENT_H_
#define CHROME_BROWSER_UI_ASH_AMBIENT_PHOTO_CLIENT_H_
#include <memory>
#include "ash/public/cpp/ambient/photo_controller.h"
#include "base/callback.h"
#include "base/optional.h"
// The interface of a client to retrieve photos.
class PhotoClient {
public:
using OnTopicInfoFetchedCallback = base::OnceCallback<void(
bool success,
const base::Optional<ash::PhotoController::Topic>& topic)>;
// Creates PhotoClient based on the build flag ENABLE_CROS_LIBASSISTANT.
static std::unique_ptr<PhotoClient> Create();
PhotoClient() = default;
PhotoClient(const PhotoClient&) = delete;
PhotoClient& operator=(const PhotoClient&) = delete;
virtual ~PhotoClient() = default;
virtual void FetchTopicInfo(OnTopicInfoFetchedCallback callback);
};
#endif // CHROME_BROWSER_UI_ASH_AMBIENT_PHOTO_CLIENT_H_
...@@ -6,111 +6,40 @@ ...@@ -6,111 +6,40 @@
#include "ash/public/cpp/assistant/assistant_image_downloader.h" #include "ash/public/cpp/assistant/assistant_image_downloader.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper.pb.h"
#include "chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "components/account_id/account_id.h" #include "components/account_id/account_id.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
namespace { PhotoControllerImpl::PhotoControllerImpl() : weak_factory_(this) {
photo_client_ = PhotoClient::Create();
// TODO(wutao): Discuss with UX if we should use pixel size and extract this
// helper function to be used by wallpaper_private_api.cc as well.
// Returns a suffix to be appended to the base url of Backdrop wallpapers.
std::string GetBackdropWallpaperSuffix() {
// FIFE url is used for Backdrop wallpapers and the desired image size should
// be specified. Currently we are using two times the display size. This is
// determined by trial and error and is subject to change.
gfx::Size display_size =
display::Screen::GetScreen()->GetPrimaryDisplay().size();
return "=w" + base::NumberToString(
2 * std::max(display_size.width(), display_size.height()));
}
std::string GetImageUrl(const backdrop::Image& image) {
return image.image_url() + GetBackdropWallpaperSuffix();
} }
} // namespace
PhotoControllerImpl::PhotoControllerImpl() : weak_factory_(this) {}
PhotoControllerImpl::~PhotoControllerImpl() = default; PhotoControllerImpl::~PhotoControllerImpl() = default;
void PhotoControllerImpl::GetNextImage(PhotoDownloadCallback callback) { void PhotoControllerImpl::GetNextImage(PhotoDownloadCallback callback) {
if (collections_list_.empty()) { photo_client_->FetchTopicInfo(
GetCollectionsList(std::move(callback)); base::BindOnce(&PhotoControllerImpl::OnNextImageInfoFetched,
return;
}
GetNextRandomImage(std::move(callback));
}
void PhotoControllerImpl::GetCollectionsList(PhotoDownloadCallback callback) {
if (!collection_info_fetcher_) {
collection_info_fetcher_ =
std::make_unique<backdrop_wallpaper_handlers::CollectionInfoFetcher>();
}
// If this function is called consecutively, it is possible to invalidate the
// previous callback. This is fine because we only need the latest collection
// info.
collection_info_fetcher_->Start(
base::BindOnce(&PhotoControllerImpl::OnCollectionsInfoFetched,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void PhotoControllerImpl::OnCollectionsInfoFetched(
PhotoDownloadCallback callback,
bool success,
const std::vector<backdrop::Collection>& collections_list) {
if (!success || collections_list.empty()) {
std::move(callback).Run(gfx::ImageSkia());
return;
}
collections_list_ = collections_list;
// TODO(wutao): Get |collection_id_| from settings. We need to handle the case
// |collection_id_| is not in the latest list, e.g. user deleted some
// collections but didn't update the settings on device.
collection_id_ = collections_list_[0].collection_id();
GetNextRandomImage(std::move(callback));
}
void PhotoControllerImpl::GetNextRandomImage(PhotoDownloadCallback callback) {
// If this function is called consecutively, it is possible to invalidate the
// previous request and callback and prevent fetching images in parallel.
// TODO(wutao): Refactor SurpriseMeImageFetcher::Start to take |resume_token_|
// in order not to create |surprise_me_image_fetcher_| every time.
surprise_me_image_fetcher_ =
std::make_unique<backdrop_wallpaper_handlers::SurpriseMeImageFetcher>(
collection_id_, resume_token_);
surprise_me_image_fetcher_->Start(
base::BindOnce(&PhotoControllerImpl::OnNextRandomImageInfoFetched,
weak_factory_.GetWeakPtr(), std::move(callback))); weak_factory_.GetWeakPtr(), std::move(callback)));
} }
void PhotoControllerImpl::OnNextRandomImageInfoFetched( void PhotoControllerImpl::OnNextImageInfoFetched(
PhotoDownloadCallback callback, PhotoDownloadCallback callback,
bool success, bool success,
const backdrop::Image& image, const base::Optional<ash::PhotoController::Topic>& topic) {
const std::string& new_resume_token) { if (!success ||
if (!success || image.image_url().empty()) { (topic->url.empty() && !topic->portrait_image_url.has_value())) {
std::move(callback).Run(gfx::ImageSkia()); std::move(callback).Run(/*success=*/false, gfx::ImageSkia());
return; return;
} }
resume_token_ = new_resume_token; std::string image_url = topic->portrait_image_url.value_or(topic->url);
std::string image_url = GetImageUrl(image);
AccountId account_id = AccountId account_id =
chromeos::ProfileHelper::Get() chromeos::ProfileHelper::Get()
->GetUserByProfile(ProfileManager::GetActiveUserProfile()) ->GetUserByProfile(ProfileManager::GetActiveUserProfile())
->GetAccountId(); ->GetAccountId();
ash::AssistantImageDownloader::GetInstance()->Download( ash::AssistantImageDownloader::GetInstance()->Download(
account_id, GURL(image_url), std::move(callback)); account_id, GURL(image_url),
base::BindOnce(std::move(callback), success));
} }
...@@ -6,21 +6,12 @@ ...@@ -6,21 +6,12 @@
#define CHROME_BROWSER_UI_ASH_AMBIENT_PHOTO_CONTROLLER_IMPL_H_ #define CHROME_BROWSER_UI_ASH_AMBIENT_PHOTO_CONTROLLER_IMPL_H_
#include <string> #include <string>
#include <vector>
#include "ash/public/cpp/ambient/photo_controller.h" #include "ash/public/cpp/ambient/photo_controller.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h"
namespace backdrop { #include "chrome/browser/ui/ash/ambient/photo_client.h"
class Collection;
class Image;
} // namespace backdrop
namespace backdrop_wallpaper_handlers {
class CollectionInfoFetcher;
class SurpriseMeImageFetcher;
} // namespace backdrop_wallpaper_handlers
// TODO(wutao): Move this class to ash. // TODO(wutao): Move this class to ash.
// Class to handle photos from Backdrop service. // Class to handle photos from Backdrop service.
...@@ -35,25 +26,12 @@ class PhotoControllerImpl : public ash::PhotoController { ...@@ -35,25 +26,12 @@ class PhotoControllerImpl : public ash::PhotoController {
void GetNextImage(PhotoDownloadCallback callback) override; void GetNextImage(PhotoDownloadCallback callback) override;
private: private:
void GetCollectionsList(PhotoDownloadCallback callback); void OnNextImageInfoFetched(
void OnCollectionsInfoFetched(
PhotoDownloadCallback callback, PhotoDownloadCallback callback,
bool success, bool success,
const std::vector<backdrop::Collection>& collections_list); const base::Optional<ash::PhotoController::Topic>& topic);
void GetNextRandomImage(PhotoDownloadCallback callback);
void OnNextRandomImageInfoFetched(PhotoDownloadCallback callback, std::unique_ptr<PhotoClient> photo_client_;
bool success,
const backdrop::Image& image,
const std::string& new_resume_token);
std::vector<backdrop::Collection> collections_list_;
std::string collection_id_;
std::string resume_token_;
std::unique_ptr<backdrop_wallpaper_handlers::CollectionInfoFetcher>
collection_info_fetcher_;
std::unique_ptr<backdrop_wallpaper_handlers::SurpriseMeImageFetcher>
surprise_me_image_fetcher_;
base::WeakPtrFactory<PhotoControllerImpl> weak_factory_; base::WeakPtrFactory<PhotoControllerImpl> weak_factory_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment