blob: 81f2a8178cb5df121925e33f3bedafea3ab5e6d0 [file] [log] [blame]
// 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_CHROMEOS_REMOTE_APPS_REMOTE_APPS_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_REMOTE_APPS_REMOTE_APPS_MANAGER_H_
#include <map>
#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observer.h"
#include "chrome/browser/apps/app_service/remote_apps.h"
#include "chrome/browser/chromeos/remote_apps/remote_apps_impl.h"
#include "chrome/browser/chromeos/remote_apps/remote_apps_model.h"
#include "chrome/browser/chromeos/remote_apps/remote_apps_types.h"
#include "chrome/browser/ui/app_list/app_list_model_updater_observer.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
#include "chrome/browser/ui/app_list/chrome_app_list_model_updater.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 {
class AppUpdate;
} // namespace apps
namespace gfx {
class ImageSkia;
} // namespace gfx
namespace chromeos {
class RemoteAppsImpl;
// KeyedService which manages the logic for |AppType::kRemote| in AppService.
// This service is only created for Managed Guest Sessions.
// The IDs of the added apps and folders are GUIDs generated using
// |base::GenerateGUID()|.
// 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 remote_apps::mojom::RemoteAppsFactory {
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 BindInterface(
mojo::PendingReceiver<remote_apps::mojom::RemoteAppsFactory>
pending_remote_apps_factory);
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.
// 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& name,
const std::string& folder_id,
const GURL& icon_url,
AddAppCallback callback);
// Deletes the app with id |id|.
// Deleting a non-existent app will result in an error.
RemoteAppsError DeleteApp(const std::string& id);
// Adds a folder with |folder_name|. Note that empty folders are not
// shown in the launcher. Returns the ID for the added folder.
std::string AddFolder(const std::string& folder_name);
// 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);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// KeyedService:
void Shutdown() override;
// remote_apps::mojom::RemoteAppsFactory:
void Create(
mojo::PendingReceiver<remote_apps::mojom::RemoteApps> pending_remote_apps,
mojo::PendingRemote<remote_apps::mojom::RemoteAppLaunchObserver>
pending_observer) override;
// apps::RemoteApps::Delegate:
const std::map<std::string, RemoteAppsModel::AppInfo>& GetApps() override;
void LaunchApp(const std::string& 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::mojom::MenuItemsPtr GetMenuModel(const std::string& id) override;
// app_list::AppListSyncableService::Observer:
void OnSyncModelUpdated() override;
// AppListModelUpdaterObserver:
void OnAppListItemAdded(ChromeAppListItem* item) override;
void SetRemoteAppsForTesting(std::unique_ptr<apps::RemoteApps> remote_apps);
void SetImageDownloaderForTesting(
std::unique_ptr<ImageDownloader> image_downloader);
RemoteAppsModel* GetModelForTesting();
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);
Profile* profile_ = nullptr;
bool is_initialized_ = false;
app_list::AppListSyncableService* app_list_syncable_service_ = nullptr;
AppListModelUpdater* model_updater_ = 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<remote_apps::mojom::RemoteAppsFactory> 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_;
ScopedObserver<app_list::AppListSyncableService,
app_list::AppListSyncableService::Observer,
&app_list::AppListSyncableService::AddObserverAndStart>
app_list_syncable_service_observer_{this};
ScopedObserver<AppListModelUpdater, AppListModelUpdaterObserver>
app_list_model_updater_observer_{this};
base::WeakPtrFactory<RemoteAppsManager> weak_factory_{this};
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_REMOTE_APPS_REMOTE_APPS_MANAGER_H_