blob: 537e78abbd0eeba9228a370cd90b988081b5af85 [file] [log] [blame]
// Copyright 2019 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/extensions/bookmark_app_registrar.h"
#include <utility>
#include "base/one_shot_event.h"
#include "chrome/browser/extensions/convert_web_app.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/launch_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/components/app_registrar_observer.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h"
#include "chrome/common/extensions/manifest_handlers/app_display_mode_info.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/extensions/manifest_handlers/app_theme_color_info.h"
#include "chrome/common/extensions/manifest_handlers/linked_app_icons.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/unloaded_extension_reason.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/web_app_linked_shortcut_items.h"
#include "url/gurl.h"
using web_app::DisplayMode;
namespace extensions {
namespace {
// These need to match the keys in
// chrome/browser/extensions/chrome_app_sorting.cc
const char kPrefAppLaunchOrdinal[] = "app_launcher_ordinal";
const char kPrefPageOrdinal[] = "page_ordinal";
} // namespace
BookmarkAppRegistrar::BookmarkAppRegistrar(Profile* profile)
: AppRegistrar(profile) {
}
BookmarkAppRegistrar::~BookmarkAppRegistrar() = default;
void BookmarkAppRegistrar::Start() {
extension_observer_.Add(ExtensionRegistry::Get(profile()));
}
bool BookmarkAppRegistrar::IsInstalled(const web_app::AppId& app_id) const {
const Extension* extension = GetEnabledExtension(app_id);
return extension && extension->from_bookmark();
}
bool BookmarkAppRegistrar::IsLocallyInstalled(
const web_app::AppId& app_id) const {
const Extension* extension = GetEnabledExtension(app_id);
return extension && extension->from_bookmark() &&
BookmarkAppIsLocallyInstalled(profile(), extension);
}
bool BookmarkAppRegistrar::WasInstalledByUser(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension && !extension->was_installed_by_default();
}
int BookmarkAppRegistrar::CountUserInstalledApps() const {
return CountUserInstalledBookmarkApps(profile());
}
void BookmarkAppRegistrar::OnExtensionUninstalled(
content::BrowserContext* browser_context,
const Extension* extension,
UninstallReason reason) {
DCHECK_EQ(browser_context, profile());
if (extension->from_bookmark()) {
DCHECK(!bookmark_app_being_observed_);
bookmark_app_being_observed_ = extension;
NotifyWebAppUninstalled(extension->id());
bookmark_app_being_observed_ = nullptr;
}
}
void BookmarkAppRegistrar::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) {
DCHECK_EQ(browser_context, profile());
if (!extension->from_bookmark())
return;
DCHECK(!bookmark_app_being_observed_);
bookmark_app_being_observed_ = extension;
// If a profile is removed, notify the web app that it is uninstalled, so it
// can cleanup any state outside the profile dir (e.g., registry settings).
if (reason == UnloadedExtensionReason::PROFILE_SHUTDOWN)
NotifyWebAppProfileWillBeDeleted(extension->id());
bookmark_app_being_observed_ = nullptr;
}
void BookmarkAppRegistrar::OnShutdown(ExtensionRegistry* registry) {
NotifyAppRegistrarShutdown();
extension_observer_.RemoveAll();
}
std::string BookmarkAppRegistrar::GetAppShortName(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension ? extension->short_name() : std::string();
}
std::string BookmarkAppRegistrar::GetAppDescription(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension ? extension->description() : std::string();
}
base::Optional<SkColor> BookmarkAppRegistrar::GetAppThemeColor(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
if (!extension)
return base::nullopt;
return AppThemeColorInfo::GetThemeColor(extension);
}
const GURL& BookmarkAppRegistrar::GetAppLaunchURL(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension ? AppLaunchInfo::GetLaunchWebURL(extension)
: GURL::EmptyGURL();
}
base::Optional<GURL> BookmarkAppRegistrar::GetAppScopeInternal(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
if (!extension)
return base::nullopt;
GURL scope_url = GetScopeURLFromBookmarkApp(GetBookmarkAppDchecked(app_id));
if (scope_url.is_valid())
return scope_url;
return base::nullopt;
}
DisplayMode BookmarkAppRegistrar::GetAppDisplayMode(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
if (!extension)
return DisplayMode::kUndefined;
return AppDisplayModeInfo::GetDisplayMode(extension);
}
DisplayMode BookmarkAppRegistrar::GetAppUserDisplayMode(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
if (!extension)
return DisplayMode::kStandalone;
switch (extensions::GetLaunchContainer(
extensions::ExtensionPrefs::Get(profile()), extension)) {
case LaunchContainer::kLaunchContainerWindow:
case LaunchContainer::kLaunchContainerPanelDeprecated:
return DisplayMode::kStandalone;
case LaunchContainer::kLaunchContainerTab:
return DisplayMode::kBrowser;
case LaunchContainer::kLaunchContainerNone:
NOTREACHED();
return DisplayMode::kUndefined;
}
}
base::Time BookmarkAppRegistrar::GetAppLastLaunchTime(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension
? extensions::ExtensionPrefs::Get(profile())->GetLastLaunchTime(
extension->id())
: base::Time();
}
base::Time BookmarkAppRegistrar::GetAppInstallTime(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension ? extensions::ExtensionPrefs::Get(profile())->GetInstallTime(
extension->id())
: base::Time();
}
std::vector<WebApplicationIconInfo> BookmarkAppRegistrar::GetAppIconInfos(
const web_app::AppId& app_id) const {
std::vector<WebApplicationIconInfo> result;
const Extension* extension = GetBookmarkAppDchecked(app_id);
if (!extension)
return result;
for (const LinkedAppIcons::IconInfo& icon_info :
LinkedAppIcons::GetLinkedAppIcons(extension).icons) {
WebApplicationIconInfo web_app_icon_info;
web_app_icon_info.url = icon_info.url;
if (icon_info.size != LinkedAppIcons::kAnySize)
web_app_icon_info.square_size_px = icon_info.size;
result.push_back(std::move(web_app_icon_info));
}
return result;
}
std::vector<SquareSizePx> BookmarkAppRegistrar::GetAppDownloadedIconSizes(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension ? GetBookmarkAppDownloadedIconSizes(extension)
: std::vector<SquareSizePx>();
}
std::vector<WebApplicationShortcutsMenuItemInfo>
BookmarkAppRegistrar::GetAppShortcutInfos(const web_app::AppId& app_id) const {
std::vector<WebApplicationShortcutsMenuItemInfo> result;
const Extension* extension = GetBookmarkAppDchecked(app_id);
if (!extension)
return result;
const WebAppLinkedShortcutItems& linked_shortcut_items =
WebAppLinkedShortcutItems::GetWebAppLinkedShortcutItems(extension);
result.reserve(linked_shortcut_items.shortcut_item_infos.size());
for (const WebAppLinkedShortcutItems::ShortcutItemInfo& linked_item_info :
linked_shortcut_items.shortcut_item_infos) {
WebApplicationShortcutsMenuItemInfo shortcut_item_info;
shortcut_item_info.name = linked_item_info.name;
shortcut_item_info.url = linked_item_info.url;
shortcut_item_info.shortcut_icon_infos.reserve(
linked_item_info.shortcut_item_icon_infos.size());
for (const WebAppLinkedShortcutItems::ShortcutItemInfo::IconInfo&
shortcut_item_icon_info :
linked_item_info.shortcut_item_icon_infos) {
WebApplicationShortcutsMenuItemInfo::Icon shortcut_icon_info;
shortcut_icon_info.square_size_px = shortcut_item_icon_info.size;
shortcut_icon_info.url = shortcut_item_icon_info.url;
shortcut_item_info.shortcut_icon_infos.emplace_back(
std::move(shortcut_icon_info));
}
result.emplace_back(std::move(shortcut_item_info));
}
return result;
}
std::vector<std::vector<SquareSizePx>>
BookmarkAppRegistrar::GetAppDownloadedShortcutsMenuIconsSizes(
const web_app::AppId& app_id) const {
const Extension* extension = GetBookmarkAppDchecked(app_id);
return extension ? GetBookmarkAppDownloadedShortcutsMenuIconsSizes(extension)
: std::vector<std::vector<SquareSizePx>>();
}
std::vector<web_app::AppId> BookmarkAppRegistrar::GetAppIds() const {
std::vector<web_app::AppId> app_ids;
for (scoped_refptr<const Extension> app :
ExtensionRegistry::Get(profile())->enabled_extensions()) {
if (app->from_bookmark()) {
app_ids.push_back(app->id());
}
}
return app_ids;
}
web_app::WebAppRegistrar* BookmarkAppRegistrar::AsWebAppRegistrar() {
return nullptr;
}
BookmarkAppRegistrar* BookmarkAppRegistrar::AsBookmarkAppRegistrar() {
return this;
}
syncer::StringOrdinal BookmarkAppRegistrar::GetUserPageOrdinal(
const web_app::AppId& app_id) const {
std::string page_ordinal_raw_data;
// If the preference read fails then raw_data will still be unset and we
// will return an invalid StringOrdinal to signal that no page ordinal was
// found.
extensions::ExtensionPrefs::Get(profile())->ReadPrefAsString(
app_id, kPrefPageOrdinal, &page_ordinal_raw_data);
return syncer::StringOrdinal(page_ordinal_raw_data);
}
syncer::StringOrdinal BookmarkAppRegistrar::GetUserLaunchOrdinal(
const web_app::AppId& app_id) const {
std::string launch_ordinal_raw_data;
// If the preference read fails then raw_data will still be unset and we
// will return an invalid StringOrdinal to signal that no page ordinal was
// found.
extensions::ExtensionPrefs::Get(profile())->ReadPrefAsString(
app_id, kPrefAppLaunchOrdinal, &launch_ordinal_raw_data);
return syncer::StringOrdinal(launch_ordinal_raw_data);
}
const Extension* BookmarkAppRegistrar::FindExtension(
const web_app::AppId& app_id) const {
if (bookmark_app_being_observed_ &&
bookmark_app_being_observed_->id() == app_id) {
return bookmark_app_being_observed_;
}
return ExtensionRegistry::Get(profile())->GetInstalledExtension(app_id);
}
const Extension* BookmarkAppRegistrar::GetBookmarkAppDchecked(
const web_app::AppId& app_id) const {
const Extension* extension = GetEnabledExtension(app_id);
DCHECK(!extension || extension->from_bookmark());
return extension;
}
const Extension* BookmarkAppRegistrar::GetEnabledExtension(
const web_app::AppId& app_id) const {
return ExtensionRegistry::Get(profile())->enabled_extensions().GetByID(
app_id);
}
} // namespace extensions