1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
// Copyright 2021 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/web_applications/web_app_origin_association_task.h"
#include <optional>
#include <utility>
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/browser_process.h"
#include "components/webapps/services/web_app_origin_association/public/mojom/web_app_origin_association_parser.mojom.h"
#include "components/webapps/services/web_app_origin_association/web_app_origin_association_fetcher.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"
namespace web_app {
WebAppOriginAssociationManager::Task::Task(
const GURL& web_app_identity,
ScopeExtensions scope_extensions,
WebAppOriginAssociationManager& manager,
OnDidGetWebAppOriginAssociations callback)
: web_app_identity_(web_app_identity),
owner_(manager),
callback_(std::move(callback)) {
for (auto& scope_extension : scope_extensions) {
pending_scope_extensions_.push_back(std::move(scope_extension));
}
scope_extensions.clear();
}
WebAppOriginAssociationManager::Task::~Task() = default;
void WebAppOriginAssociationManager::Task::Start() {
if (pending_scope_extensions_.empty()) {
Finalize();
return;
}
FetchAssociationFile(GetCurrentScopeExtension());
}
ScopeExtensionInfo&
WebAppOriginAssociationManager::Task::GetCurrentScopeExtension() {
DCHECK(!pending_scope_extensions_.empty());
return pending_scope_extensions_.front();
}
void WebAppOriginAssociationManager::Task::FetchAssociationFile(
ScopeExtensionInfo& scope_extension) {
if (scope_extension.origin.Serialize().empty()) {
MaybeStartNextScopeExtension();
return;
}
owner_->GetFetcher().FetchWebAppOriginAssociationFile(
scope_extension.origin, g_browser_process->shared_url_loader_factory(),
base::BindOnce(
&WebAppOriginAssociationManager::Task::OnAssociationFileFetched,
weak_ptr_factory_.GetWeakPtr()));
}
void WebAppOriginAssociationManager::Task::OnAssociationFileFetched(
std::optional<std::string> file_content) {
if (!file_content || file_content->empty()) {
MaybeStartNextScopeExtension();
return;
}
owner_->GetParser()->ParseWebAppOriginAssociation(
*file_content, GetCurrentScopeExtension().origin,
base::BindOnce(&WebAppOriginAssociationManager::Task::OnAssociationParsed,
weak_ptr_factory_.GetWeakPtr()));
}
void WebAppOriginAssociationManager::Task::OnAssociationParsed(
webapps::mojom::WebAppOriginAssociationPtr association,
std::vector<webapps::mojom::WebAppOriginAssociationErrorPtr> errors) {
if (association.is_null() || association->apps.empty()) {
MaybeStartNextScopeExtension();
return;
}
auto& scope_extension = GetCurrentScopeExtension();
for (webapps::mojom::AssociatedWebAppPtr& associated_app :
association->apps) {
if (associated_app->web_app_identity == web_app_identity_) {
// Must drop the fragments and queries per `scope` rules
// https://w3c.github.io/manifest/#scope-member
GURL::Replacements replacements;
replacements.ClearRef();
replacements.ClearQuery();
scope_extension.scope =
associated_app->scope.ReplaceComponents(replacements);
result_.insert(scope_extension);
scope_extension.Reset();
// Only information in the first valid app is saved.
break;
}
}
association->apps.clear();
MaybeStartNextScopeExtension();
}
void WebAppOriginAssociationManager::Task::MaybeStartNextScopeExtension() {
DCHECK(!pending_scope_extensions_.empty());
pending_scope_extensions_.pop_front();
if (!pending_scope_extensions_.empty()) {
// Continue with the next scope extension.
FetchAssociationFile(GetCurrentScopeExtension());
return;
}
Finalize();
}
void WebAppOriginAssociationManager::Task::Finalize() {
ScopeExtensions result = std::move(result_);
result_.clear();
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback_), std::move(result)));
owner_->OnTaskCompleted();
}
} // namespace web_app
|