Skip to content

Commit

Permalink
Add APIs to pause/resume/cancel/open-when-complete Lacros downloads.
Browse files Browse the repository at this point in the history
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 <dmblack@google.com>
Reviewed-by: Erik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#907312}
  • Loading branch information
David Black authored and Chromium LUCI CQ committed Jul 30, 2021
1 parent b1c36bc commit 0cdec65
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 2 deletions.
29 changes: 29 additions & 0 deletions chrome/browser/ash/crosapi/download_controller_ash.cc
Expand Up @@ -14,6 +14,11 @@ void DownloadControllerAsh::BindReceiver(
receivers_.Add(this, std::move(pending_receiver));
}

void DownloadControllerAsh::BindClient(
mojo::PendingRemote<mojom::DownloadControllerClient> client) {
clients_.Add(std::move(client));
}

void DownloadControllerAsh::OnDownloadCreated(
crosapi::mojom::DownloadEventPtr event) {
for (auto& observer : observers_)
Expand Down Expand Up @@ -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
27 changes: 27 additions & 0 deletions chrome/browser/ash/crosapi/download_controller_ash.h
Expand Up @@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_ASH_CROSAPI_DOWNLOAD_CONTROLLER_ASH_H_
#define CHROME_BROWSER_ASH_CROSAPI_DOWNLOAD_CONTROLLER_ASH_H_

#include <string>

#include "base/observer_list_types.h"
#include "chromeos/crosapi/mojom/download_controller.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
Expand Down Expand Up @@ -36,6 +38,8 @@ class DownloadControllerAsh : public mojom::DownloadController {
void BindReceiver(mojo::PendingReceiver<mojom::DownloadController> receiver);

// mojom::DownloadController:
void BindClient(
mojo::PendingRemote<mojom::DownloadControllerClient> client) override;
void OnDownloadCreated(mojom::DownloadEventPtr event) override;
void OnDownloadUpdated(mojom::DownloadEventPtr event) override;
void OnDownloadDestroyed(mojom::DownloadEventPtr event) override;
Expand All @@ -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<mojom::DownloadController> receivers_;
mojo::RemoteSet<mojom::DownloadControllerClient> clients_;
base::ObserverList<DownloadControllerObserver> observers_;
};

Expand Down
87 changes: 87 additions & 0 deletions chrome/browser/lacros/download_controller_client_lacros.cc
Expand Up @@ -15,6 +15,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"

namespace {

crosapi::mojom::DownloadState ConvertDownloadState(
download::DownloadItem::DownloadState value) {
switch (value) {
Expand Down Expand Up @@ -53,6 +54,7 @@ crosapi::mojom::DownloadEventPtr BuildDownloadEvent(
dle->has_total_bytes = true;
return dle;
}

} // namespace

// A wrapper for `base::ScopedObservation` and `DownloadManageObserver` that
Expand All @@ -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 {
Expand Down Expand Up @@ -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_;
Expand All @@ -136,13 +182,54 @@ DownloadControllerClientLacros::DownloadControllerClientLacros() {
auto profiles = g_browser_process->profile_manager()->GetLoadedProfiles();
for (auto* profile : profiles)
OnProfileAdded(profile);

auto* service = chromeos::LacrosService::Get();
if (!service->IsAvailable<crosapi::mojom::DownloadController>())
return;

int remote_version =
service->GetInterfaceVersion(crosapi::mojom::DownloadController::Uuid_);
if (remote_version < 0 ||
static_cast<uint32_t>(remote_version) <
crosapi::mojom::DownloadController::kBindClientMinVersion) {
return;
}

service->GetRemote<crosapi::mojom::DownloadController>()->BindClient(
client_receiver_.BindNewPipeAndPassRemoteWithVersion());
}

DownloadControllerClientLacros::~DownloadControllerClientLacros() {
if (g_browser_process && g_browser_process->profile_manager())
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();
Expand Down
19 changes: 17 additions & 2 deletions chrome/browser/lacros/download_controller_client_lacros.h
Expand Up @@ -7,6 +7,7 @@

#include <memory>
#include <set>
#include <string>

#include "base/containers/unique_ptr_adapters.h"
#include "base/scoped_multi_source_observation.h"
Expand All @@ -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;
Expand All @@ -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&) =
Expand All @@ -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;

Expand All @@ -54,6 +66,9 @@ class DownloadControllerClientLacros : public ProfileManagerObserver,

base::ScopedMultiSourceObservation<Profile, ProfileObserver>
profile_observer_{this};

mojo::Receiver<crosapi::mojom::DownloadControllerClient> client_receiver_{
this};
};

#endif // CHROME_BROWSER_LACROS_DOWNLOAD_CONTROLLER_CLIENT_LACROS_H_
38 changes: 38 additions & 0 deletions chromeos/crosapi/mojom/download_controller.mojom
Expand Up @@ -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<DownloadControllerClient> 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);
};

0 comments on commit 0cdec65

Please sign in to comment.