blob: 6e5fa998093e154993ed6fed41f9dfb4b148246c [file] [log] [blame]
// Copyright 2018 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/web_applications/web_app_registrar.h"
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/containers/contains.h"
#include "base/containers/cxx20_erase.h"
#include "base/feature_list.h"
#include "base/strings/string_util.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/web_applications/components/app_registrar_observer.h"
#include "chrome/browser/web_applications/components/externally_installed_web_app_prefs.h"
#include "chrome/browser/web_applications/components/install_bounce_metric.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_prefs_utils.h"
#include "chrome/browser/web_applications/components/web_app_utils.h"
#include "chrome/browser/web_applications/os_integration_manager.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_features.h"
#include "content/public/common/content_features.h"
namespace web_app {
namespace {
// With Lacros, only system web apps are exposed using the Ash browser.
bool WebAppExposed(const WebApp& web_app) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (base::FeatureList::IsEnabled(features::kWebAppsCrosapi) &&
!web_app.IsSystemApp()) {
return false;
}
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
if (web_app.IsSystemApp() && !AreSystemWebAppsSupported())
return false;
#endif
return true;
}
} // namespace
WebAppRegistrar::WebAppRegistrar(Profile* profile) : profile_(profile) {}
WebAppRegistrar::~WebAppRegistrar() {
for (AppRegistrarObserver& observer : observers_)
observer.OnAppRegistrarDestroyed();
}
void WebAppRegistrar::SetSubsystems(
OsIntegrationManager* os_integration_manager) {
os_integration_manager_ = os_integration_manager;
}
bool WebAppRegistrar::IsLocallyInstalled(const GURL& start_url) const {
return IsLocallyInstalled(
GenerateAppId(/*manifest_id=*/absl::nullopt, start_url));
}
bool WebAppRegistrar::IsPlaceholderApp(const AppId& app_id) const {
return ExternallyInstalledWebAppPrefs(profile_->GetPrefs())
.IsPlaceholderApp(app_id);
}
void WebAppRegistrar::AddObserver(AppRegistrarObserver* observer) {
observers_.AddObserver(observer);
}
void WebAppRegistrar::RemoveObserver(AppRegistrarObserver* observer) {
observers_.RemoveObserver(observer);
}
void WebAppRegistrar::NotifyWebAppInstalled(const AppId& app_id) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppInstalled(app_id);
// TODO(alancutter): Call RecordWebAppInstallation here when we get access to
// the webapps::WebappInstallSource in this event.
}
void WebAppRegistrar::NotifyWebAppManifestUpdated(const AppId& app_id,
base::StringPiece old_name) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppManifestUpdated(app_id, old_name);
}
void WebAppRegistrar::NotifyWebAppsWillBeUpdatedFromSync(
const std::vector<const WebApp*>& new_apps_state) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppsWillBeUpdatedFromSync(new_apps_state);
}
void WebAppRegistrar::NotifyWebAppUninstalled(const AppId& app_id) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppUninstalled(app_id);
}
void WebAppRegistrar::NotifyWebAppWillBeUninstalled(const AppId& app_id) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppWillBeUninstalled(app_id);
RecordWebAppUninstallation(profile()->GetPrefs(), app_id);
}
void WebAppRegistrar::NotifyWebAppLocallyInstalledStateChanged(
const AppId& app_id,
bool is_locally_installed) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppLocallyInstalledStateChanged(app_id, is_locally_installed);
}
void WebAppRegistrar::NotifyWebAppDisabledStateChanged(const AppId& app_id,
bool is_disabled) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppDisabledStateChanged(app_id, is_disabled);
}
void WebAppRegistrar::NotifyWebAppsDisabledModeChanged() {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppsDisabledModeChanged();
}
void WebAppRegistrar::NotifyWebAppLastLaunchTimeChanged(
const AppId& app_id,
const base::Time& time) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppLastLaunchTimeChanged(app_id, time);
}
void WebAppRegistrar::NotifyWebAppInstallTimeChanged(const AppId& app_id,
const base::Time& time) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppInstallTimeChanged(app_id, time);
}
void WebAppRegistrar::NotifyWebAppProfileWillBeDeleted(const AppId& app_id) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppProfileWillBeDeleted(app_id);
}
void WebAppRegistrar::NotifyWebAppInstalledWithOsHooks(const AppId& app_id) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppInstalledWithOsHooks(app_id);
}
void WebAppRegistrar::NotifyWebAppUserDisplayModeChanged(
const AppId& app_id,
DisplayMode user_display_mode) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppUserDisplayModeChanged(app_id, user_display_mode);
}
void WebAppRegistrar::NotifyWebAppExperimentalTabbedWindowModeChanged(
const AppId& app_id,
bool enabled) {
for (AppRegistrarObserver& observer : observers_)
observer.OnWebAppExperimentalTabbedWindowModeChanged(app_id, enabled);
}
void WebAppRegistrar::NotifyAppRegistrarShutdown() {
for (AppRegistrarObserver& observer : observers_)
observer.OnAppRegistrarShutdown();
}
std::map<AppId, GURL> WebAppRegistrar::GetExternallyInstalledApps(
ExternalInstallSource install_source) const {
std::map<AppId, GURL> installed_apps =
ExternallyInstalledWebAppPrefs::BuildAppIdsMap(profile()->GetPrefs(),
install_source);
base::EraseIf(installed_apps, [this](const std::pair<AppId, GURL>& app) {
return !IsInstalled(app.first);
});
return installed_apps;
}
absl::optional<AppId> WebAppRegistrar::LookupExternalAppId(
const GURL& install_url) const {
return ExternallyInstalledWebAppPrefs(profile()->GetPrefs())
.LookupAppId(install_url);
}
bool WebAppRegistrar::HasExternalApp(const AppId& app_id) const {
return ExternallyInstalledWebAppPrefs::HasAppId(profile()->GetPrefs(),
app_id);
}
bool WebAppRegistrar::HasExternalAppWithInstallSource(
const AppId& app_id,
ExternalInstallSource install_source) const {
return ExternallyInstalledWebAppPrefs::HasAppIdWithInstallSource(
profile()->GetPrefs(), app_id, install_source);
}
GURL WebAppRegistrar::GetAppLaunchUrl(const AppId& app_id) const {
const GURL& start_url = GetAppStartUrl(app_id);
const std::string* launch_query_params = GetAppLaunchQueryParams(app_id);
if (!start_url.is_valid() || !launch_query_params)
return start_url;
GURL::Replacements replacements;
if (start_url.query_piece().empty()) {
replacements.SetQueryStr(*launch_query_params);
return start_url.ReplaceComponents(replacements);
}
if (start_url.query_piece().find(*launch_query_params) !=
base::StringPiece::npos) {
return start_url;
}
std::string query_params = start_url.query() + "&" + *launch_query_params;
replacements.SetQueryStr(query_params);
return start_url.ReplaceComponents(replacements);
}
GURL WebAppRegistrar::GetAppScope(const AppId& app_id) const {
absl::optional<GURL> scope = GetAppScopeInternal(app_id);
if (scope)
return *scope;
if (base::FeatureList::IsEnabled(
features::kDesktopPWAsTabStripLinkCapturing) &&
IsTabbedWindowModeEnabled(app_id)) {
return GetAppStartUrl(app_id).GetOrigin();
}
return GetAppStartUrl(app_id).GetWithoutFilename();
}
absl::optional<AppId> WebAppRegistrar::FindAppWithUrlInScope(
const GURL& url) const {
const std::string url_path = url.spec();
absl::optional<AppId> best_app_id;
size_t best_app_path_length = 0U;
bool best_app_is_shortcut = true;
for (const AppId& app_id : GetAppIds()) {
// TODO(crbug.com/910016): Treat shortcuts as PWAs.
bool app_is_shortcut = IsShortcutApp(app_id);
if (app_is_shortcut && !best_app_is_shortcut)
continue;
const std::string app_path = GetAppScope(app_id).spec();
if ((app_path.size() > best_app_path_length ||
(best_app_is_shortcut && !app_is_shortcut)) &&
base::StartsWith(url_path, app_path, base::CompareCase::SENSITIVE)) {
best_app_id = app_id;
best_app_path_length = app_path.size();
best_app_is_shortcut = app_is_shortcut;
}
}
return best_app_id;
}
bool WebAppRegistrar::DoesScopeContainAnyApp(const GURL& scope) const {
std::string scope_str = scope.spec();
for (const auto& app_id : GetAppIds()) {
if (!IsLocallyInstalled(app_id))
continue;
std::string app_scope = GetAppScope(app_id).spec();
DCHECK(!app_scope.empty());
if (base::StartsWith(app_scope, scope_str, base::CompareCase::SENSITIVE))
return true;
}
return false;
}
std::vector<AppId> WebAppRegistrar::FindAppsInScope(const GURL& scope) const {
std::string scope_str = scope.spec();
std::vector<AppId> in_scope;
for (const auto& app_id : GetAppIds()) {
if (!IsLocallyInstalled(app_id))
continue;
std::string app_scope = GetAppScope(app_id).spec();
DCHECK(!app_scope.empty());
if (!base::StartsWith(app_scope, scope_str, base::CompareCase::SENSITIVE))
continue;
in_scope.push_back(app_id);
}
return in_scope;
}
absl::optional<AppId> WebAppRegistrar::FindInstalledAppWithUrlInScope(
const GURL& url,
bool window_only) const {
const std::string url_path = url.spec();
absl::optional<AppId> best_app_id;
size_t best_app_path_length = 0U;
bool best_app_is_shortcut = true;
for (const AppId& app_id : GetAppIds()) {
// TODO(crbug.com/910016): Treat shortcuts as PWAs.
bool app_is_shortcut = IsShortcutApp(app_id);
if (app_is_shortcut && !best_app_is_shortcut)
continue;
if (!IsLocallyInstalled(app_id))
continue;
if (window_only &&
GetAppEffectiveDisplayMode(app_id) == DisplayMode::kBrowser) {
continue;
}
const std::string app_path = GetAppScope(app_id).spec();
if ((app_path.size() > best_app_path_length ||
(best_app_is_shortcut && !app_is_shortcut)) &&
base::StartsWith(url_path, app_path, base::CompareCase::SENSITIVE)) {
best_app_id = app_id;
best_app_path_length = app_path.size();
best_app_is_shortcut = app_is_shortcut;
}
}
return best_app_id;
}
bool WebAppRegistrar::IsShortcutApp(const AppId& app_id) const {
// TODO (crbug/910016): Make app scope always return a value and record this
// distinction in some other way.
return !GetAppScopeInternal(app_id).has_value();
}
DisplayMode WebAppRegistrar::GetAppEffectiveDisplayMode(
const AppId& app_id) const {
if (!IsLocallyInstalled(app_id))
return DisplayMode::kBrowser;
auto app_display_mode = GetAppDisplayMode(app_id);
auto user_display_mode = GetAppUserDisplayMode(app_id);
if (app_display_mode == DisplayMode::kUndefined ||
user_display_mode == DisplayMode::kUndefined) {
return DisplayMode::kUndefined;
}
std::vector<DisplayMode> display_mode_overrides =
GetAppDisplayModeOverride(app_id);
return ResolveEffectiveDisplayMode(app_display_mode, display_mode_overrides,
user_display_mode);
}
DisplayMode WebAppRegistrar::GetEffectiveDisplayModeFromManifest(
const AppId& app_id) const {
std::vector<DisplayMode> display_mode_overrides =
GetAppDisplayModeOverride(app_id);
if (!display_mode_overrides.empty())
return display_mode_overrides[0];
return GetAppDisplayMode(app_id);
}
bool WebAppRegistrar::IsInExperimentalTabbedWindowMode(
const AppId& app_id) const {
return base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip) &&
base::FeatureList::IsEnabled(features::kDesktopPWAsTabStripSettings) &&
GetBoolWebAppPref(profile()->GetPrefs(), app_id,
kExperimentalTabbedWindowMode);
}
bool WebAppRegistrar::IsTabbedWindowModeEnabled(const AppId& app_id) const {
if (!base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip))
return false;
DisplayMode display = GetAppEffectiveDisplayMode(app_id);
return IsInExperimentalTabbedWindowMode(app_id) ||
display == DisplayMode::kTabbed;
}
const WebApp* WebAppRegistrar::GetAppById(const AppId& app_id) const {
if (registry_profile_being_deleted_)
return nullptr;
auto it = registry_.find(app_id);
if (it != registry_.end() && WebAppExposed(*it->second))
return it->second.get();
return nullptr;
}
const WebApp* WebAppRegistrar::GetAppByStartUrl(const GURL& start_url) const {
if (registry_profile_being_deleted_)
return nullptr;
for (auto const& it : registry_) {
if (WebAppExposed(*it.second) && it.second->start_url() == start_url)
return it.second.get();
}
return nullptr;
}
std::vector<AppId> WebAppRegistrar::GetAppsFromSyncAndPendingInstallation() {
AppSet apps_in_sync_install = AppSet(this, [](const WebApp& web_app) {
return web_app.is_from_sync_and_pending_installation();
});
std::vector<AppId> app_ids;
for (const WebApp& app : apps_in_sync_install)
app_ids.push_back(app.app_id());
return app_ids;
}
bool WebAppRegistrar::WasInstalledByDefaultOnly(const AppId& app_id) const {
const WebApp* web_app = GetAppById(app_id);
return web_app && web_app->HasOnlySource(Source::Type::kDefault);
}
void WebAppRegistrar::Start() {
// Profile manager can be null in unit tests.
if (g_browser_process->profile_manager())
g_browser_process->profile_manager()->AddObserver(this);
}
void WebAppRegistrar::Shutdown() {
if (g_browser_process->profile_manager())
g_browser_process->profile_manager()->RemoveObserver(this);
}
bool WebAppRegistrar::IsInstalled(const AppId& app_id) const {
const WebApp* web_app = GetAppById(app_id);
return web_app && !web_app->is_from_sync_and_pending_installation();
}
bool WebAppRegistrar::IsUninstalling(const AppId& app_id) const {
const WebApp* web_app = GetAppById(app_id);
return web_app && web_app->is_uninstalling();
}
bool WebAppRegistrar::IsLocallyInstalled(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->is_locally_installed() : false;
}
bool WebAppRegistrar::WasInstalledByUser(const AppId& app_id) const {
const WebApp* web_app = GetAppById(app_id);
return web_app && web_app->WasInstalledByUser();
}
bool WebAppRegistrar::WasInstalledByOem(const AppId& app_id) const {
const WebApp* web_app = GetAppById(app_id);
return web_app && web_app->chromeos_data().has_value() &&
web_app->chromeos_data()->oem_installed;
}
bool WebAppRegistrar::IsApprovedLaunchProtocol(
const AppId& app_id,
std::string protocol_scheme) const {
const WebApp* web_app = GetAppById(app_id);
return web_app &&
base::Contains(web_app->approved_launch_protocols(), protocol_scheme);
}
int WebAppRegistrar::CountUserInstalledApps() const {
int num_user_installed = 0;
for (const WebApp& app : GetAppsIncludingStubs()) {
if (app.is_locally_installed() && app.WasInstalledByUser())
++num_user_installed;
}
return num_user_installed;
}
std::string WebAppRegistrar::GetAppShortName(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->name() : std::string();
}
std::string WebAppRegistrar::GetAppDescription(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->description() : std::string();
}
absl::optional<SkColor> WebAppRegistrar::GetAppThemeColor(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->theme_color() : absl::nullopt;
}
absl::optional<SkColor> WebAppRegistrar::GetAppBackgroundColor(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->background_color() : absl::nullopt;
}
const GURL& WebAppRegistrar::GetAppStartUrl(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->start_url() : GURL::EmptyGURL();
}
absl::optional<std::string> WebAppRegistrar::GetAppManifestId(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->manifest_id() : absl::nullopt;
}
const std::string* WebAppRegistrar::GetAppLaunchQueryParams(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->launch_query_params() : nullptr;
}
const apps::ShareTarget* WebAppRegistrar::GetAppShareTarget(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return (web_app && web_app->share_target().has_value())
? &web_app->share_target().value()
: nullptr;
}
blink::mojom::CaptureLinks WebAppRegistrar::GetAppCaptureLinks(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->capture_links()
: blink::mojom::CaptureLinks::kUndefined;
}
const apps::FileHandlers* WebAppRegistrar::GetAppFileHandlers(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? &web_app->file_handlers() : nullptr;
}
const apps::ProtocolHandlers* WebAppRegistrar::GetAppProtocolHandlers(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? &web_app->protocol_handlers() : nullptr;
}
bool WebAppRegistrar::IsAppFileHandlerPermissionBlocked(
const web_app::AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->file_handler_permission_blocked() : false;
}
absl::optional<GURL> WebAppRegistrar::GetAppScopeInternal(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
if (!web_app)
return absl::nullopt;
// TODO(crbug.com/910016): Treat shortcuts as PWAs.
// Shortcuts on the WebApp system have empty scopes, while the implementation
// of IsShortcutApp just checks if the scope is |absl::nullopt|, so make sure
// we return |absl::nullopt| rather than an empty scope.
if (web_app->scope().is_empty())
return absl::nullopt;
return web_app->scope();
}
DisplayMode WebAppRegistrar::GetAppDisplayMode(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->display_mode() : DisplayMode::kUndefined;
}
DisplayMode WebAppRegistrar::GetAppUserDisplayMode(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->user_display_mode() : DisplayMode::kUndefined;
}
std::vector<DisplayMode> WebAppRegistrar::GetAppDisplayModeOverride(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->display_mode_override()
: std::vector<DisplayMode>();
}
apps::UrlHandlers WebAppRegistrar::GetAppUrlHandlers(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->url_handlers()
: std::vector<apps::UrlHandlerInfo>();
}
GURL WebAppRegistrar::GetAppManifestUrl(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->manifest_url() : GURL::EmptyGURL();
}
base::Time WebAppRegistrar::GetAppLastBadgingTime(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->last_badging_time() : base::Time();
}
base::Time WebAppRegistrar::GetAppLastLaunchTime(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->last_launch_time() : base::Time();
}
base::Time WebAppRegistrar::GetAppInstallTime(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->install_time() : base::Time();
}
std::vector<WebApplicationIconInfo> WebAppRegistrar::GetAppIconInfos(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->icon_infos()
: std::vector<WebApplicationIconInfo>();
}
SortedSizesPx WebAppRegistrar::GetAppDownloadedIconSizesAny(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->downloaded_icon_sizes(IconPurpose::ANY)
: SortedSizesPx();
}
std::vector<WebApplicationShortcutsMenuItemInfo>
WebAppRegistrar::GetAppShortcutsMenuItemInfos(const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->shortcuts_menu_item_infos()
: std::vector<WebApplicationShortcutsMenuItemInfo>();
}
std::vector<IconSizes> WebAppRegistrar::GetAppDownloadedShortcutsMenuIconsSizes(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->downloaded_shortcuts_menu_icons_sizes()
: std::vector<IconSizes>();
}
std::vector<AppId> WebAppRegistrar::GetAppIds() const {
std::vector<AppId> app_ids;
for (const WebApp& app : GetApps())
app_ids.push_back(app.app_id());
return app_ids;
}
RunOnOsLoginMode WebAppRegistrar::GetAppRunOnOsLoginMode(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->run_on_os_login_mode() : RunOnOsLoginMode::kNotRun;
}
bool WebAppRegistrar::GetWindowControlsOverlayEnabled(
const AppId& app_id) const {
auto* web_app = GetAppById(app_id);
return web_app ? web_app->window_controls_overlay_enabled() : false;
}
void WebAppRegistrar::OnProfileMarkedForPermanentDeletion(
Profile* profile_to_be_deleted) {
if (profile() != profile_to_be_deleted)
return;
for (const auto& app : GetAppsIncludingStubs()) {
NotifyWebAppProfileWillBeDeleted(app.app_id());
os_integration_manager().UninstallAllOsHooks(app.app_id(),
base::DoNothing());
}
// We can't do registry_.clear() here because it makes in-memory registry
// diverged from the sync server registry and from the on-disk registry
// (WebAppDatabase/LevelDB and "Web Applications" profile directory).
registry_profile_being_deleted_ = true;
}
WebAppRegistrar::AppSet::AppSet(const WebAppRegistrar* registrar, Filter filter)
: registrar_(registrar),
filter_(filter)
#if DCHECK_IS_ON()
,
mutations_count_(registrar->mutations_count_)
#endif
{
}
WebAppRegistrar::AppSet::~AppSet() {
#if DCHECK_IS_ON()
DCHECK_EQ(mutations_count_, registrar_->mutations_count_);
#endif
}
WebAppRegistrar::AppSet::iterator WebAppRegistrar::AppSet::begin() {
return iterator(registrar_->registry_.begin(), registrar_->registry_.end(),
filter_);
}
WebAppRegistrar::AppSet::iterator WebAppRegistrar::AppSet::end() {
return iterator(registrar_->registry_.end(), registrar_->registry_.end(),
filter_);
}
WebAppRegistrar::AppSet::const_iterator WebAppRegistrar::AppSet::begin() const {
return const_iterator(registrar_->registry_.begin(),
registrar_->registry_.end(), filter_);
}
WebAppRegistrar::AppSet::const_iterator WebAppRegistrar::AppSet::end() const {
return const_iterator(registrar_->registry_.end(),
registrar_->registry_.end(), filter_);
}
const WebAppRegistrar::AppSet WebAppRegistrar::GetAppsIncludingStubs() const {
return AppSet(this, nullptr);
}
const WebAppRegistrar::AppSet WebAppRegistrar::GetApps() const {
return AppSet(this, [](const WebApp& web_app) {
return WebAppExposed(web_app) &&
!web_app.is_from_sync_and_pending_installation();
});
}
void WebAppRegistrar::SetRegistry(Registry&& registry) {
registry_ = std::move(registry);
}
const WebAppRegistrar::AppSet WebAppRegistrar::FilterApps(Filter filter) const {
return AppSet(this, filter);
}
void WebAppRegistrar::CountMutation() {
#if DCHECK_IS_ON()
++mutations_count_;
#endif
}
WebAppRegistrarMutable::WebAppRegistrarMutable(Profile* profile)
: WebAppRegistrar(profile) {}
WebAppRegistrarMutable::~WebAppRegistrarMutable() = default;
void WebAppRegistrarMutable::InitRegistry(Registry&& registry) {
DCHECK(is_empty());
SetRegistry(std::move(registry));
}
WebApp* WebAppRegistrarMutable::GetAppByIdMutable(const AppId& app_id) {
return const_cast<WebApp*>(GetAppById(app_id));
}
WebAppRegistrar::AppSet WebAppRegistrarMutable::FilterAppsMutable(
Filter filter) {
return AppSet(this, filter);
}
WebAppRegistrar::AppSet WebAppRegistrarMutable::GetAppsIncludingStubsMutable() {
return AppSet(this, nullptr);
}
WebAppRegistrar::AppSet WebAppRegistrarMutable::GetAppsMutable() {
return AppSet(this, [](const WebApp& web_app) {
return WebAppExposed(web_app) &&
!web_app.is_from_sync_and_pending_installation();
});
}
bool IsRegistryEqual(const Registry& registry, const Registry& registry2) {
if (registry.size() != registry2.size())
return false;
for (auto& kv : registry) {
const WebApp* web_app = kv.second.get();
const WebApp* web_app2 = registry2.at(web_app->app_id()).get();
if (*web_app != *web_app2)
return false;
}
return true;
}
} // namespace web_app