Commit 77012d26 authored by Giovanni Ortuño Urquidi's avatar Giovanni Ortuño Urquidi Committed by Commit Bot

desktop-pwas: Add queue to PendingBookmarkAppManager

Adds a queue to process installations to PendingBookmarkAppManager.

Multiple calls to Install() will result in installations being
added to the queue. Once an installation finishes, the next one
will start.

Bug: 864904
Change-Id: I063c1dd16760183a1fbbde64ed7b43bf89078dfe
Reviewed-on: https://chromium-review.googlesource.com/1163403
Commit-Queue: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#582781}
parent 291dd264
......@@ -9,10 +9,11 @@
#include <utility>
#include <vector>
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
namespace extensions {
......@@ -33,6 +34,15 @@ std::unique_ptr<BookmarkAppInstallationTask> InstallationTaskCreateWrapper(
} // namespace
struct PendingBookmarkAppManager::Installation {
Installation(AppInfo info, InstallCallback callback)
: info(std::move(info)), callback(std::move(callback)) {}
~Installation() = default;
AppInfo info;
InstallCallback callback;
};
PendingBookmarkAppManager::PendingBookmarkAppManager(Profile* profile)
: profile_(profile),
web_contents_factory_(base::BindRepeating(&WebContentsCreateWrapper)),
......@@ -42,22 +52,25 @@ PendingBookmarkAppManager::~PendingBookmarkAppManager() = default;
void PendingBookmarkAppManager::Install(AppInfo app_to_install,
InstallCallback callback) {
// The app is already being installed.
if (current_install_info_ && *current_install_info_ == app_to_install) {
// Check that we are not already installing the same app.
if (current_installation_ && current_installation_->info == app_to_install) {
std::move(callback).Run(std::string());
return;
}
for (const auto& installation : installation_queue_) {
if (installation->info == app_to_install) {
std::move(callback).Run(std::string());
return;
}
}
current_install_info_ = std::make_unique<AppInfo>(std::move(app_to_install));
current_install_callback_ = std::move(callback);
CreateWebContentsIfNecessary();
Observe(web_contents_.get());
installation_queue_.push_back(std::make_unique<Installation>(
std::move(app_to_install), std::move(callback)));
content::NavigationController::LoadURLParams load_params(
current_install_info_->url);
load_params.transition_type = ui::PAGE_TRANSITION_GENERATED;
web_contents_->GetController().LoadURLWithParams(load_params);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&PendingBookmarkAppManager::MaybeStartNextInstallation,
weak_ptr_factory_.GetWeakPtr()));
}
void PendingBookmarkAppManager::ProcessAppOperations(
......@@ -70,11 +83,53 @@ void PendingBookmarkAppManager::SetFactoriesForTesting(
task_factory_ = std::move(task_factory);
}
void PendingBookmarkAppManager::MaybeStartNextInstallation() {
if (current_installation_)
return;
if (installation_queue_.empty()) {
web_contents_.reset();
return;
}
current_installation_ = std::move(installation_queue_.front());
installation_queue_.pop_front();
CreateWebContentsIfNecessary();
Observe(web_contents_.get());
content::NavigationController::LoadURLParams load_params(
current_installation_->info.url);
load_params.transition_type = ui::PAGE_TRANSITION_GENERATED;
web_contents_->GetController().LoadURLWithParams(load_params);
}
void PendingBookmarkAppManager::CreateWebContentsIfNecessary() {
if (!web_contents_)
web_contents_ = web_contents_factory_.Run(profile_);
}
void PendingBookmarkAppManager::OnInstalled(
BookmarkAppInstallationTask::Result result) {
CurrentInstallationFinished(result.app_id);
}
void PendingBookmarkAppManager::CurrentInstallationFinished(
const std::string& app_id) {
// Post a task to avoid reentrancy issues e.g. adding a WebContentsObserver
// while a previous observer call is being executed. Post a task before
// running the callback in case the callback tries to install another
// app.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&PendingBookmarkAppManager::MaybeStartNextInstallation,
weak_ptr_factory_.GetWeakPtr()));
std::unique_ptr<Installation> installation;
installation.swap(current_installation_);
std::move(installation->callback).Run(app_id);
}
void PendingBookmarkAppManager::DidFinishLoad(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url) {
......@@ -82,8 +137,8 @@ void PendingBookmarkAppManager::DidFinishLoad(
return;
}
if (validated_url != current_install_info_->url) {
std::move(current_install_callback_).Run(std::string());
if (validated_url != current_installation_->info.url) {
CurrentInstallationFinished(std::string());
return;
}
......@@ -110,21 +165,7 @@ void PendingBookmarkAppManager::DidFailLoad(
}
Observe(nullptr);
// TODO(crbug.com/864904): Only destroy the WebContents if there are no
// queued installation requests.
web_contents_.reset();
current_install_info_.reset();
std::move(current_install_callback_).Run(std::string());
}
void PendingBookmarkAppManager::OnInstalled(
BookmarkAppInstallationTask::Result result) {
// TODO(crbug.com/864904): Only destroy the WebContents if there are no
// queued installation requests.
web_contents_.reset();
current_install_info_.reset();
std::move(current_install_callback_).Run(result.app_id);
CurrentInstallationFinished(std::string());
}
} // namespace extensions
......@@ -5,11 +5,14 @@
#ifndef CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_PENDING_BOOKMARK_APP_MANAGER_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_PENDING_BOOKMARK_APP_MANAGER_H_
#include <deque>
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/web_applications/components/pending_app_manager.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_installation_task.h"
#include "content/public/browser/web_contents_observer.h"
......@@ -50,6 +53,16 @@ class PendingBookmarkAppManager final : public web_app::PendingAppManager,
TaskFactory task_factory);
private:
struct Installation;
void MaybeStartNextInstallation();
void CreateWebContentsIfNecessary();
void OnInstalled(BookmarkAppInstallationTask::Result result);
void CurrentInstallationFinished(const std::string& app_id);
// WebContentsObserver
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
......@@ -58,10 +71,6 @@ class PendingBookmarkAppManager final : public web_app::PendingAppManager,
int error_code,
const base::string16& error_description) override;
void OnInstalled(BookmarkAppInstallationTask::Result result);
void CreateWebContentsIfNecessary();
Profile* profile_;
WebContentsFactory web_contents_factory_;
......@@ -69,10 +78,13 @@ class PendingBookmarkAppManager final : public web_app::PendingAppManager,
std::unique_ptr<content::WebContents> web_contents_;
InstallCallback current_install_callback_;
std::unique_ptr<AppInfo> current_install_info_;
std::unique_ptr<Installation> current_installation_;
std::unique_ptr<BookmarkAppInstallationTask> current_installation_task_;
std::deque<std::unique_ptr<Installation>> installation_queue_;
base::WeakPtrFactory<PendingBookmarkAppManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PendingBookmarkAppManager);
};
......
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