blob: 2bf9c8f9b9678df2c7dd9eb54cbaa46e5f674382 [file] [log] [blame]
// Copyright 2019 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/web_applications/web_app_launch_manager.h"
#include <string>
#include <utility>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/apps/app_service/launch_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/web_applications/web_app_launch_process.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/web_applications/web_app.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_utils.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/render_view_host.h"
#include "extensions/common/constants.h"
#include "third_party/blink/public/common/custom_handlers/protocol_handler_utils.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
namespace web_app {
namespace {
WebAppLaunchManager::OpenApplicationCallback&
GetOpenApplicationCallbackForTesting() {
static base::NoDestructor<WebAppLaunchManager::OpenApplicationCallback>
callback;
return *callback;
}
} // namespace
WebAppLaunchManager::WebAppLaunchManager(Profile* profile)
: profile_(profile),
provider_(WebAppProvider::GetForLocalAppsUnchecked(profile)) {}
WebAppLaunchManager::~WebAppLaunchManager() = default;
content::WebContents* WebAppLaunchManager::OpenApplication(
apps::AppLaunchParams&& params) {
if (GetOpenApplicationCallbackForTesting())
return GetOpenApplicationCallbackForTesting().Run(std::move(params));
WebAppProvider* provider =
WebAppProvider::GetForLocalAppsUnchecked(profile_.get());
DCHECK(provider);
return WebAppLaunchProcess::CreateAndRun(*profile_, provider->registrar(),
provider->os_integration_manager(),
params);
}
void WebAppLaunchManager::LaunchApplication(
const std::string& app_id,
const base::CommandLine& command_line,
const base::FilePath& current_directory,
const absl::optional<GURL>& url_handler_launch_url,
const absl::optional<GURL>& protocol_handler_launch_url,
const absl::optional<GURL>& file_launch_url,
const std::vector<base::FilePath>& launch_files,
base::OnceCallback<void(Browser* browser, apps::LaunchContainer container)>
callback) {
if (!provider_)
return;
// At most one of these parameters should be non-empty.
DCHECK_LE(url_handler_launch_url.has_value() +
protocol_handler_launch_url.has_value() + !launch_files.empty(),
1);
apps::LaunchSource launch_source = apps::LaunchSource::kFromCommandLine;
if (url_handler_launch_url.has_value()) {
launch_source = apps::LaunchSource::kFromUrlHandler;
} else if (!launch_files.empty()) {
DCHECK(file_launch_url.has_value());
launch_source = apps::LaunchSource::kFromFileManager;
}
if (base::FeatureList::IsEnabled(features::kDesktopPWAsRunOnOsLogin) &&
command_line.HasSwitch(switches::kAppRunOnOsLoginMode)) {
launch_source = apps::LaunchSource::kFromOsLogin;
} else if (protocol_handler_launch_url.has_value()) {
launch_source = apps::LaunchSource::kFromProtocolHandler;
}
apps::AppLaunchParams params(
app_id, apps::LaunchContainer::kLaunchContainerWindow,
WindowOpenDisposition::NEW_WINDOW, launch_source);
params.command_line = command_line;
params.current_directory = current_directory;
params.launch_files = launch_files;
params.url_handler_launch_url = url_handler_launch_url;
params.protocol_handler_launch_url = protocol_handler_launch_url;
if (file_launch_url) {
params.override_url = *file_launch_url;
} else {
params.override_url = GURL(command_line.GetSwitchValueASCII(
switches::kAppLaunchUrlForShortcutsMenuItem));
}
// Wait for the web applications database to load.
// If the profile and WebAppLaunchManager are destroyed,
// on_registry_ready will not fire.
provider_->on_registry_ready().Post(
FROM_HERE, base::BindOnce(&WebAppLaunchManager::LaunchWebApplication,
weak_ptr_factory_.GetWeakPtr(),
std::move(params), std::move(callback)));
}
// static
void WebAppLaunchManager::SetOpenApplicationCallbackForTesting(
OpenApplicationCallback callback) {
GetOpenApplicationCallbackForTesting() = std::move(callback);
}
void WebAppLaunchManager::LaunchWebApplication(
apps::AppLaunchParams&& params,
base::OnceCallback<void(Browser* browser, apps::LaunchContainer container)>
callback) {
apps::LaunchContainer container;
Browser* browser = nullptr;
if (provider_->registrar().IsInstalled(params.app_id)) {
if (provider_->registrar().GetAppEffectiveDisplayMode(params.app_id) ==
blink::mojom::DisplayMode::kBrowser) {
params.container = apps::LaunchContainer::kLaunchContainerTab;
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
}
container = params.container;
const content::WebContents* web_contents =
OpenApplication(std::move(params));
if (web_contents)
browser = chrome::FindBrowserWithWebContents(web_contents);
} else {
// Open an empty browser window as the app_id is invalid.
container = apps::LaunchContainer::kLaunchContainerNone;
browser = apps::CreateBrowserWithNewTabPage(profile_);
}
std::move(callback).Run(browser, container);
}
} // namespace web_app