blob: 6c044a0bfdb81b99a9d3c5be7f8e4bd996b4ffa2 [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/ui/web_applications/web_app_dialog_utils.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
#include "chrome/browser/web_applications/user_display_mode.h"
#include "chrome/browser/web_applications/web_app_command_manager.h"
#include "chrome/browser/web_applications/web_app_constants.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_install_info.h"
#include "chrome/browser/web_applications/web_app_install_manager.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_provider.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/chrome_features.h"
#include "components/webapps/browser/banners/app_banner_manager.h"
#include "components/webapps/browser/installable/installable_metrics.h"
#include "content/public/browser/navigation_entry.h"
namespace web_app {
namespace {
void OnWebAppInstallShowInstallDialog(
WebAppInstallFlow flow,
webapps::WebappInstallSource install_source,
chrome::PwaInProductHelpState iph_state,
content::WebContents* initiator_web_contents,
std::unique_ptr<WebAppInstallInfo> web_app_info,
WebAppInstallationAcceptanceCallback web_app_acceptance_callback) {
DCHECK(web_app_info);
switch (flow) {
case WebAppInstallFlow::kInstallSite:
web_app_info->user_display_mode = UserDisplayMode::kStandalone;
if (base::FeatureList::IsEnabled(
features::kDesktopPWAsDetailedInstallDialog) &&
webapps::AppBannerManager::FromWebContents(initiator_web_contents)
->screenshots()
.size()) {
chrome::ShowWebAppDetailedInstallDialog(
initiator_web_contents, std::move(web_app_info),
std::move(web_app_acceptance_callback),
webapps::AppBannerManager::FromWebContents(initiator_web_contents)
->screenshots(),
iph_state);
return;
} else {
chrome::ShowPWAInstallBubble(
initiator_web_contents, std::move(web_app_info),
std::move(web_app_acceptance_callback), iph_state);
return;
}
case WebAppInstallFlow::kCreateShortcut:
chrome::ShowWebAppInstallDialog(initiator_web_contents,
std::move(web_app_info),
std::move(web_app_acceptance_callback));
return;
case WebAppInstallFlow::kUnknown:
NOTREACHED();
}
NOTREACHED();
}
WebAppInstalledCallback& GetInstalledCallbackForTesting() {
static base::NoDestructor<WebAppInstalledCallback> instance;
return *instance;
}
void OnWebAppInstalled(WebAppInstalledCallback callback,
const AppId& installed_app_id,
webapps::InstallResultCode code) {
if (GetInstalledCallbackForTesting())
std::move(GetInstalledCallbackForTesting()).Run(installed_app_id, code);
std::move(callback).Run(installed_app_id, code);
}
} // namespace
bool CanCreateWebApp(const Browser* browser) {
// Check whether user is allowed to install web app.
if (!WebAppProvider::GetForWebApps(browser->profile()) ||
!AreWebAppsUserInstallable(browser->profile()))
return false;
// Check whether we're able to install the current page as an app.
content::WebContents* web_contents =
browser->tab_strip_model()->GetActiveWebContents();
if (!IsValidWebAppUrl(web_contents->GetLastCommittedURL()) ||
web_contents->IsCrashed())
return false;
content::NavigationEntry* entry =
web_contents->GetController().GetLastCommittedEntry();
if (entry && entry->GetPageType() == content::PAGE_TYPE_ERROR)
return false;
return true;
}
bool CanPopOutWebApp(Profile* profile) {
return AreWebAppsEnabled(profile) && !profile->IsGuestSession() &&
!profile->IsOffTheRecord();
}
void CreateWebAppFromCurrentWebContents(Browser* browser,
WebAppInstallFlow flow) {
DCHECK(CanCreateWebApp(browser));
content::WebContents* web_contents =
browser->tab_strip_model()->GetActiveWebContents();
auto* provider = WebAppProvider::GetForWebContents(web_contents);
DCHECK(provider);
if (provider->install_manager().IsInstallingForWebContents(web_contents) ||
provider->command_manager().IsInstallingForWebContents(web_contents)) {
return;
}
webapps::WebappInstallSource install_source =
webapps::InstallableMetrics::GetInstallSource(
web_contents, flow == WebAppInstallFlow::kCreateShortcut
? webapps::InstallTrigger::CREATE_SHORTCUT
: webapps::InstallTrigger::MENU);
WebAppInstalledCallback callback = base::DoNothing();
provider->command_manager().ScheduleCommand(
std::make_unique<FetchManifestAndInstallCommand>(
&provider->install_finalizer(), &provider->registrar(),
install_source, web_contents->GetWeakPtr(),
/*bypass_service_worker_check=*/false,
base::BindOnce(OnWebAppInstallShowInstallDialog, flow, install_source,
chrome::PwaInProductHelpState::kNotShown),
base::BindOnce(OnWebAppInstalled, std::move(callback)),
/*use_fallback=*/true, flow));
}
bool CreateWebAppFromManifest(content::WebContents* web_contents,
bool bypass_service_worker_check,
webapps::WebappInstallSource install_source,
WebAppInstalledCallback installed_callback,
chrome::PwaInProductHelpState iph_state) {
auto* provider = WebAppProvider::GetForWebContents(web_contents);
if (!provider)
return false;
provider->command_manager().ScheduleCommand(
std::make_unique<FetchManifestAndInstallCommand>(
&provider->install_finalizer(), &provider->registrar(),
install_source, web_contents->GetWeakPtr(),
bypass_service_worker_check,
base::BindOnce(OnWebAppInstallShowInstallDialog,
WebAppInstallFlow::kInstallSite, install_source,
iph_state),
base::BindOnce(OnWebAppInstalled, std::move(installed_callback))));
return true;
}
void SetInstalledCallbackForTesting(WebAppInstalledCallback callback) {
GetInstalledCallbackForTesting() = std::move(callback);
}
} // namespace web_app