From 0cdec653f5259aaa3686015416f080314be729da Mon Sep 17 00:00:00 2001 From: David Black Date: Fri, 30 Jul 2021 23:28:41 +0000 Subject: [PATCH] Add APIs to pause/resume/cancel/open-when-complete Lacros downloads. This CL adds a client interface, implemented in Lacros, by which Ash can pause/resume/cancel/open-when-complete downloads. In a follow up CL, this will be used by the Tote feature in CrOS system UI. Bug: 1184438 Change-Id: Ib5f88670d5f13aedd19a38cf5a55f76b85d042c2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3062719 Commit-Queue: David Black Reviewed-by: Erik Chen Cr-Commit-Position: refs/heads/master@{#907312} --- .../ash/crosapi/download_controller_ash.cc | 29 +++++++ .../ash/crosapi/download_controller_ash.h | 27 ++++++ .../download_controller_client_lacros.cc | 87 +++++++++++++++++++ .../download_controller_client_lacros.h | 19 +++- .../crosapi/mojom/download_controller.mojom | 38 ++++++++ 5 files changed, 198 insertions(+), 2 deletions(-) diff --git a/chrome/browser/ash/crosapi/download_controller_ash.cc b/chrome/browser/ash/crosapi/download_controller_ash.cc index cf651fe1b4647..2b9a5986bfd1c 100644 --- a/chrome/browser/ash/crosapi/download_controller_ash.cc +++ b/chrome/browser/ash/crosapi/download_controller_ash.cc @@ -14,6 +14,11 @@ void DownloadControllerAsh::BindReceiver( receivers_.Add(this, std::move(pending_receiver)); } +void DownloadControllerAsh::BindClient( + mojo::PendingRemote client) { + clients_.Add(std::move(client)); +} + void DownloadControllerAsh::OnDownloadCreated( crosapi::mojom::DownloadEventPtr event) { for (auto& observer : observers_) @@ -41,4 +46,28 @@ void DownloadControllerAsh::RemoveObserver( observers_.RemoveObserver(observer); } +void DownloadControllerAsh::Pause(const std::string& download_guid) { + for (auto& client : clients_) + client->Pause(download_guid); +} + +void DownloadControllerAsh::Resume(const std::string& download_guid, + bool user_resume) { + for (auto& client : clients_) + client->Resume(download_guid, user_resume); +} + +void DownloadControllerAsh::Cancel(const std::string& download_guid, + bool user_cancel) { + for (auto& client : clients_) + client->Cancel(download_guid, user_cancel); +} + +void DownloadControllerAsh::SetOpenWhenComplete( + const std::string& download_guid, + bool open_when_complete) { + for (auto& client : clients_) + client->SetOpenWhenComplete(download_guid, open_when_complete); +} + } // namespace crosapi diff --git a/chrome/browser/ash/crosapi/download_controller_ash.h b/chrome/browser/ash/crosapi/download_controller_ash.h index 03d4860044153..b128a74257324 100644 --- a/chrome/browser/ash/crosapi/download_controller_ash.h +++ b/chrome/browser/ash/crosapi/download_controller_ash.h @@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_ASH_CROSAPI_DOWNLOAD_CONTROLLER_ASH_H_ #define CHROME_BROWSER_ASH_CROSAPI_DOWNLOAD_CONTROLLER_ASH_H_ +#include + #include "base/observer_list_types.h" #include "chromeos/crosapi/mojom/download_controller.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -36,6 +38,8 @@ class DownloadControllerAsh : public mojom::DownloadController { void BindReceiver(mojo::PendingReceiver receiver); // mojom::DownloadController: + void BindClient( + mojo::PendingRemote client) override; void OnDownloadCreated(mojom::DownloadEventPtr event) override; void OnDownloadUpdated(mojom::DownloadEventPtr event) override; void OnDownloadDestroyed(mojom::DownloadEventPtr event) override; @@ -44,8 +48,31 @@ class DownloadControllerAsh : public mojom::DownloadController { void AddObserver(DownloadControllerObserver* observer); void RemoveObserver(DownloadControllerObserver* observer); + // Pauses the download associated with the specified `download_guid`. This + // method will ultimately invoke `download::DownloadItem::Pause()`. + void Pause(const std::string& download_guid); + + // Resumes the download associated with the specified `download_guid`. If + // `user_resume` is set to `true`, it signifies that this invocation was + // triggered by an explicit user action. This method will ultimately invoke + // `download::DownloadItem::Resume()`. + void Resume(const std::string& download_guid, bool user_resume); + + // Cancels the download associated with the specified `download_guid`. If + // `user_cancel` is set to `true`, it signifies that this invocation was + // triggered by an explicit user action. This method will ultimately invoke + // `download::DownloadItem::Cancel()`. + void Cancel(const std::string& download_guid, bool user_cancel); + + // Marks the download associated with the specified `download_guid` to be + // `open_when_complete`. This method will ultimately invoke + // `download::DownloadItem::SetOpenWhenComplete()`. + void SetOpenWhenComplete(const std::string& download_guid, + bool open_when_complete); + private: mojo::ReceiverSet receivers_; + mojo::RemoteSet clients_; base::ObserverList observers_; }; diff --git a/chrome/browser/lacros/download_controller_client_lacros.cc b/chrome/browser/lacros/download_controller_client_lacros.cc index ff33f195f3f32..9d71d3c1bce4a 100644 --- a/chrome/browser/lacros/download_controller_client_lacros.cc +++ b/chrome/browser/lacros/download_controller_client_lacros.cc @@ -15,6 +15,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" namespace { + crosapi::mojom::DownloadState ConvertDownloadState( download::DownloadItem::DownloadState value) { switch (value) { @@ -53,6 +54,7 @@ crosapi::mojom::DownloadEventPtr BuildDownloadEvent( dle->has_total_bytes = true; return dle; } + } // namespace // A wrapper for `base::ScopedObservation` and `DownloadManageObserver` that @@ -74,6 +76,40 @@ class DownloadControllerClientLacros::ObservableDownloadManager ~ObservableDownloadManager() override = default; + // Pauses the download associated with the specified `download_guid`. + void Pause(const std::string& download_guid) { + download::DownloadItem* download = GetDownloadByGuid(download_guid); + if (download) + download->Pause(); + } + + // Resumes the download associated with the specified `download_guid`. If + // `user_resume` is `true`, it signifies that this invocation was triggered by + // an explicit user action. + void Resume(const std::string& download_guid, bool user_resume) { + download::DownloadItem* download = GetDownloadByGuid(download_guid); + if (download) + download->Resume(user_resume); + } + + // Cancels the download associated with the specified `download_guid`. If + // `user_cancel` is `true`, it signifies that this invocation was triggered by + // an explicit user action. + void Cancel(const std::string& download_guid, bool user_cancel) { + download::DownloadItem* download = GetDownloadByGuid(download_guid); + if (download) + download->Cancel(user_cancel); + } + + // Marks the download associated with the specified `download_guid` to be + // `open_when_complete`. + void SetOpenWhenComplete(const std::string& download_guid, + bool open_when_complete) { + download::DownloadItem* download = GetDownloadByGuid(download_guid); + if (download) + download->SetOpenWhenComplete(open_when_complete); + } + private: // content::DownloadManager::Observer: void OnManagerInitialized() override { @@ -118,6 +154,16 @@ class DownloadControllerClientLacros::ObservableDownloadManager controller_client_->OnDownloadDestroyed(item); } + download::DownloadItem* GetDownloadByGuid(const std::string& guid) { + download::SimpleDownloadManager::DownloadVector downloads; + manager_->GetAllDownloads(&downloads); + for (auto* download : downloads) { + if (download->GetGuid() == guid) + return download; + } + return nullptr; + } + DownloadControllerClientLacros* const controller_client_; content::DownloadManager* const manager_; @@ -136,6 +182,21 @@ DownloadControllerClientLacros::DownloadControllerClientLacros() { auto profiles = g_browser_process->profile_manager()->GetLoadedProfiles(); for (auto* profile : profiles) OnProfileAdded(profile); + + auto* service = chromeos::LacrosService::Get(); + if (!service->IsAvailable()) + return; + + int remote_version = + service->GetInterfaceVersion(crosapi::mojom::DownloadController::Uuid_); + if (remote_version < 0 || + static_cast(remote_version) < + crosapi::mojom::DownloadController::kBindClientMinVersion) { + return; + } + + service->GetRemote()->BindClient( + client_receiver_.BindNewPipeAndPassRemoteWithVersion()); } DownloadControllerClientLacros::~DownloadControllerClientLacros() { @@ -143,6 +204,32 @@ DownloadControllerClientLacros::~DownloadControllerClientLacros() { g_browser_process->profile_manager()->RemoveObserver(this); } +void DownloadControllerClientLacros::Pause(const std::string& download_guid) { + for (auto& observable_download_manager : observable_download_managers_) + observable_download_manager->Pause(download_guid); +} + +void DownloadControllerClientLacros::Resume(const std::string& download_guid, + bool user_resume) { + for (auto& observable_download_manager : observable_download_managers_) + observable_download_manager->Resume(download_guid, user_resume); +} + +void DownloadControllerClientLacros::Cancel(const std::string& download_guid, + bool user_cancel) { + for (auto& observable_download_manager : observable_download_managers_) + observable_download_manager->Cancel(download_guid, user_cancel); +} + +void DownloadControllerClientLacros::SetOpenWhenComplete( + const std::string& download_guid, + bool open_when_complete) { + for (auto& observable_download_manager : observable_download_managers_) { + observable_download_manager->SetOpenWhenComplete(download_guid, + open_when_complete); + } +} + void DownloadControllerClientLacros::OnProfileAdded(Profile* profile) { profile_observer_.AddObservation(profile); auto* manager = profile->GetDownloadManager(); diff --git a/chrome/browser/lacros/download_controller_client_lacros.h b/chrome/browser/lacros/download_controller_client_lacros.h index 78affad085c96..206ac24a261e7 100644 --- a/chrome/browser/lacros/download_controller_client_lacros.h +++ b/chrome/browser/lacros/download_controller_client_lacros.h @@ -7,6 +7,7 @@ #include #include +#include #include "base/containers/unique_ptr_adapters.h" #include "base/scoped_multi_source_observation.h" @@ -15,6 +16,8 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager_observer.h" #include "chrome/browser/profiles/profile_observer.h" +#include "chromeos/crosapi/mojom/download_controller.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" namespace download { class DownloadItem; @@ -23,8 +26,10 @@ class DownloadItem; // This class receives and forwards download events to Ash. It can only be // used on the main thread. In the near future, it will also be the receiver for // calls to pause, cancel, and resume downloads from ash-chrome, hence the name. -class DownloadControllerClientLacros : public ProfileManagerObserver, - public ProfileObserver { +class DownloadControllerClientLacros + : public crosapi::mojom::DownloadControllerClient, + public ProfileManagerObserver, + public ProfileObserver { public: DownloadControllerClientLacros(); DownloadControllerClientLacros(const DownloadControllerClientLacros&) = @@ -36,6 +41,13 @@ class DownloadControllerClientLacros : public ProfileManagerObserver, private: class ObservableDownloadManager; + // crosapi::mojom::DownloadControllerClient: + void Pause(const std::string& download_guid) override; + void Resume(const std::string& download_guid, bool user_resume) override; + void Cancel(const std::string& download_guid, bool user_cancel) override; + void SetOpenWhenComplete(const std::string& download_guid, + bool open_when_complete) override; + // ProfileManagerObserver: void OnProfileAdded(Profile* profile) override; @@ -54,6 +66,9 @@ class DownloadControllerClientLacros : public ProfileManagerObserver, base::ScopedMultiSourceObservation profile_observer_{this}; + + mojo::Receiver client_receiver_{ + this}; }; #endif // CHROME_BROWSER_LACROS_DOWNLOAD_CONTROLLER_CLIENT_LACROS_H_ diff --git a/chromeos/crosapi/mojom/download_controller.mojom b/chromeos/crosapi/mojom/download_controller.mojom index 2023ef5ca5064..f3c284e8c9c92 100644 --- a/chromeos/crosapi/mojom/download_controller.mojom +++ b/chromeos/crosapi/mojom/download_controller.mojom @@ -43,15 +43,53 @@ struct DownloadEvent { [MinVersion=1] int64 total_bytes@12; }; +// A client implemented in lacros-chrome for the DownloadController which is +// implemented in ash-chrome. +[Stable, Uuid="eccf720b-538a-4943-a6fd-d073639c4140"] +interface DownloadControllerClient { + + // Pauses the download associated with the specified `download_guid`. This + // method will ultimately invoke `download::DownloadItem::Pause()`. + Pause@1(string download_guid); + + // Resumes the download associated with the specified `download_guid`. If + // `user_resume` is set to `true`, it signifies that this invocation was + // triggered by an explicit user action. This method will ultimately invoke + // `download::DownloadItem::Resume()`. + Resume@2(string download_guid, bool user_resume); + + // Cancels the download associated with the specified `download_guid`. If + // `user_cancel` is set to `true`, it signifies that this invocation was + // triggered by an explicit user action. This method will ultimately invoke + // `download::DownloadItem::Cancel()`. + Cancel@3(string download_guid, bool user_cancel); + + // Marks the download associated with the specified `download_guid` to be + // `open_when_complete`. This method will ultimately invoke + // `download::DownloadItem::SetOpenWhenComplete()`. + SetOpenWhenComplete@4(string download_guid, bool open_when_complete); +}; + // Allows lacros to pass download information to ash-chrome. // Implemented in ash-chrome. +// +// Next MinVersion: 2 +// Next ID: 4 [Stable, Uuid="c3d8bd4b-1fc9-4529-aeb2-76770b0ad1c3"] interface DownloadController { + // Binds the DownloadControllerClient interface, which allows the + // DownloadController implemented in ash-chrome to communicate with its client + // which is implemented in lacros-chrome. + [MinVersion=1] BindClient@3( + pending_remote client); + // Called when a download is created. Comes from `content::DownloadManager`, // and will only pass events once that's initialized. OnDownloadCreated@0(crosapi.mojom.DownloadEvent event); + // Called whenever a `download::DownloadItem` is updated. OnDownloadUpdated@1(crosapi.mojom.DownloadEvent event); + // Called when a `download::DownloadItem` is destroyed. OnDownloadDestroyed@2(crosapi.mojom.DownloadEvent event); };