blob: 9a493716a863788b6a6a85f2c1948a24c988e253 [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_provider.h"
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h"
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h"
#include "chrome/browser/web_applications/extensions/web_app_extension_ids_map.h"
#include "chrome/browser/web_applications/external_web_apps.h"
#include "chrome/browser/web_applications/file_utils_wrapper.h"
#include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
#include "chrome/browser/web_applications/system_web_app_manager.h"
#include "chrome/browser/web_applications/web_app_database.h"
#include "chrome/browser/web_applications/web_app_database_factory.h"
#include "chrome/browser/web_applications/web_app_icon_manager.h"
#include "chrome/browser/web_applications/web_app_install_finalizer.h"
#include "chrome/browser/web_applications/web_app_install_manager.h"
#include "chrome/browser/web_applications/web_app_provider_factory.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/chrome_features.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
namespace web_app {
// static
WebAppProvider* WebAppProvider::Get(Profile* profile) {
return WebAppProviderFactory::GetForProfile(profile);
}
// static
WebAppProvider* WebAppProvider::GetForWebContents(
content::WebContents* web_contents) {
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
DCHECK(profile);
return WebAppProvider::Get(profile);
}
WebAppProvider::WebAppProvider(Profile* profile) {
if (base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions))
CreateWebAppsSubsystems(profile);
else
CreateBookmarkAppsSubsystems(profile);
}
WebAppProvider::~WebAppProvider() = default;
void WebAppProvider::CreateWebAppsSubsystems(Profile* profile) {
if (!AllowWebAppInstallation(profile))
return;
database_factory_ = std::make_unique<WebAppDatabaseFactory>(profile);
database_ = std::make_unique<WebAppDatabase>(database_factory_.get());
registrar_ = std::make_unique<WebAppRegistrar>(database_.get());
icon_manager_ = std::make_unique<WebAppIconManager>(
profile, std::make_unique<FileUtilsWrapper>());
auto install_finalizer = std::make_unique<WebAppInstallFinalizer>(
registrar_.get(), icon_manager_.get());
install_manager_ = std::make_unique<WebAppInstallManager>(
profile, std::move(install_finalizer));
registrar_->Init(base::DoNothing());
}
void WebAppProvider::CreateBookmarkAppsSubsystems(Profile* profile) {
install_manager_ = std::make_unique<extensions::BookmarkAppInstallManager>();
pending_app_manager_ =
std::make_unique<extensions::PendingBookmarkAppManager>(profile);
if (WebAppPolicyManager::ShouldEnableForProfile(profile)) {
web_app_policy_manager_ = std::make_unique<WebAppPolicyManager>(
profile, pending_app_manager_.get());
}
system_web_app_manager_ = std::make_unique<SystemWebAppManager>(
profile, pending_app_manager_.get());
notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
content::Source<Profile>(profile));
web_app::ScanForExternalWebApps(
profile, base::BindOnce(&WebAppProvider::OnScanForExternalWebApps,
weak_ptr_factory_.GetWeakPtr()));
}
// static
void WebAppProvider::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
ExtensionIdsMap::RegisterProfilePrefs(registry);
WebAppPolicyManager::RegisterProfilePrefs(registry);
}
// static
bool WebAppProvider::CanInstallWebApp(content::WebContents* web_contents) {
auto* provider = WebAppProvider::GetForWebContents(web_contents);
if (!provider || !provider->install_manager_)
return false;
return provider->install_manager_->CanInstallWebApp(web_contents);
}
// static
void WebAppProvider::InstallWebApp(content::WebContents* web_contents,
bool force_shortcut_app) {
auto* provider = WebAppProvider::GetForWebContents(web_contents);
if (!provider || !provider->install_manager_)
return;
provider->install_manager_->InstallWebApp(web_contents, force_shortcut_app,
base::DoNothing());
}
void WebAppProvider::Reset() {
// TODO(loyso): Make it independent to the order of destruction via using two
// end-to-end passes:
// 1) Do Reset() for each subsystem to nullify pointers (detach subsystems).
// 2) Destroy subsystems.
// PendingAppManager is used by WebAppPolicyManager and therefore should be
// deleted after it.
web_app_policy_manager_.reset();
system_web_app_manager_.reset();
pending_app_manager_.reset();
install_manager_.reset();
icon_manager_.reset();
registrar_.reset();
database_.reset();
database_factory_.reset();
}
void WebAppProvider::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& detals) {
DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
// KeyedService::Shutdown() gets called when the profile is being destroyed,
// but after DCHECK'ing that no RenderProcessHosts are being leaked. The
// "chrome::NOTIFICATION_PROFILE_DESTROYED" notification gets sent before the
// DCHECK so we use that to clean up RenderProcessHosts instead.
Reset();
}
void WebAppProvider::OnScanForExternalWebApps(
std::vector<web_app::PendingAppManager::AppInfo> app_infos) {
pending_app_manager_->SynchronizeInstalledApps(
std::move(app_infos), InstallSource::kExternalDefault);
}
} // namespace web_app