Commit 618f5936 authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

Update DigitialAssetLinksHandler to be more flexible.

The handler can now support checking for different types of digital
asset links, including web targets.

Also includes some minor stylistic improvements.

Bug: 1043970
Change-Id: Icb651573a98201c810e53f74cea91a225a48cac0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2037673Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738583}
parent 285bc3c0
...@@ -38,9 +38,9 @@ OriginVerifier::OriginVerifier(JNIEnv* env, ...@@ -38,9 +38,9 @@ OriginVerifier::OriginVerifier(JNIEnv* env,
DCHECK(profile); DCHECK(profile);
asset_link_handler_ = asset_link_handler_ =
std::make_unique<digital_asset_links::DigitalAssetLinksHandler>( std::make_unique<digital_asset_links::DigitalAssetLinksHandler>(
content::WebContents::FromJavaWebContents(jweb_contents),
content::BrowserContext::GetDefaultStoragePartition(profile) content::BrowserContext::GetDefaultStoragePartition(profile)
->GetURLLoaderFactoryForBrowserProcess()); ->GetURLLoaderFactoryForBrowserProcess(),
content::WebContents::FromJavaWebContents(jweb_contents));
} }
OriginVerifier::~OriginVerifier() = default; OriginVerifier::~OriginVerifier() = default;
...@@ -65,10 +65,10 @@ bool OriginVerifier::VerifyOrigin(JNIEnv* env, ...@@ -65,10 +65,10 @@ bool OriginVerifier::VerifyOrigin(JNIEnv* env,
// UrlFetcher making the request will also get killed, so we won't get any // UrlFetcher making the request will also get killed, so we won't get any
// dangling callback reference issues. // dangling callback reference issues.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return asset_link_handler_->CheckDigitalAssetLinkRelationship( return asset_link_handler_->CheckDigitalAssetLinkRelationshipForAndroidApp(
base::Bind(&customtabs::OriginVerifier::OnRelationshipCheckComplete, origin, relationship, fingerprint, package_name,
base::Unretained(this)), base::BindOnce(&customtabs::OriginVerifier::OnRelationshipCheckComplete,
origin, package_name, fingerprint, relationship); base::Unretained(this)));
} }
void OriginVerifier::OnRelationshipCheckComplete( void OriginVerifier::OnRelationshipCheckComplete(
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "chrome/browser/android/digital_asset_links/digital_asset_links_handler.h" #include "chrome/browser/android/digital_asset_links/digital_asset_links_handler.h"
#include <string>
#include <vector> #include <vector>
#include "base/bind.h" #include "base/bind.h"
...@@ -75,12 +74,13 @@ bool StatementHasMatchingRelationship(const base::Value& statement, ...@@ -75,12 +74,13 @@ bool StatementHasMatchingRelationship(const base::Value& statement,
return false; return false;
} }
bool StatementHasMatchingPackage(const base::Value& statement, bool StatementHasMatchingTargetValue(const base::Value& statement,
const std::string& target_package) { const std::string& target_key,
const std::string& target_value) {
const base::Value* package = statement.FindPathOfType( const base::Value* package = statement.FindPathOfType(
{"target", "package_name"}, base::Value::Type::STRING); {"target", target_key}, base::Value::Type::STRING);
return package && package->GetString() == target_package; return package && package->GetString() == target_value;
} }
bool StatementHasMatchingFingerprint(const base::Value& statement, bool StatementHasMatchingFingerprint(const base::Value& statement,
...@@ -121,17 +121,17 @@ namespace digital_asset_links { ...@@ -121,17 +121,17 @@ namespace digital_asset_links {
const char kDigitalAssetLinksCheckResponseKeyLinked[] = "linked"; const char kDigitalAssetLinksCheckResponseKeyLinked[] = "linked";
DigitalAssetLinksHandler::DigitalAssetLinksHandler( DigitalAssetLinksHandler::DigitalAssetLinksHandler(
content::WebContents* web_contents, scoped_refptr<network::SharedURLLoaderFactory> factory,
scoped_refptr<network::SharedURLLoaderFactory> factory) content::WebContents* web_contents)
: content::WebContentsObserver(web_contents), : content::WebContentsObserver(web_contents),
shared_url_loader_factory_(std::move(factory)) {} shared_url_loader_factory_(std::move(factory)) {}
DigitalAssetLinksHandler::~DigitalAssetLinksHandler() = default; DigitalAssetLinksHandler::~DigitalAssetLinksHandler() = default;
void DigitalAssetLinksHandler::OnURLLoadComplete( void DigitalAssetLinksHandler::OnURLLoadComplete(
const std::string& package, std::string relationship,
const std::string& fingerprint, base::Optional<std::string> fingerprint,
const std::string& relationship, std::map<std::string, std::string> target_values,
std::unique_ptr<std::string> response_body) { std::unique_ptr<std::string> response_body) {
int response_code = -1; int response_code = -1;
if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers)
...@@ -143,7 +143,7 @@ void DigitalAssetLinksHandler::OnURLLoadComplete( ...@@ -143,7 +143,7 @@ void DigitalAssetLinksHandler::OnURLLoadComplete(
net_error == net::ERR_NAME_NOT_RESOLVED) { net_error == net::ERR_NAME_NOT_RESOLVED) {
AddMessageToConsole(web_contents(), AddMessageToConsole(web_contents(),
"Digital Asset Links connection failed."); "Digital Asset Links connection failed.");
std::move(callback_).Run(RelationshipCheckResult::NO_CONNECTION); std::move(callback_).Run(RelationshipCheckResult::kNoConnection);
return; return;
} }
...@@ -152,36 +152,36 @@ void DigitalAssetLinksHandler::OnURLLoadComplete( ...@@ -152,36 +152,36 @@ void DigitalAssetLinksHandler::OnURLLoadComplete(
base::StringPrintf( base::StringPrintf(
"Digital Asset Links endpoint responded with code %d.", "Digital Asset Links endpoint responded with code %d.",
response_code)); response_code));
std::move(callback_).Run(RelationshipCheckResult::FAILURE); std::move(callback_).Run(RelationshipCheckResult::kFailure);
return; return;
} }
data_decoder::DataDecoder::ParseJsonIsolated( data_decoder::DataDecoder::ParseJsonIsolated(
*response_body, *response_body,
base::BindOnce(&DigitalAssetLinksHandler::OnJSONParseResult, base::BindOnce(&DigitalAssetLinksHandler::OnJSONParseResult,
weak_ptr_factory_.GetWeakPtr(), package, fingerprint, weak_ptr_factory_.GetWeakPtr(), std::move(relationship),
relationship)); std::move(fingerprint), std::move(target_values)));
url_loader_.reset(nullptr); url_loader_.reset(nullptr);
} }
void DigitalAssetLinksHandler::OnJSONParseResult( void DigitalAssetLinksHandler::OnJSONParseResult(
const std::string& package, std::string relationship,
const std::string& fingerprint, base::Optional<std::string> fingerprint,
const std::string& relationship, std::map<std::string, std::string> target_values,
data_decoder::DataDecoder::ValueOrError result) { data_decoder::DataDecoder::ValueOrError result) {
if (!result.value) { if (!result.value) {
AddMessageToConsole( AddMessageToConsole(
web_contents(), web_contents(),
"Digital Asset Links response parsing failed with message: " + "Digital Asset Links response parsing failed with message: " +
*result.error); *result.error);
std::move(callback_).Run(RelationshipCheckResult::FAILURE); std::move(callback_).Run(RelationshipCheckResult::kFailure);
return; return;
} }
auto& statement_list = *result.value; auto& statement_list = *result.value;
if (!statement_list.is_list()) { if (!statement_list.is_list()) {
std::move(callback_).Run(RelationshipCheckResult::FAILURE); std::move(callback_).Run(RelationshipCheckResult::kFailure);
AddMessageToConsole(web_contents(), "Statement List is not a list."); AddMessageToConsole(web_contents(), "Statement List is not a list.");
return; return;
} }
...@@ -200,33 +200,54 @@ void DigitalAssetLinksHandler::OnJSONParseResult( ...@@ -200,33 +200,54 @@ void DigitalAssetLinksHandler::OnJSONParseResult(
continue; continue;
} }
if (!StatementHasMatchingPackage(statement, package)) { if (fingerprint &&
failures.push_back("Statement failure matching package."); !StatementHasMatchingFingerprint(statement, *fingerprint)) {
failures.push_back("Statement failure matching fingerprint.");
continue; continue;
} }
if (!StatementHasMatchingFingerprint(statement, fingerprint)) { bool failed_target_check = false;
failures.push_back("Statement failure matching fingerprint."); for (const auto& key_value : target_values) {
continue; if (!StatementHasMatchingTargetValue(statement, key_value.first,
key_value.second)) {
failures.push_back("Statement failure matching " + key_value.first +
".");
failed_target_check = true;
break;
}
} }
if (failed_target_check)
continue;
std::move(callback_).Run(RelationshipCheckResult::SUCCESS); std::move(callback_).Run(RelationshipCheckResult::kSuccess);
return; return;
} }
for (const auto& failure_reason : failures) for (const auto& failure_reason : failures)
AddMessageToConsole(web_contents(), failure_reason); AddMessageToConsole(web_contents(), failure_reason);
std::move(callback_).Run(RelationshipCheckResult::FAILURE); std::move(callback_).Run(RelationshipCheckResult::kFailure);
} }
bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationship( bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationshipForAndroidApp(
RelationshipCheckResultCallback callback,
const std::string& web_domain, const std::string& web_domain,
const std::string& package, const std::string& relationship,
const std::string& fingerprint, const std::string& fingerprint,
const std::string& relationship) { const std::string& package,
// TODO(peconn): Propegate the use of url::Origin backwards to clients. RelationshipCheckResultCallback callback) {
// TODO(rayankans): Should we also check the namespace here?
return CheckDigitalAssetLinkRelationship(
web_domain, relationship, fingerprint, {{"package_name", package}},
std::move(callback));
}
bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationship(
const std::string& web_domain,
const std::string& relationship,
const base::Optional<std::string>& fingerprint,
const std::map<std::string, std::string>& target_values,
RelationshipCheckResultCallback callback) {
// TODO(peconn): Propagate the use of url::Origin backwards to clients.
GURL request_url = GetUrlForAssetLinks(url::Origin::Create(GURL(web_domain))); GURL request_url = GetUrlForAssetLinks(url::Origin::Create(GURL(web_domain)));
if (!request_url.is_valid()) if (!request_url.is_valid())
...@@ -272,8 +293,8 @@ bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationship( ...@@ -272,8 +293,8 @@ bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationship(
url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
shared_url_loader_factory_.get(), shared_url_loader_factory_.get(),
base::BindOnce(&DigitalAssetLinksHandler::OnURLLoadComplete, base::BindOnce(&DigitalAssetLinksHandler::OnURLLoadComplete,
weak_ptr_factory_.GetWeakPtr(), package, fingerprint, weak_ptr_factory_.GetWeakPtr(), relationship, fingerprint,
relationship)); target_values));
return true; return true;
} }
......
...@@ -5,8 +5,12 @@ ...@@ -5,8 +5,12 @@
#ifndef CHROME_BROWSER_ANDROID_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_ #ifndef CHROME_BROWSER_ANDROID_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_
#define CHROME_BROWSER_ANDROID_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_ #define CHROME_BROWSER_ANDROID_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_
#include <map>
#include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/values.h" #include "base/values.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "services/data_decoder/public/cpp/data_decoder.h" #include "services/data_decoder/public/cpp/data_decoder.h"
...@@ -22,9 +26,9 @@ extern const char kDigitalAssetLinksCheckResponseKeyLinked[]; ...@@ -22,9 +26,9 @@ extern const char kDigitalAssetLinksCheckResponseKeyLinked[];
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.browserservices // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.browserservices
enum class RelationshipCheckResult { enum class RelationshipCheckResult {
SUCCESS = 0, kSuccess = 0,
FAILURE, kFailure,
NO_CONNECTION kNoConnection,
}; };
using RelationshipCheckResultCallback = using RelationshipCheckResultCallback =
...@@ -39,9 +43,10 @@ using RelationshipCheckResultCallback = ...@@ -39,9 +43,10 @@ using RelationshipCheckResultCallback =
// The WebContents are used for logging console messages. // The WebContents are used for logging console messages.
class DigitalAssetLinksHandler : public content::WebContentsObserver { class DigitalAssetLinksHandler : public content::WebContentsObserver {
public: public:
DigitalAssetLinksHandler( // Optionally include |web_contents| for logging error messages to DevTools.
content::WebContents* web_contents, explicit DigitalAssetLinksHandler(
scoped_refptr<network::SharedURLLoaderFactory> factory); scoped_refptr<network::SharedURLLoaderFactory> factory,
content::WebContents* web_contents = nullptr);
~DigitalAssetLinksHandler() override; ~DigitalAssetLinksHandler() override;
// Checks whether the given "relationship" has been declared by the target // Checks whether the given "relationship" has been declared by the target
...@@ -55,23 +60,31 @@ class DigitalAssetLinksHandler : public content::WebContentsObserver { ...@@ -55,23 +60,31 @@ class DigitalAssetLinksHandler : public content::WebContentsObserver {
// See // See
// https://developers.google.com/digital-asset-links/reference/rest/v1/assetlinks/check // https://developers.google.com/digital-asset-links/reference/rest/v1/assetlinks/check
// for details. // for details.
bool CheckDigitalAssetLinkRelationship( bool CheckDigitalAssetLinkRelationshipForAndroidApp(
RelationshipCheckResultCallback callback,
const std::string& web_domain, const std::string& web_domain,
const std::string& package, const std::string& relationship,
const std::string& fingerprint, const std::string& fingerprint,
const std::string& relationship); const std::string& package,
RelationshipCheckResultCallback callback);
private: private:
void OnURLLoadComplete(const std::string& package, // Generic DAL verifier.
const std::string& fingerprint, bool CheckDigitalAssetLinkRelationship(
const std::string& relationship, const std::string& web_domain,
const std::string& relationship,
const base::Optional<std::string>& fingerprint,
const std::map<std::string, std::string>& target_values,
RelationshipCheckResultCallback callback);
void OnURLLoadComplete(std::string relationship,
base::Optional<std::string> fingerprint,
std::map<std::string, std::string> target_values,
std::unique_ptr<std::string> response_body); std::unique_ptr<std::string> response_body);
// Callback for the DataDecoder. // Callback for the DataDecoder.
void OnJSONParseResult(const std::string& package, void OnJSONParseResult(std::string relationship,
const std::string& fingerprint, base::Optional<std::string> fingerprint,
const std::string& relationship, std::map<std::string, std::string> target_values,
data_decoder::DataDecoder::ValueOrError result); data_decoder::DataDecoder::ValueOrError result);
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
......
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