blob: 14099325d755570de378d27aaa26d0bb2708cc5f [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_BROWSER_AW_APP_DEFINED_WEBSITES_H_
#define ANDROID_WEBVIEW_BROWSER_AW_APP_DEFINED_WEBSITES_H_
#include <memory>
#include <string>
#include <vector>
#include "android_webview/browser/aw_asset_domain_list_include_handler.h"
#include "base/callback_list.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/origin.h"
namespace android_webview {
// Used to determine which sources to retrieve related websites from.
// This enum is used to set the values for feature parameter
// `features::kWebViewIpProtectionExclusionCriteria`.
// Do not modify/reorder the enum without ensuring that the above mentioned
// feature is compatible with the change.
enum class AppDefinedDomainCriteria {
// Return nothing.
kNone = 0,
// Return domains defined in the `asset_statements` meta-data tag in the
// app's manifest.
kAndroidAssetStatements = 1,
// For API >= 31, return domains defined in Android App Links and verified
// by DomainVerificationManager.
// For API < 31, return nothing.
kAndroidVerifiedAppLinks = 2,
// For API >= 31, return domains defined in Web Links (including Android
// App Links).
// For API < 31, return nothing.
kAndroidWebLinks = 3,
// Union of kAndroidAssetStatements, kAndroidVerifiedAppLinks and
// kAndroidVerifiedAppLinks.
kAndroidAssetStatementsAndWebLinks = 4,
};
// AppDefinedWebsites provides access to domain lists defined in the embedding
// app's manifest file. As the domain lists are static, they will be cached for
// future access once they have been loaded once.
// This class should only be accessed on the UI thread.
class AppDefinedWebsites {
public:
using AppDomainCallbackFunctionType = void(const std::vector<std::string>&);
using AppDomainCallback = base::OnceCallback<AppDomainCallbackFunctionType>;
using AppDomainSetCallback =
base::OnceCallback<void(const std::vector<std::string>&)>;
// Get the global instance of AppDefinedWebsites.
// May only be called on the UI thread.
static AppDefinedWebsites* GetInstance();
// Get the specified list of domains from the app manifest.
// The list will be fetched on a background thread if it is not already
// cached. The `callback` will be executed on the calling sequence.
void GetAppDefinedDomains(AppDefinedDomainCriteria criteria,
AppDomainCallback callback);
// Get the list of Android Asset Statement domains, including any domains
// refenced through "include" statements.
// This method may cause network requests if there are any include statements
// in the asset list and they have not been loaded yet.
// The `domain_list_loader` will be used to load included references from the
// network. The `callback` is executed on the calling sequence.
void GetAssetStatmentsWithIncludes(
std::unique_ptr<AssetDomainListIncludeHandler> domain_list_loader,
AppDomainSetCallback callback);
// Check if the provided `origin` is defined by the app's asset statement
// domains. This method may cause network requests if there are any include
// statements in the asset list and they have not been loaded yet. The
// `domain_list_loader` will be used to load included references from the
// network. The `callback` is executed on the calling sequence.
void AppDeclaresDomainInAssetStatements(
std::unique_ptr<AssetDomainListIncludeHandler> domain_list_loader,
const url::Origin& origin,
base::OnceCallback<void(bool)> callback);
private:
friend class base::NoDestructor<AppDefinedWebsites>;
friend class AppDefinedWebsitesTest;
using AppDomainProvider = base::RepeatingCallback<std::vector<std::string>(
AppDefinedDomainCriteria)>;
using IncludeLinkProvider =
base::RepeatingCallback<std::vector<std::string>()>;
using AppDomainCallbackList =
base::OnceCallbackList<AppDomainCallbackFunctionType>;
AppDefinedWebsites(AppDomainProvider provider,
IncludeLinkProvider include_link_provider);
~AppDefinedWebsites();
AppDomainCallbackList& GetCallbackList(AppDefinedDomainCriteria criteria);
void DomainsReturnedFromManifest(AppDefinedDomainCriteria criteria,
const std::vector<std::string>& data);
void AssetIncludeStatementsReturned(
std::unique_ptr<AssetDomainListIncludeHandler> domain_list_loader,
std::vector<std::string> data);
void OnAssetStatementsWithIncludesLoaded(
std::unique_ptr<AssetDomainListIncludeHandler> domain_list_handler,
std::vector<std::vector<std::string>> all_domains);
SEQUENCE_CHECKER(sequence_checker_);
AppDomainProvider provider_;
IncludeLinkProvider include_link_provider_;
// Cache of already-fetched domains. A nullptr value means the domains have
// not been fetched yet.
base::flat_map<AppDefinedDomainCriteria,
std::unique_ptr<std::vector<std::string>>>
domains_cache_;
// Lists of callbacks that wait for a particular criteria to be fetched.
// Using OnceCallbackList to handle multiple concurrent calls waiting.
base::flat_map<AppDefinedDomainCriteria,
std::unique_ptr<AppDomainCallbackList>>
on_domains_returned_callbacks_;
std::unique_ptr<std::vector<std::string>> asset_statements_with_includes_;
AppDomainCallbackList asset_statements_with_includes_callbacks_;
base::WeakPtrFactory<AppDefinedWebsites> weak_ptr_factory_{this};
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_AW_APP_DEFINED_WEBSITES_H_