1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
// Copyright 2020 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_REMOTE_APPS_REMOTE_APPS_MANAGER_H_
#define CHROME_BROWSER_ASH_REMOTE_APPS_REMOTE_APPS_MANAGER_H_
#include <map>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "chrome/browser/apps/app_service/publishers/remote_apps.h"
#include "chrome/browser/ash/app_list/app_list_model_updater_observer.h"
#include "chrome/browser/ash/app_list/app_list_syncable_service.h"
#include "chrome/browser/ash/app_list/chrome_app_list_model_updater.h"
#include "chrome/browser/ash/remote_apps/remote_apps_impl.h"
#include "chrome/browser/ash/remote_apps/remote_apps_model.h"
#include "chrome/browser/ash/remote_apps/remote_apps_types.h"
#include "chromeos/components/remote_apps/mojom/remote_apps.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
class AppListModelUpdater;
class ChromeAppListItem;
class Profile;
namespace apps {
struct MenuItems;
} // namespace apps
namespace gfx {
class ImageSkia;
} // namespace gfx
namespace extensions {
class EventRouter;
} // namespace extensions
namespace ash {
class RemoteAppsImpl;
// KeyedService which manages the logic for |AppType::kRemote| in AppService.
// This service is created for Managed Guest Sessions and Regular User Sessions.
// The IDs of the added apps and folders are GUIDs generated using
// |base::Uuid::GenerateRandomV4().AsLowercaseString()|.
// See crbug.com/1101208 for more details on Remote Apps.
class RemoteAppsManager
: public KeyedService,
public apps::RemoteApps::Delegate,
public app_list::AppListSyncableService::Observer,
public AppListModelUpdaterObserver,
public chromeos::remote_apps::mojom::RemoteAppsFactory,
public chromeos::remote_apps::mojom::RemoteAppsLacrosBridge {
public:
class Observer : public base::CheckedObserver {
public:
~Observer() override = default;
// Invoked when an app is launched. |id| is the ID of the app.
virtual void OnAppLaunched(const std::string& id) {}
};
class ImageDownloader {
public:
virtual ~ImageDownloader() = default;
using DownloadCallback = base::OnceCallback<void(const gfx::ImageSkia&)>;
virtual void Download(const GURL& url, DownloadCallback callback) = 0;
};
explicit RemoteAppsManager(Profile* profile);
RemoteAppsManager(const RemoteAppsManager&) = delete;
RemoteAppsManager& operator=(const RemoteAppsManager&) = delete;
~RemoteAppsManager() override;
bool is_initialized() const { return is_initialized_; }
void BindFactoryInterface(
mojo::PendingReceiver<chromeos::remote_apps::mojom::RemoteAppsFactory>
pending_remote_apps_factory);
void BindLacrosBridgeInterface(
mojo::PendingReceiver<
chromeos::remote_apps::mojom::RemoteAppsLacrosBridge>
pending_remote_apps_lacros_bridge);
using AddAppCallback =
base::OnceCallback<void(const std::string& id, RemoteAppsError error)>;
// Adds a app with the given `name`. If `folder_id` is non-empty, the app is
// added to the folder with the given ID. The icon of the app is an image
// retrieved from `icon_url` and is retrieved asynchronously. If the icon has
// not been downloaded, or there is an error in downloading the icon, a
// placeholder icon will be used. If `add_to_front` is true and the app has
// no parent folder, the app will be added to the front of the app item list.
// `source_id` is a string used to identify the caller of this method. This
// identifier is typically an extension or app ID.
// The callback will be run with the ID of the added app, or an error if
// there is one.
// Adding to a non-existent folder will result in an error.
// Adding an app before the manager is initialized will result in an error.
void AddApp(const std::string& source_id,
const std::string& name,
const std::string& folder_id,
const GURL& icon_url,
bool add_to_front,
AddAppCallback callback);
// Adds a folder if the specified folder is missing in `model_updater_`.
void MaybeAddFolder(const std::string& folder_id);
// Returns a const pointer to the info of the specified app. If the app does
// not exist, returns a nullptr.
const RemoteAppsModel::AppInfo* GetAppInfo(const std::string& app_id) const;
// Deletes the app with id |id|.
// Deleting a non-existent app will result in an error.
RemoteAppsError DeleteApp(const std::string& id);
// Sorts the launcher items with the custom kAlphabeticalEphemeralAppFirst
// sort order which moves the remote apps to the front of the launcher.
void SortLauncherWithRemoteAppsFirst();
// Sets the list of apps to be pinned on the shelf. If `app_ids` are empty
// it should unpin all currently pinned apps.
RemoteAppsError SetPinnedApps(const std::vector<std::string>& app_ids);
// Adds a folder with |folder_name|. Note that empty folders are not shown in
// the launcher. Returns the ID for the added folder. If |add_to_front| is
// true, the folder will be added to the front of the app item list.
std::string AddFolder(const std::string& folder_name, bool add_to_front);
// Deletes the folder with id |folder_id|. All items in the folder are moved
// to the top-level in the launcher.
// Deleting a non-existent folder will result in an error.
RemoteAppsError DeleteFolder(const std::string& folder_id);
// Returns true if the app or folder with |id| should be added to the front
// of the app item list.
bool ShouldAddToFront(const std::string& id) const;
// KeyedService:
void Shutdown() override;
// chromeos::remote_apps::mojom::RemoteAppsFactory:
void BindRemoteAppsAndAppLaunchObserver(
const std::string& source_id,
mojo::PendingReceiver<chromeos::remote_apps::mojom::RemoteApps>
pending_remote_apps,
mojo::PendingRemote<chromeos::remote_apps::mojom::RemoteAppLaunchObserver>
pending_observer) override;
// chromeos::remote_apps::mojom::RemoteAppsLacrosBridge:
void BindRemoteAppsAndAppLaunchObserverForLacros(
mojo::PendingReceiver<chromeos::remote_apps::mojom::RemoteApps>
pending_remote_apps,
mojo::PendingRemote<chromeos::remote_apps::mojom::RemoteAppLaunchObserver>
pending_observer) override;
// apps::RemoteApps::Delegate:
const std::map<std::string, RemoteAppsModel::AppInfo>& GetApps() override;
void LaunchApp(const std::string& app_id) override;
gfx::ImageSkia GetIcon(const std::string& id) override;
gfx::ImageSkia GetPlaceholderIcon(const std::string& id,
int32_t size_hint_in_dip) override;
apps::MenuItems GetMenuModel(const std::string& id) override;
// app_list::AppListSyncableService::Observer:
void OnSyncModelUpdated() override;
// AppListModelUpdaterObserver:
void OnAppListItemAdded(ChromeAppListItem* item) override;
void SetImageDownloaderForTesting(
std::unique_ptr<ImageDownloader> image_downloader);
RemoteAppsModel* GetModelForTesting();
RemoteAppsImpl& GetRemoteAppsImpl() { return remote_apps_impl_; }
void SetIsInitializedForTesting(bool is_initialized);
private:
void Initialize();
void HandleOnAppAdded(const std::string& id);
void HandleOnFolderCreated(const std::string& folder_id);
void StartIconDownload(const std::string& id, const GURL& icon_url);
void OnIconDownloaded(const std::string& id, const gfx::ImageSkia& icon);
raw_ptr<Profile> profile_ = nullptr;
bool is_initialized_ = false;
raw_ptr<app_list::AppListSyncableService> app_list_syncable_service_ =
nullptr;
raw_ptr<AppListModelUpdater> model_updater_ = nullptr;
raw_ptr<extensions::EventRouter> event_router_ = nullptr;
std::unique_ptr<apps::RemoteApps> remote_apps_;
RemoteAppsImpl remote_apps_impl_{this};
std::unique_ptr<RemoteAppsModel> model_;
std::unique_ptr<ImageDownloader> image_downloader_;
base::ObserverList<Observer> observer_list_;
mojo::ReceiverSet<chromeos::remote_apps::mojom::RemoteAppsFactory>
factory_receivers_;
mojo::ReceiverSet<chromeos::remote_apps::mojom::RemoteAppsLacrosBridge>
bridge_receivers_;
// Map from id to callback. The callback is run after |OnAppUpdate| for the
// app has been observed.
std::map<std::string, AddAppCallback> add_app_callback_map_;
std::map<std::string, std::string> app_id_to_source_id_map_;
base::ScopedObservation<app_list::AppListSyncableService,
app_list::AppListSyncableService::Observer>
app_list_syncable_service_observation_{this};
base::ScopedObservation<AppListModelUpdater, AppListModelUpdaterObserver>
app_list_model_updater_observation_{this};
base::WeakPtrFactory<RemoteAppsManager> weak_factory_{this};
};
} // namespace ash
#endif // CHROME_BROWSER_ASH_REMOTE_APPS_REMOTE_APPS_MANAGER_H_
|