blob: 3bb427f2f469c7528fc1385c478399307125bb72 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/url_identity.h"
#include <optional>
#include <string>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/types/expected.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "components/url_formatter/elide_url.h"
#include "components/url_formatter/url_formatter.h"
#include "extensions/buildflags/buildflags.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "components/webapps/common/web_app_id.h"
#include "extensions/browser/extension_registry.h" // nogncheck
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
using Type = UrlIdentity::Type;
using DefaultFormatOptions = UrlIdentity::DefaultFormatOptions;
using FormatOptions = UrlIdentity::FormatOptions;
namespace {
UrlIdentity CreateDefaultUrlIdentityFromUrl(const GURL& url,
const FormatOptions& options) {
std::u16string name;
if (options.default_options.Has(DefaultFormatOptions::kRawSpec)) {
return UrlIdentity{
.type = Type::kDefault,
.name = base::CollapseWhitespace(base::UTF8ToUTF16(url.spec()), false)};
}
if (options.default_options.Has(
DefaultFormatOptions::kOmitCryptographicScheme)) {
name = url_formatter::FormatUrlForSecurityDisplay(
url, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
} else if (options.default_options.Has(DefaultFormatOptions::kHostname)) {
name = url_formatter::IDNToUnicode(url.host());
} else if (options.default_options.Has(
DefaultFormatOptions::kOmitSchemePathAndTrivialSubdomains)) {
name = url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
url);
} else {
name = url_formatter::FormatUrlForSecurityDisplay(url);
}
return UrlIdentity{.type = Type::kDefault, .name = name};
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
UrlIdentity CreateChromeExtensionIdentityFromUrl(Profile* profile,
const GURL& url,
const FormatOptions& options) {
DCHECK(url.SchemeIs(extensions::kExtensionScheme));
DCHECK(profile) << "Profile cannot be null when type is Chrome Extensions.";
extensions::ExtensionRegistry* extension_registry =
extensions::ExtensionRegistry::Get(profile);
DCHECK(extension_registry);
const extensions::Extension* extension = nullptr;
extension = extension_registry->enabled_extensions().GetByID(url.host());
if (!extension) { // fallback to default
return CreateDefaultUrlIdentityFromUrl(url, options);
}
return UrlIdentity{.type = Type::kChromeExtension,
.name = base::CollapseWhitespace(
base::UTF8ToUTF16(extension->name()), false)};
}
std::optional<webapps::AppId> GetIsolatedWebAppIdFromUrl(const GURL& url) {
base::expected<web_app::IsolatedWebAppUrlInfo, std::string> url_info =
web_app::IsolatedWebAppUrlInfo::Create(url);
return url_info.has_value() ? std::make_optional(url_info.value().app_id())
: std::nullopt;
}
UrlIdentity CreateIsolatedWebAppIdentityFromUrl(Profile* profile,
const GURL& url,
const FormatOptions& options) {
DCHECK(url.SchemeIs(chrome::kIsolatedAppScheme));
DCHECK(profile) << "Profile cannot be null when type is Isolated Web App.";
web_app::WebAppProvider* provider =
web_app::WebAppProvider::GetForWebApps(profile);
DCHECK(provider);
std::optional<webapps::AppId> app_id = GetIsolatedWebAppIdFromUrl(url);
if (!app_id.has_value()) { // fallback to default
return CreateDefaultUrlIdentityFromUrl(url, options);
}
const web_app::WebApp* web_app =
provider->registrar_unsafe().GetAppById(app_id.value());
if (!web_app) { // fallback to default
return CreateDefaultUrlIdentityFromUrl(url, options);
}
return UrlIdentity{
.type = Type::kIsolatedWebApp,
.name = base::CollapseWhitespace(
base::UTF8ToUTF16(
provider->registrar_unsafe().GetAppShortName(app_id.value())),
false)};
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
UrlIdentity CreateFileIdentityFromUrl(Profile* profile,
const GURL& url,
const FormatOptions& options) {
DCHECK(url.SchemeIsFile());
return UrlIdentity{
.type = Type::kFile,
.name = url_formatter::FormatUrlForSecurityDisplay(url),
};
}
} // namespace
UrlIdentity UrlIdentity::CreateFromUrl(Profile* profile,
const GURL& url,
const TypeSet& allowed_types,
const FormatOptions& options) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
if (url.SchemeIs(extensions::kExtensionScheme)) {
DCHECK(allowed_types.Has(Type::kChromeExtension));
return CreateChromeExtensionIdentityFromUrl(profile, url, options);
}
if (url.SchemeIs(chrome::kIsolatedAppScheme)) {
DCHECK(allowed_types.Has(Type::kIsolatedWebApp));
return CreateIsolatedWebAppIdentityFromUrl(profile, url, options);
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
if (url.SchemeIsFile()) {
DCHECK(allowed_types.Has(Type::kFile));
return CreateFileIdentityFromUrl(profile, url, options);
}
DCHECK(allowed_types.Has(Type::kDefault));
return CreateDefaultUrlIdentityFromUrl(url, options);
}