Commit 89baca17 authored by Alexey Baskakov's avatar Alexey Baskakov Committed by Commit Bot

WebApp: Extract WebAppInstallTask from WebAppInstallManager.

Allow concurrent installs.
WebAppInstallManager owns all install tasks.

This CL introduces no behavior changes.

Bug: 901226
Change-Id: Ib231faeb7b3749f3f68436ac01d872075c4e6cb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1556659Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Commit-Queue: Alexey Baskakov <loyso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#649322}
parent f5163337
...@@ -27,6 +27,8 @@ source_set("web_applications") { ...@@ -27,6 +27,8 @@ source_set("web_applications") {
"web_app_install_finalizer.h", "web_app_install_finalizer.h",
"web_app_install_manager.cc", "web_app_install_manager.cc",
"web_app_install_manager.h", "web_app_install_manager.h",
"web_app_install_task.cc",
"web_app_install_task.h",
"web_app_registrar.cc", "web_app_registrar.cc",
"web_app_registrar.h", "web_app_registrar.h",
"web_app_tab_helper.cc", "web_app_tab_helper.cc",
...@@ -89,7 +91,7 @@ source_set("web_applications_unit_tests") { ...@@ -89,7 +91,7 @@ source_set("web_applications_unit_tests") {
sources = [ sources = [
"web_app_database_unittest.cc", "web_app_database_unittest.cc",
"web_app_icon_manager_unittest.cc", "web_app_icon_manager_unittest.cc",
"web_app_install_manager_unittest.cc", "web_app_install_task_unittest.cc",
"web_app_registrar_unittest.cc", "web_app_registrar_unittest.cc",
"web_app_utils_unittest.cc", "web_app_utils_unittest.cc",
] ]
......
...@@ -8,26 +8,18 @@ ...@@ -8,26 +8,18 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/logging.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/components/install_finalizer.h"
#include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_data_retriever.h" #include "chrome/browser/web_applications/web_app_install_task.h"
#include "chrome/browser/web_applications/components/web_app_icon_generator.h"
#include "chrome/browser/web_applications/components/web_app_install_utils.h"
#include "chrome/browser/web_applications/web_app_utils.h" #include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/web_application_info.h" #include "chrome/common/web_application_info.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "third_party/blink/public/common/manifest/manifest.h"
namespace web_app { namespace web_app {
WebAppInstallManager::WebAppInstallManager(Profile* profile, WebAppInstallManager::WebAppInstallManager(Profile* profile,
InstallFinalizer* install_finalizer) InstallFinalizer* install_finalizer)
: data_retriever_(std::make_unique<WebAppDataRetriever>()), : install_finalizer_(install_finalizer), profile_(profile) {}
install_finalizer_(install_finalizer),
profile_(profile) {}
WebAppInstallManager::~WebAppInstallManager() = default; WebAppInstallManager::~WebAppInstallManager() = default;
...@@ -45,23 +37,16 @@ void WebAppInstallManager::InstallWebApp( ...@@ -45,23 +37,16 @@ void WebAppInstallManager::InstallWebApp(
bool force_shortcut_app, bool force_shortcut_app,
WebappInstallSource install_source, WebappInstallSource install_source,
WebAppInstallDialogCallback dialog_callback, WebAppInstallDialogCallback dialog_callback,
OnceInstallCallback install_callback) { OnceInstallCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(AreWebAppsUserInstallable(profile_)); DCHECK(AreWebAppsUserInstallable(profile_));
// Concurrent calls are not allowed. auto task = std::make_unique<WebAppInstallTask>(profile_, install_finalizer_);
DCHECK(!web_contents()); task->InstallWebApp(
CHECK(!install_callback_); contents, force_shortcut_app, install_source, std::move(dialog_callback),
base::BindOnce(&WebAppInstallManager::OnTaskCompleted,
Observe(contents); base::Unretained(this), task.get(), std::move(callback)));
dialog_callback_ = std::move(dialog_callback);
install_callback_ = std::move(install_callback);
install_source_ = install_source;
data_retriever_->GetWebApplicationInfo( tasks_.insert(std::move(task));
web_contents(),
base::BindOnce(&WebAppInstallManager::OnGetWebApplicationInfo,
weak_ptr_factory_.GetWeakPtr(), force_shortcut_app));
} }
void WebAppInstallManager::InstallWebAppFromBanner( void WebAppInstallManager::InstallWebAppFromBanner(
...@@ -105,194 +90,14 @@ void WebAppInstallManager::InstallWebAppForTesting( ...@@ -105,194 +90,14 @@ void WebAppInstallManager::InstallWebAppForTesting(
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
void WebAppInstallManager::WebContentsDestroyed() { void WebAppInstallManager::OnTaskCompleted(WebAppInstallTask* task,
ReturnError(InstallResultCode::kWebContentsDestroyed); OnceInstallCallback callback,
} const AppId& app_id,
InstallResultCode code) {
void WebAppInstallManager::SetDataRetrieverForTesting( DCHECK(tasks_.contains(task));
std::unique_ptr<WebAppDataRetriever> data_retriever) { tasks_.erase(task);
data_retriever_ = std::move(data_retriever);
}
void WebAppInstallManager::SetInstallFinalizerForTesting(
InstallFinalizer* install_finalizer) {
install_finalizer_ = install_finalizer;
}
void WebAppInstallManager::CallInstallCallback(const AppId& app_id,
InstallResultCode code) {
Observe(nullptr);
dialog_callback_.Reset();
DCHECK(install_source_ != kNoInstallSource);
install_source_ = kNoInstallSource;
DCHECK(install_callback_);
std::move(install_callback_).Run(app_id, code);
}
void WebAppInstallManager::ReturnError(InstallResultCode code) {
CallInstallCallback(AppId(), code);
}
bool WebAppInstallManager::InstallInterrupted() const {
// Interrupt early if WebContents is being destroyed.
// WebContentsDestroyed will get called eventually and the callback will be
// invoked at that point.
if (!web_contents() || web_contents()->IsBeingDestroyed())
return true;
return false;
}
void WebAppInstallManager::OnGetWebApplicationInfo(
bool force_shortcut_app,
std::unique_ptr<WebApplicationInfo> web_app_info) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (InstallInterrupted())
return;
if (!web_app_info)
return ReturnError(InstallResultCode::kGetWebApplicationInfoFailed);
data_retriever_->CheckInstallabilityAndRetrieveManifest(
web_contents(),
base::BindOnce(&WebAppInstallManager::OnDidPerformInstallableCheck,
weak_ptr_factory_.GetWeakPtr(), std::move(web_app_info),
force_shortcut_app));
}
void WebAppInstallManager::OnDidPerformInstallableCheck(
std::unique_ptr<WebApplicationInfo> web_app_info,
bool force_shortcut_app,
const blink::Manifest& manifest,
bool is_installable) {
if (InstallInterrupted())
return;
DCHECK(web_app_info);
const ForInstallableSite for_installable_site =
is_installable && !force_shortcut_app ? ForInstallableSite::kYes
: ForInstallableSite::kNo;
// TODO(loyso): Implement UpdateShareTargetInPrefs installation logic.
UpdateWebAppInfoFromManifest(manifest, web_app_info.get(),
for_installable_site);
std::vector<GURL> icon_urls;
for (auto& icon_info : web_app_info->icons) {
if (icon_info.url.is_valid())
icon_urls.push_back(icon_info.url);
}
// If the manifest specified icons, don't use the page icons.
const bool skip_page_fav_icons = !manifest.icons.empty();
data_retriever_->GetIcons(
web_contents(), icon_urls, skip_page_fav_icons,
base::BindOnce(&WebAppInstallManager::OnIconsRetrieved,
weak_ptr_factory_.GetWeakPtr(), std::move(web_app_info),
for_installable_site));
}
void WebAppInstallManager::OnIconsRetrieved(
std::unique_ptr<WebApplicationInfo> web_app_info,
ForInstallableSite for_installable_site,
IconsMap icons_map) {
if (InstallInterrupted())
return;
DCHECK(web_app_info);
std::vector<BitmapAndSource> downloaded_icons =
FilterSquareIcons(icons_map, *web_app_info);
ResizeDownloadedIconsGenerateMissing(std::move(downloaded_icons),
web_app_info.get());
std::move(dialog_callback_)
.Run(
web_contents(), std::move(web_app_info), for_installable_site,
base::BindOnce(&WebAppInstallManager::OnDialogCompleted,
weak_ptr_factory_.GetWeakPtr(), for_installable_site));
}
void WebAppInstallManager::OnDialogCompleted(
ForInstallableSite for_installable_site,
bool user_accepted,
std::unique_ptr<WebApplicationInfo> web_app_info) {
if (InstallInterrupted())
return;
if (!user_accepted)
return ReturnError(InstallResultCode::kUserInstallDeclined);
WebApplicationInfo web_app_info_copy = *web_app_info;
DCHECK(install_source_ != kNoInstallSource);
// This metric is recorded regardless of the installation result.
if (InstallableMetrics::IsReportableInstallSource(install_source_) &&
for_installable_site == ForInstallableSite::kYes) {
InstallableMetrics::TrackInstallEvent(install_source_);
}
install_finalizer_->FinalizeInstall(
web_app_info_copy,
base::BindOnce(&WebAppInstallManager::OnInstallFinalized,
weak_ptr_factory_.GetWeakPtr(), std::move(web_app_info)));
// Check that the finalizer hasn't called OnInstallFinalized synchronously:
DCHECK(install_callback_);
}
void WebAppInstallManager::OnInstallFinalized(
std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
InstallResultCode code) {
if (InstallInterrupted())
return;
if (code != InstallResultCode::kSuccess) {
CallInstallCallback(app_id, code);
return;
}
RecordAppBanner(web_contents(), web_app_info->app_url);
// TODO(loyso): Implement |create_shortcuts| to skip OS shortcuts creation.
auto create_shortcuts_callback = base::BindOnce(
&WebAppInstallManager::OnShortcutsCreated, weak_ptr_factory_.GetWeakPtr(),
std::move(web_app_info), app_id);
if (install_finalizer_->CanCreateOsShortcuts()) {
install_finalizer_->CreateOsShortcuts(app_id,
std::move(create_shortcuts_callback));
} else {
std::move(create_shortcuts_callback).Run(false /* created_shortcuts */);
}
}
void WebAppInstallManager::OnShortcutsCreated(
std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
bool shortcut_created) {
if (InstallInterrupted())
return;
if (install_finalizer_->CanPinAppToShelf())
install_finalizer_->PinAppToShelf(app_id);
// TODO(loyso): Implement |reparent_tab| to skip tab reparenting logic.
if (web_app_info->open_as_window &&
install_finalizer_->CanReparentTab(app_id, shortcut_created)) {
install_finalizer_->ReparentTab(app_id, web_contents());
}
if (install_finalizer_->CanRevealAppShim())
install_finalizer_->RevealAppShim(app_id);
CallInstallCallback(app_id, InstallResultCode::kSuccess); std::move(callback).Run(app_id, code);
} }
} // namespace web_app } // namespace web_app
...@@ -7,31 +7,21 @@ ...@@ -7,31 +7,21 @@
#include <memory> #include <memory>
#include "base/callback.h" #include "base/containers/flat_set.h"
#include "base/memory/weak_ptr.h" #include "base/containers/unique_ptr_adapters.h"
#include "chrome/browser/installable/installable_metrics.h" #include "base/macros.h"
#include "chrome/browser/web_applications/components/install_manager.h" #include "chrome/browser/web_applications/components/install_manager.h"
#include "chrome/browser/web_applications/components/web_app_install_utils.h" #include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "content/public/browser/web_contents_observer.h"
class Profile; class Profile;
struct WebApplicationInfo;
namespace blink {
struct Manifest;
}
namespace content {
class WebContents;
}
namespace web_app { namespace web_app {
enum class InstallResultCode;
class InstallFinalizer; class InstallFinalizer;
class WebAppDataRetriever; class WebAppInstallTask;
class WebAppInstallManager final : public InstallManager, class WebAppInstallManager final : public InstallManager {
content::WebContentsObserver {
public: public:
WebAppInstallManager(Profile* profile, InstallFinalizer* install_finalizer); WebAppInstallManager(Profile* profile, InstallFinalizer* install_finalizer);
~WebAppInstallManager() override; ~WebAppInstallManager() override;
...@@ -63,58 +53,19 @@ class WebAppInstallManager final : public InstallManager, ...@@ -63,58 +53,19 @@ class WebAppInstallManager final : public InstallManager,
std::unique_ptr<WebApplicationInfo> web_application_info, std::unique_ptr<WebApplicationInfo> web_application_info,
OnceInstallCallback callback) override; OnceInstallCallback callback) override;
// WebContentsObserver:
void WebContentsDestroyed() override;
void SetDataRetrieverForTesting(
std::unique_ptr<WebAppDataRetriever> data_retriever);
void SetInstallFinalizerForTesting(InstallFinalizer* install_finalizer);
private: private:
void CallInstallCallback(const AppId& app_id, InstallResultCode code); void OnTaskCompleted(WebAppInstallTask* task,
void ReturnError(InstallResultCode code); OnceInstallCallback callback,
const AppId& app_id,
InstallResultCode code);
// Checks typical errors like WebContents destroyed. Callers must return using Tasks = base::flat_set<std::unique_ptr<WebAppInstallTask>,
// early if this is true. Note that if install interrupted, install_callback_ base::UniquePtrComparator>;
// is already invoked or may be invoked later - no actions needed from caller. Tasks tasks_;
bool InstallInterrupted() const;
void OnGetWebApplicationInfo(
bool force_shortcut_app,
std::unique_ptr<WebApplicationInfo> web_app_info);
void OnDidPerformInstallableCheck(
std::unique_ptr<WebApplicationInfo> web_app_info,
bool force_shortcut_app,
const blink::Manifest& manifest,
bool is_installable);
void OnIconsRetrieved(std::unique_ptr<WebApplicationInfo> web_app_info,
ForInstallableSite for_installable_site,
IconsMap icons_map);
void OnDialogCompleted(ForInstallableSite for_installable_site,
bool user_accepted,
std::unique_ptr<WebApplicationInfo> web_app_info);
void OnInstallFinalized(std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
InstallResultCode code);
void OnShortcutsCreated(std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
bool shortcut_created);
// TODO(loyso): Extract these parameters as a struct and reset it on every
// installation task:
WebAppInstallDialogCallback dialog_callback_;
OnceInstallCallback install_callback_;
// The mechanism via which the app creation was triggered.
static constexpr WebappInstallSource kNoInstallSource =
WebappInstallSource::COUNT;
WebappInstallSource install_source_ = kNoInstallSource;
std::unique_ptr<WebAppDataRetriever> data_retriever_;
InstallFinalizer* install_finalizer_; InstallFinalizer* install_finalizer_;
Profile* profile_; Profile* profile_;
base::WeakPtrFactory<WebAppInstallManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WebAppInstallManager); DISALLOW_COPY_AND_ASSIGN(WebAppInstallManager);
}; };
......
// 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 <utility>
#include "chrome/browser/web_applications/web_app_install_task.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/components/install_finalizer.h"
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_data_retriever.h"
#include "chrome/browser/web_applications/components/web_app_icon_generator.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/web_application_info.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/common/manifest/manifest.h"
namespace web_app {
WebAppInstallTask::WebAppInstallTask(Profile* profile,
InstallFinalizer* install_finalizer)
: data_retriever_(std::make_unique<WebAppDataRetriever>()),
install_finalizer_(install_finalizer),
profile_(profile) {}
WebAppInstallTask::~WebAppInstallTask() = default;
void WebAppInstallTask::InstallWebApp(
content::WebContents* contents,
bool force_shortcut_app,
WebappInstallSource install_source,
InstallManager::WebAppInstallDialogCallback dialog_callback,
InstallManager::OnceInstallCallback install_callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(AreWebAppsUserInstallable(profile_));
// Concurrent calls are not allowed.
DCHECK(!web_contents());
CHECK(!install_callback_);
Observe(contents);
dialog_callback_ = std::move(dialog_callback);
install_callback_ = std::move(install_callback);
install_source_ = install_source;
data_retriever_->GetWebApplicationInfo(
web_contents(),
base::BindOnce(&WebAppInstallTask::OnGetWebApplicationInfo,
weak_ptr_factory_.GetWeakPtr(), force_shortcut_app));
}
void WebAppInstallTask::WebContentsDestroyed() {
CallInstallCallback(AppId(), InstallResultCode::kWebContentsDestroyed);
}
void WebAppInstallTask::SetDataRetrieverForTesting(
std::unique_ptr<WebAppDataRetriever> data_retriever) {
data_retriever_ = std::move(data_retriever);
}
void WebAppInstallTask::SetInstallFinalizerForTesting(
InstallFinalizer* install_finalizer) {
install_finalizer_ = install_finalizer;
}
void WebAppInstallTask::CallInstallCallback(const AppId& app_id,
InstallResultCode code) {
Observe(nullptr);
dialog_callback_.Reset();
DCHECK(install_source_ != kNoInstallSource);
install_source_ = kNoInstallSource;
DCHECK(install_callback_);
std::move(install_callback_).Run(app_id, code);
}
bool WebAppInstallTask::ShouldStopInstall() const {
// Install should stop early if WebContents is being destroyed.
// WebAppInstallTask::WebContentsDestroyed will get called eventually and the
// callback will be invoked at that point.
return !web_contents() || web_contents()->IsBeingDestroyed();
}
void WebAppInstallTask::OnGetWebApplicationInfo(
bool force_shortcut_app,
std::unique_ptr<WebApplicationInfo> web_app_info) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (ShouldStopInstall())
return;
if (!web_app_info) {
CallInstallCallback(AppId(),
InstallResultCode::kGetWebApplicationInfoFailed);
return;
}
data_retriever_->CheckInstallabilityAndRetrieveManifest(
web_contents(),
base::BindOnce(&WebAppInstallTask::OnDidPerformInstallableCheck,
weak_ptr_factory_.GetWeakPtr(), std::move(web_app_info),
force_shortcut_app));
}
void WebAppInstallTask::OnDidPerformInstallableCheck(
std::unique_ptr<WebApplicationInfo> web_app_info,
bool force_shortcut_app,
const blink::Manifest& manifest,
bool is_installable) {
if (ShouldStopInstall())
return;
DCHECK(web_app_info);
const auto for_installable_site = is_installable && !force_shortcut_app
? ForInstallableSite::kYes
: ForInstallableSite::kNo;
// TODO(loyso): Implement UpdateShareTargetInPrefs installation logic.
UpdateWebAppInfoFromManifest(manifest, web_app_info.get(),
for_installable_site);
std::vector<GURL> icon_urls;
for (auto& icon_info : web_app_info->icons) {
if (icon_info.url.is_valid())
icon_urls.push_back(icon_info.url);
}
// If the manifest specified icons, don't use the page icons.
const bool skip_page_fav_icons = !manifest.icons.empty();
data_retriever_->GetIcons(
web_contents(), icon_urls, skip_page_fav_icons,
base::BindOnce(&WebAppInstallTask::OnIconsRetrieved,
weak_ptr_factory_.GetWeakPtr(), std::move(web_app_info),
for_installable_site));
}
void WebAppInstallTask::OnIconsRetrieved(
std::unique_ptr<WebApplicationInfo> web_app_info,
ForInstallableSite for_installable_site,
IconsMap icons_map) {
if (ShouldStopInstall())
return;
DCHECK(web_app_info);
std::vector<BitmapAndSource> downloaded_icons =
FilterSquareIcons(icons_map, *web_app_info);
ResizeDownloadedIconsGenerateMissing(std::move(downloaded_icons),
web_app_info.get());
std::move(dialog_callback_)
.Run(
web_contents(), std::move(web_app_info), for_installable_site,
base::BindOnce(&WebAppInstallTask::OnDialogCompleted,
weak_ptr_factory_.GetWeakPtr(), for_installable_site));
}
void WebAppInstallTask::OnDialogCompleted(
ForInstallableSite for_installable_site,
bool user_accepted,
std::unique_ptr<WebApplicationInfo> web_app_info) {
if (ShouldStopInstall())
return;
if (!user_accepted) {
CallInstallCallback(AppId(), InstallResultCode::kUserInstallDeclined);
return;
}
WebApplicationInfo web_app_info_copy = *web_app_info;
DCHECK(install_source_ != kNoInstallSource);
// This metric is recorded regardless of the installation result.
if (InstallableMetrics::IsReportableInstallSource(install_source_) &&
for_installable_site == ForInstallableSite::kYes) {
InstallableMetrics::TrackInstallEvent(install_source_);
}
install_finalizer_->FinalizeInstall(
web_app_info_copy,
base::BindOnce(&WebAppInstallTask::OnInstallFinalized,
weak_ptr_factory_.GetWeakPtr(), std::move(web_app_info)));
// Check that the finalizer hasn't called OnInstallFinalized synchronously:
DCHECK(install_callback_);
}
void WebAppInstallTask::OnInstallFinalized(
std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
InstallResultCode code) {
if (ShouldStopInstall())
return;
if (code != InstallResultCode::kSuccess) {
CallInstallCallback(app_id, code);
return;
}
RecordAppBanner(web_contents(), web_app_info->app_url);
// TODO(loyso): Implement |create_shortcuts| to skip OS shortcuts creation.
auto create_shortcuts_callback = base::BindOnce(
&WebAppInstallTask::OnShortcutsCreated, weak_ptr_factory_.GetWeakPtr(),
std::move(web_app_info), app_id);
if (install_finalizer_->CanCreateOsShortcuts()) {
install_finalizer_->CreateOsShortcuts(app_id,
std::move(create_shortcuts_callback));
} else {
std::move(create_shortcuts_callback).Run(false /* created_shortcuts */);
}
}
void WebAppInstallTask::OnShortcutsCreated(
std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
bool shortcut_created) {
if (ShouldStopInstall())
return;
if (install_finalizer_->CanPinAppToShelf())
install_finalizer_->PinAppToShelf(app_id);
// TODO(loyso): Implement |reparent_tab| to skip tab reparenting logic.
if (web_app_info->open_as_window &&
install_finalizer_->CanReparentTab(app_id, shortcut_created)) {
install_finalizer_->ReparentTab(app_id, web_contents());
}
if (install_finalizer_->CanRevealAppShim())
install_finalizer_->RevealAppShim(app_id);
CallInstallCallback(app_id, InstallResultCode::kSuccess);
}
} // namespace web_app
// 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.
#ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_INSTALL_TASK_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_INSTALL_TASK_H_
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/installable/installable_metrics.h"
#include "chrome/browser/web_applications/components/install_manager.h"
#include "chrome/browser/web_applications/components/web_app_install_utils.h"
#include "content/public/browser/web_contents_observer.h"
class Profile;
struct WebApplicationInfo;
namespace blink {
struct Manifest;
}
namespace content {
class WebContents;
}
namespace web_app {
class InstallFinalizer;
class WebAppDataRetriever;
class WebAppInstallTask : content::WebContentsObserver {
public:
WebAppInstallTask(Profile* profile, InstallFinalizer* install_finalizer);
~WebAppInstallTask() override;
void InstallWebApp(
content::WebContents* web_contents,
bool force_shortcut_app,
WebappInstallSource install_source,
InstallManager::WebAppInstallDialogCallback dialog_callback,
InstallManager::OnceInstallCallback callback);
// WebContentsObserver:
void WebContentsDestroyed() override;
void SetDataRetrieverForTesting(
std::unique_ptr<WebAppDataRetriever> data_retriever);
void SetInstallFinalizerForTesting(InstallFinalizer* install_finalizer);
private:
// Calling the callback may destroy |this| task. Callers shoudln't work with
// any |this| class members after calling it.
void CallInstallCallback(const AppId& app_id, InstallResultCode code);
// Checks if any errors occurred while |this| was async awaiting. All On*
// completion handlers below must return early if this is true. Also, if
// ShouldStopInstall is true, install_callback_ is already invoked or may be
// invoked later: All On* completion handlers don't need to call
// install_callback_.
bool ShouldStopInstall() const;
void OnGetWebApplicationInfo(
bool force_shortcut_app,
std::unique_ptr<WebApplicationInfo> web_app_info);
void OnDidPerformInstallableCheck(
std::unique_ptr<WebApplicationInfo> web_app_info,
bool force_shortcut_app,
const blink::Manifest& manifest,
bool is_installable);
void OnIconsRetrieved(std::unique_ptr<WebApplicationInfo> web_app_info,
ForInstallableSite for_installable_site,
IconsMap icons_map);
void OnDialogCompleted(ForInstallableSite for_installable_site,
bool user_accepted,
std::unique_ptr<WebApplicationInfo> web_app_info);
void OnInstallFinalized(std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
InstallResultCode code);
void OnShortcutsCreated(std::unique_ptr<WebApplicationInfo> web_app_info,
const AppId& app_id,
bool shortcut_created);
InstallManager::WebAppInstallDialogCallback dialog_callback_;
InstallManager::OnceInstallCallback install_callback_;
// The mechanism via which the app creation was triggered.
static constexpr WebappInstallSource kNoInstallSource =
WebappInstallSource::COUNT;
WebappInstallSource install_source_ = kNoInstallSource;
std::unique_ptr<WebAppDataRetriever> data_retriever_;
InstallFinalizer* install_finalizer_;
Profile* profile_;
base::WeakPtrFactory<WebAppInstallTask> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WebAppInstallTask);
};
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_INSTALL_TASK_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/web_applications/web_app_install_manager.h" #include "chrome/browser/web_applications/web_app_install_task.h"
#include <memory> #include <memory>
...@@ -98,7 +98,7 @@ void TestDeclineDialogCallback( ...@@ -98,7 +98,7 @@ void TestDeclineDialogCallback(
} // namespace } // namespace
class WebAppInstallManagerTest : public WebAppTest { class WebAppInstallTaskTest : public WebAppTest {
public: public:
void SetUp() override { void SetUp() override {
WebAppTest::SetUp(); WebAppTest::SetUp();
...@@ -115,7 +115,7 @@ class WebAppInstallManagerTest : public WebAppTest { ...@@ -115,7 +115,7 @@ class WebAppInstallManagerTest : public WebAppTest {
install_finalizer_ = std::make_unique<WebAppInstallFinalizer>( install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(
registrar_.get(), icon_manager_.get()); registrar_.get(), icon_manager_.get());
install_manager_ = std::make_unique<WebAppInstallManager>( install_task_ = std::make_unique<WebAppInstallTask>(
profile(), install_finalizer_.get()); profile(), install_finalizer_.get());
} }
...@@ -136,7 +136,7 @@ class WebAppInstallManagerTest : public WebAppTest { ...@@ -136,7 +136,7 @@ class WebAppInstallManagerTest : public WebAppTest {
auto data_retriever = auto data_retriever =
std::make_unique<TestDataRetriever>(std::move(web_app_info)); std::make_unique<TestDataRetriever>(std::move(web_app_info));
data_retriever_ = data_retriever.get(); data_retriever_ = data_retriever.get();
install_manager_->SetDataRetrieverForTesting(std::move(data_retriever)); install_task_->SetDataRetrieverForTesting(std::move(data_retriever));
} }
void CreateRendererAppInfo(const GURL& url, void CreateRendererAppInfo(const GURL& url,
...@@ -160,7 +160,7 @@ class WebAppInstallManagerTest : public WebAppTest { ...@@ -160,7 +160,7 @@ class WebAppInstallManagerTest : public WebAppTest {
auto test_install_finalizer = std::make_unique<TestInstallFinalizer>(); auto test_install_finalizer = std::make_unique<TestInstallFinalizer>();
test_install_finalizer_ = test_install_finalizer.get(); test_install_finalizer_ = test_install_finalizer.get();
install_finalizer_ = std::move(test_install_finalizer); install_finalizer_ = std::move(test_install_finalizer);
install_manager_->SetInstallFinalizerForTesting(test_install_finalizer_); install_task_->SetInstallFinalizerForTesting(test_install_finalizer_);
} }
TestInstallFinalizer& test_install_finalizer() { TestInstallFinalizer& test_install_finalizer() {
...@@ -182,7 +182,7 @@ class WebAppInstallManagerTest : public WebAppTest { ...@@ -182,7 +182,7 @@ class WebAppInstallManagerTest : public WebAppTest {
InstallResult result; InstallResult result;
base::RunLoop run_loop; base::RunLoop run_loop;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, web_contents(), force_shortcut_app,
WebappInstallSource::MENU_BROWSER_TAB, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
...@@ -217,10 +217,10 @@ class WebAppInstallManagerTest : public WebAppTest { ...@@ -217,10 +217,10 @@ class WebAppInstallManagerTest : public WebAppTest {
std::unique_ptr<TestWebAppDatabase> database_; std::unique_ptr<TestWebAppDatabase> database_;
std::unique_ptr<WebAppRegistrar> registrar_; std::unique_ptr<WebAppRegistrar> registrar_;
std::unique_ptr<WebAppIconManager> icon_manager_; std::unique_ptr<WebAppIconManager> icon_manager_;
std::unique_ptr<WebAppInstallManager> install_manager_; std::unique_ptr<WebAppInstallTask> install_task_;
std::unique_ptr<InstallFinalizer> install_finalizer_; std::unique_ptr<InstallFinalizer> install_finalizer_;
// Owned by install_manager_: // Owned by install_task_:
TestFileUtils* file_utils_ = nullptr; TestFileUtils* file_utils_ = nullptr;
TestDataRetriever* data_retriever_ = nullptr; TestDataRetriever* data_retriever_ = nullptr;
...@@ -228,7 +228,7 @@ class WebAppInstallManagerTest : public WebAppTest { ...@@ -228,7 +228,7 @@ class WebAppInstallManagerTest : public WebAppTest {
TestInstallFinalizer* test_install_finalizer_ = nullptr; TestInstallFinalizer* test_install_finalizer_ = nullptr;
}; };
TEST_F(WebAppInstallManagerTest, InstallFromWebContents) { TEST_F(WebAppInstallTaskTest, InstallFromWebContents) {
EXPECT_TRUE(AreWebAppsUserInstallable(profile())); EXPECT_TRUE(AreWebAppsUserInstallable(profile()));
const GURL url = GURL("https://example.com/path"); const GURL url = GURL("https://example.com/path");
...@@ -246,7 +246,7 @@ TEST_F(WebAppInstallManagerTest, InstallFromWebContents) { ...@@ -246,7 +246,7 @@ TEST_F(WebAppInstallManagerTest, InstallFromWebContents) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -271,7 +271,7 @@ TEST_F(WebAppInstallManagerTest, InstallFromWebContents) { ...@@ -271,7 +271,7 @@ TEST_F(WebAppInstallManagerTest, InstallFromWebContents) {
EXPECT_EQ(theme_color, web_app->theme_color()); EXPECT_EQ(theme_color, web_app->theme_color());
} }
TEST_F(WebAppInstallManagerTest, AlreadyInstalled) { TEST_F(WebAppInstallTaskTest, AlreadyInstalled) {
const GURL url = GURL("https://example.com/path"); const GURL url = GURL("https://example.com/path");
const std::string name = "Name"; const std::string name = "Name";
const std::string description = "Description"; const std::string description = "Description";
...@@ -291,7 +291,7 @@ TEST_F(WebAppInstallManagerTest, AlreadyInstalled) { ...@@ -291,7 +291,7 @@ TEST_F(WebAppInstallManagerTest, AlreadyInstalled) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -306,10 +306,9 @@ TEST_F(WebAppInstallManagerTest, AlreadyInstalled) { ...@@ -306,10 +306,9 @@ TEST_F(WebAppInstallManagerTest, AlreadyInstalled) {
EXPECT_TRUE(callback_called); EXPECT_TRUE(callback_called);
} }
TEST_F(WebAppInstallManagerTest, GetWebApplicationInfoFailed) { TEST_F(WebAppInstallTaskTest, GetWebApplicationInfoFailed) {
install_manager_->SetDataRetrieverForTesting( install_task_->SetDataRetrieverForTesting(std::make_unique<TestDataRetriever>(
std::make_unique<TestDataRetriever>( std::unique_ptr<WebApplicationInfo>()));
std::unique_ptr<WebApplicationInfo>()));
CreateDefaultInstallableManager(); CreateDefaultInstallableManager();
...@@ -317,7 +316,7 @@ TEST_F(WebAppInstallManagerTest, GetWebApplicationInfoFailed) { ...@@ -317,7 +316,7 @@ TEST_F(WebAppInstallManagerTest, GetWebApplicationInfoFailed) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -332,7 +331,7 @@ TEST_F(WebAppInstallManagerTest, GetWebApplicationInfoFailed) { ...@@ -332,7 +331,7 @@ TEST_F(WebAppInstallManagerTest, GetWebApplicationInfoFailed) {
EXPECT_TRUE(callback_called); EXPECT_TRUE(callback_called);
} }
TEST_F(WebAppInstallManagerTest, WebContentsDestroyed) { TEST_F(WebAppInstallTaskTest, WebContentsDestroyed) {
CreateRendererAppInfo(GURL("https://example.com/path"), "Name", CreateRendererAppInfo(GURL("https://example.com/path"), "Name",
"Description"); "Description");
CreateDefaultInstallableManager(); CreateDefaultInstallableManager();
...@@ -341,7 +340,7 @@ TEST_F(WebAppInstallManagerTest, WebContentsDestroyed) { ...@@ -341,7 +340,7 @@ TEST_F(WebAppInstallManagerTest, WebContentsDestroyed) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -361,7 +360,7 @@ TEST_F(WebAppInstallManagerTest, WebContentsDestroyed) { ...@@ -361,7 +360,7 @@ TEST_F(WebAppInstallManagerTest, WebContentsDestroyed) {
EXPECT_TRUE(callback_called); EXPECT_TRUE(callback_called);
} }
TEST_F(WebAppInstallManagerTest, InstallableCheck) { TEST_F(WebAppInstallTaskTest, InstallableCheck) {
const std::string renderer_description = "RendererDescription"; const std::string renderer_description = "RendererDescription";
CreateRendererAppInfo(GURL("https://renderer.com/path"), "RendererName", CreateRendererAppInfo(GURL("https://renderer.com/path"), "RendererName",
renderer_description, renderer_description,
...@@ -390,7 +389,7 @@ TEST_F(WebAppInstallManagerTest, InstallableCheck) { ...@@ -390,7 +389,7 @@ TEST_F(WebAppInstallManagerTest, InstallableCheck) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -416,7 +415,7 @@ TEST_F(WebAppInstallManagerTest, InstallableCheck) { ...@@ -416,7 +415,7 @@ TEST_F(WebAppInstallManagerTest, InstallableCheck) {
EXPECT_EQ(manifest_theme_color, web_app->theme_color()); EXPECT_EQ(manifest_theme_color, web_app->theme_color());
} }
TEST_F(WebAppInstallManagerTest, GetIcons) { TEST_F(WebAppInstallTaskTest, GetIcons) {
CreateRendererAppInfo(GURL("https://example.com/path"), "Name", CreateRendererAppInfo(GURL("https://example.com/path"), "Name",
"Description"); "Description");
CreateDefaultInstallableManager(); CreateDefaultInstallableManager();
...@@ -450,7 +449,7 @@ TEST_F(WebAppInstallManagerTest, GetIcons) { ...@@ -450,7 +449,7 @@ TEST_F(WebAppInstallManagerTest, GetIcons) {
} }
} }
TEST_F(WebAppInstallManagerTest, GetIcons_NoIconsProvided) { TEST_F(WebAppInstallTaskTest, GetIcons_NoIconsProvided) {
CreateRendererAppInfo(GURL("https://example.com/path"), "Name", CreateRendererAppInfo(GURL("https://example.com/path"), "Name",
"Description"); "Description");
CreateDefaultInstallableManager(); CreateDefaultInstallableManager();
...@@ -475,7 +474,7 @@ TEST_F(WebAppInstallManagerTest, GetIcons_NoIconsProvided) { ...@@ -475,7 +474,7 @@ TEST_F(WebAppInstallManagerTest, GetIcons_NoIconsProvided) {
} }
} }
TEST_F(WebAppInstallManagerTest, WriteDataToDisk) { TEST_F(WebAppInstallTaskTest, WriteDataToDisk) {
CreateRendererAppInfo(GURL("https://example.com/path"), "Name", CreateRendererAppInfo(GURL("https://example.com/path"), "Name",
"Description"); "Description");
CreateDefaultInstallableManager(); CreateDefaultInstallableManager();
...@@ -544,7 +543,7 @@ TEST_F(WebAppInstallManagerTest, WriteDataToDisk) { ...@@ -544,7 +543,7 @@ TEST_F(WebAppInstallManagerTest, WriteDataToDisk) {
EXPECT_TRUE(written_sizes_px.empty()); EXPECT_TRUE(written_sizes_px.empty());
} }
TEST_F(WebAppInstallManagerTest, WriteDataToDiskFailed) { TEST_F(WebAppInstallTaskTest, WriteDataToDiskFailed) {
const GURL app_url = GURL("https://example.com/path"); const GURL app_url = GURL("https://example.com/path");
CreateRendererAppInfo(app_url, "Name", "Description"); CreateRendererAppInfo(app_url, "Name", "Description");
CreateDefaultInstallableManager(); CreateDefaultInstallableManager();
...@@ -565,7 +564,7 @@ TEST_F(WebAppInstallManagerTest, WriteDataToDiskFailed) { ...@@ -565,7 +564,7 @@ TEST_F(WebAppInstallManagerTest, WriteDataToDiskFailed) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestAcceptDialogCallback), base::BindOnce(TestAcceptDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -587,7 +586,7 @@ TEST_F(WebAppInstallManagerTest, WriteDataToDiskFailed) { ...@@ -587,7 +586,7 @@ TEST_F(WebAppInstallManagerTest, WriteDataToDiskFailed) {
EXPECT_FALSE(file_utils_->DirectoryExists(app_dir)); EXPECT_FALSE(file_utils_->DirectoryExists(app_dir));
} }
TEST_F(WebAppInstallManagerTest, UserInstallDeclined) { TEST_F(WebAppInstallTaskTest, UserInstallDeclined) {
const GURL url = GURL("https://example.com/path"); const GURL url = GURL("https://example.com/path");
const AppId app_id = GenerateAppIdFromURL(url); const AppId app_id = GenerateAppIdFromURL(url);
...@@ -598,7 +597,7 @@ TEST_F(WebAppInstallManagerTest, UserInstallDeclined) { ...@@ -598,7 +597,7 @@ TEST_F(WebAppInstallManagerTest, UserInstallDeclined) {
bool callback_called = false; bool callback_called = false;
const bool force_shortcut_app = false; const bool force_shortcut_app = false;
install_manager_->InstallWebApp( install_task_->InstallWebApp(
web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB, web_contents(), force_shortcut_app, WebappInstallSource::MENU_BROWSER_TAB,
base::BindOnce(TestDeclineDialogCallback), base::BindOnce(TestDeclineDialogCallback),
base::BindLambdaForTesting( base::BindLambdaForTesting(
...@@ -616,7 +615,7 @@ TEST_F(WebAppInstallManagerTest, UserInstallDeclined) { ...@@ -616,7 +615,7 @@ TEST_F(WebAppInstallManagerTest, UserInstallDeclined) {
EXPECT_EQ(nullptr, web_app); EXPECT_EQ(nullptr, web_app);
} }
TEST_F(WebAppInstallManagerTest, FinalizerMethodsCalled) { TEST_F(WebAppInstallTaskTest, FinalizerMethodsCalled) {
PrepareTestAppInstall(); PrepareTestAppInstall();
InstallWebApp(); InstallWebApp();
...@@ -627,7 +626,7 @@ TEST_F(WebAppInstallManagerTest, FinalizerMethodsCalled) { ...@@ -627,7 +626,7 @@ TEST_F(WebAppInstallManagerTest, FinalizerMethodsCalled) {
EXPECT_EQ(1, test_install_finalizer().num_pin_app_to_shelf_calls()); EXPECT_EQ(1, test_install_finalizer().num_pin_app_to_shelf_calls());
} }
TEST_F(WebAppInstallManagerTest, FinalizerMethodsNotCalled) { TEST_F(WebAppInstallTaskTest, FinalizerMethodsNotCalled) {
PrepareTestAppInstall(); PrepareTestAppInstall();
test_install_finalizer().SetNextFinalizeInstallResult( test_install_finalizer().SetNextFinalizeInstallResult(
AppId(), InstallResultCode::kFailedUnknownReason); AppId(), InstallResultCode::kFailedUnknownReason);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment