#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
#include <memory>
#include <utility>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/to_string.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/commands/web_app_command.h"
#include "chrome/browser/web_applications/install_bounce_metric.h"
#include "chrome/browser/web_applications/locks/app_lock.h"
#include "chrome/browser/web_applications/locks/noop_lock.h"
#include "chrome/browser/web_applications/locks/web_app_lock_manager.h"
#include "chrome/browser/web_applications/proto/web_app_install_state.pb.h"
#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
#include "chrome/browser/web_applications/web_app_command_manager.h"
#include "chrome/browser/web_applications/web_app_command_scheduler.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_icon_operations.h"
#include "chrome/browser/web_applications/web_app_install_info.h"
#include "chrome/browser/web_applications/web_app_install_params.h"
#include "chrome/browser/web_applications/web_app_install_utils.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
#include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
#include "chrome/common/chrome_features.h"
#include "components/webapps/browser/features.h"
#include "components/webapps/browser/install_result_code.h"
#include "components/webapps/browser/installable/installable_evaluator.h"
#include "components/webapps/browser/installable/installable_logging.h"
#include "components/webapps/browser/installable/installable_metrics.h"
#include "components/webapps/browser/installable/installable_params.h"
#include "components/webapps/common/web_app_id.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/visibility.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "url/origin.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/mojom/app.mojom.h"
#include "ash/components/arc/mojom/intent_helper.mojom.h"
#include "ash/components/arc/session/arc_bridge_service.h"
#include "ash/components/arc/session/arc_service_manager.h"
#include "base/strings/string_util.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "base/strings/utf_string_conversions.h"
#include "net/base/url_util.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/arc.mojom.h"
#include "chromeos/crosapi/mojom/web_app_service.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#include "chromeos/startup/browser_params_proxy.h"
#endif
namespace web_app {
namespace {
#if BUILDFLAG(IS_CHROMEOS_ASH)
constexpr bool kAddAppsToQuickLaunchBarByDefault = false;
#else
constexpr bool kAddAppsToQuickLaunchBarByDefault = …;
#endif
#if BUILDFLAG(IS_CHROMEOS)
const char kChromeOsPlayPlatform[] = "chromeos_play";
const char kPlayIntentPrefix[] =
"https://play.google.com/store/apps/details?id=";
const char kPlayStorePackage[] = "com.android.vending";
struct PlayStoreIntent {
std::string app_id;
std::string intent;
};
std::optional<PlayStoreIntent> GetPlayStoreIntentFromManifest(
const blink::mojom::Manifest& manifest) {
for (const auto& app : manifest.related_applications) {
std::string id = base::UTF16ToUTF8(app.id.value_or(std::u16string()));
if (!base::EqualsASCII(app.platform.value_or(std::u16string()),
kChromeOsPlayPlatform)) {
continue;
}
if (id.empty()) {
if (!net::GetValueForKeyInQuery(app.url, "id", &id) || id.empty()) {
continue;
}
}
std::string referrer;
if (net::GetValueForKeyInQuery(app.url, "referrer", &referrer) &&
!referrer.empty()) {
referrer = "&referrer=" + referrer;
}
std::string intent = kPlayIntentPrefix + id + referrer;
return PlayStoreIntent{id, intent};
}
return std::nullopt;
}
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
bool ShouldInteractWithArc() {
auto* lacros_service = chromeos::LacrosService::Get();
return lacros_service &&
lacros_service->IsAvailable<crosapi::mojom::WebAppService>();
}
mojo::Remote<crosapi::mojom::Arc>* GetArcRemoteWithMinVersion(
uint32_t minVersion) {
auto* lacros_service = chromeos::LacrosService::Get();
if (lacros_service && lacros_service->IsAvailable<crosapi::mojom::Arc>() &&
lacros_service->GetInterfaceVersion<crosapi::mojom::Arc>() >=
static_cast<int>(minVersion)) {
return &lacros_service->GetRemote<crosapi::mojom::Arc>();
}
return nullptr;
}
#endif
void LogInstallInfo(base::Value::Dict& dict,
const WebAppInstallInfo& install_info) { … }
bool IsShortcutCreated(WebAppRegistrar& registrar,
const webapps::AppId& app_id) { … }
}
FetchManifestAndInstallCommand::FetchManifestAndInstallCommand(
webapps::WebappInstallSource install_surface,
base::WeakPtr<content::WebContents> contents,
WebAppInstallDialogCallback dialog_callback,
OnceInstallCallback callback,
FallbackBehavior fallback_behavior,
base::WeakPtr<WebAppUiManager> ui_manager)
: … { … }
FetchManifestAndInstallCommand::~FetchManifestAndInstallCommand() = default;
void FetchManifestAndInstallCommand::OnShutdown(
base::PassKey<WebAppCommandManager>) const { … }
content::WebContents* FetchManifestAndInstallCommand::GetInstallingWebContents(
base::PassKey<WebAppCommandManager>) { … }
void FetchManifestAndInstallCommand::StartWithLock(
std::unique_ptr<NoopLock> lock) { … }
void FetchManifestAndInstallCommand::DidFinishNavigation(
content::NavigationHandle* navigation_handle) { … }
void FetchManifestAndInstallCommand::OnVisibilityChanged(
content::Visibility visibility) { … }
void FetchManifestAndInstallCommand::WebContentsDestroyed() { … }
void FetchManifestAndInstallCommand::Abort(webapps::InstallResultCode code,
const base::Location& location) { … }
bool FetchManifestAndInstallCommand::IsWebContentsDestroyed() { … }
void FetchManifestAndInstallCommand::OnGetWebAppInstallInfo(
std::unique_ptr<WebAppInstallInfo> fallback_web_app_info) { … }
void FetchManifestAndInstallCommand::FetchManifest() { … }
void FetchManifestAndInstallCommand::OnDidPerformInstallableCheck(
blink::mojom::ManifestPtr opt_manifest,
bool valid_manifest_for_web_app,
webapps::InstallableStatusCode error_code) { … }
void FetchManifestAndInstallCommand::CheckForPlayStoreIntentOrGetIcons(
std::unique_ptr<AppLock> app_lock) { … }
void FetchManifestAndInstallCommand::OnDidCheckForIntentToPlayStore(
const std::string& intent,
bool should_intent_to_store) { … }
#if BUILDFLAG(IS_CHROMEOS_LACROS)
void FetchManifestAndInstallCommand::OnDidCheckForIntentToPlayStoreLacros(
const std::string& intent,
crosapi::mojom::IsInstallableResult result) {
OnDidCheckForIntentToPlayStore(
intent, result == crosapi::mojom::IsInstallableResult::kInstallable);
}
#endif
void FetchManifestAndInstallCommand::OnIconsRetrievedShowDialog(
IconsDownloadedResult result,
IconsMap icons_map,
DownloadedIconsHttpResults icons_http_results) { … }
void FetchManifestAndInstallCommand::OnDialogCompleted(
bool user_accepted,
std::unique_ptr<WebAppInstallInfo> web_app_info) { … }
void FetchManifestAndInstallCommand::OnInstallFinalizedMaybeReparentTab(
const webapps::AppId& app_id,
webapps::InstallResultCode code) { … }
void FetchManifestAndInstallCommand::OnInstallCompleted(
const webapps::AppId& app_id,
webapps::InstallResultCode code) { … }
void FetchManifestAndInstallCommand::MeasureUserInstalledAppHistogram(
webapps::InstallResultCode code) { … }
}