0

[WebView] Remove content relationship verification code

Bug: 1454473
Change-Id: Ib25c2114f9b92e6160db86498f520f9276f46ecd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4608053
Reviewed-by: Bo Liu <boliu@chromium.org>
Commit-Queue: Susanne Westphal <swestphal@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Richard Coles <torne@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1158928}
This commit is contained in:
Susanne Westphal
2023-06-16 17:24:07 +00:00
committed by Chromium LUCI CQ
parent b99b22261f
commit 334d01268d
42 changed files with 3 additions and 1282 deletions

@ -472,7 +472,6 @@ generate_jni("browser_jni_headers") {
"java/src/org/chromium/android_webview/AwDevToolsServer.java",
"java/src/org/chromium/android_webview/AwFeatureMap.java",
"java/src/org/chromium/android_webview/AwHttpAuthHandler.java",
"java/src/org/chromium/android_webview/AwOriginVerificationSchedulerBridge.java",
"java/src/org/chromium/android_webview/AwPacProcessor.java",
"java/src/org/chromium/android_webview/AwPdfExporter.java",
"java/src/org/chromium/android_webview/AwProxyController.java",
@ -536,9 +535,6 @@ android_library("browser_java") {
"java/src/org/chromium/android_webview/AwKeyboardShortcuts.java",
"java/src/org/chromium/android_webview/AwLayoutSizer.java",
"java/src/org/chromium/android_webview/AwNetworkChangeNotifierRegistrationPolicy.java",
"java/src/org/chromium/android_webview/AwOriginVerificationScheduler.java",
"java/src/org/chromium/android_webview/AwOriginVerificationSchedulerBridge.java",
"java/src/org/chromium/android_webview/AwOriginVerifier.java",
"java/src/org/chromium/android_webview/AwPacProcessor.java",
"java/src/org/chromium/android_webview/AwPdfExporter.java",
"java/src/org/chromium/android_webview/AwPrintDocumentAdapter.java",
@ -554,7 +550,6 @@ android_library("browser_java") {
"java/src/org/chromium/android_webview/AwSupportLibIsomorphic.java",
"java/src/org/chromium/android_webview/AwThreadUtils.java",
"java/src/org/chromium/android_webview/AwTracingController.java",
"java/src/org/chromium/android_webview/AwVerificationResultStore.java",
"java/src/org/chromium/android_webview/AwViewAndroidDelegate.java",
"java/src/org/chromium/android_webview/AwViewMethods.java",
"java/src/org/chromium/android_webview/AwWebContentsDelegate.java",
@ -634,7 +629,6 @@ android_library("browser_java") {
"//components/background_task_scheduler:background_task_scheduler_task_ids_java",
"//components/component_updater/android:embedded_component_loader_java",
"//components/content_capture/android:java",
"//components/content_relationship_verification/android:java",
"//components/crash/android:handler_java",
"//components/crash/android:java",
"//components/embedder_support/android:util_java",
@ -657,7 +651,6 @@ android_library("browser_java") {
"//mojo/public/java:system_java",
"//mojo/public/java/system:system_impl_java",
"//net/android:net_java",
"//services/data_decoder/public/cpp/android:safe_json_java",
"//services/network/public/mojom:mojom_java",
"//services/network/public/mojom:url_loader_base_java",
"//third_party/android_deps:protobuf_lite_runtime_java",

@ -121,10 +121,6 @@ source_set("browser") {
"component_updater/registration.h",
"component_updater/trust_token_key_commitments_component_loader.cc",
"component_updater/trust_token_key_commitments_component_loader.h",
"content_relationship_verification/aw_origin_verification_scheduler_bridge.cc",
"content_relationship_verification/aw_origin_verification_scheduler_bridge.h",
"content_relationship_verification/browser_url_loader_throttle.cc",
"content_relationship_verification/browser_url_loader_throttle.h",
"cookie_manager.cc",
"cookie_manager.h",
"enterprise_authentication_app_link_policy_handler.cc",
@ -238,7 +234,6 @@ source_set("browser") {
"//components/url_matcher",
# Called via JNI in CrashpadMain
"//components/content_relationship_verification",
"//components/crash/android:crashpad_main",
"//components/crash/content/browser",
"//components/crash/core/app",

@ -15,7 +15,6 @@ include_rules = [
"+components/cdm/browser",
"+components/component_updater/android",
"+components/component_updater/installer_policies",
"+components/content_relationship_verification",
"+components/crash/content/browser",
"+components/crash/core",
"+components/download/public/common",
@ -112,7 +111,6 @@ include_rules = [
"+third_party/blink/public/common/storage_key/storage_key.h",
"+third_party/blink/public/common/user_agent/user_agent_metadata.h",
"+third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h",
"+third_party/blink/public/platform/resource_request_blocked_reason.h",
"+third_party/crashpad/crashpad/client",
"+third_party/crashpad/crashpad/util",
"+third_party/zlib/google/compression_utils.h",

@ -24,7 +24,6 @@
#include "android_webview/browser/aw_settings.h"
#include "android_webview/browser/aw_speech_recognition_manager_delegate.h"
#include "android_webview/browser/aw_web_contents_view_delegate.h"
#include "android_webview/browser/content_relationship_verification/aw_origin_verification_scheduler_bridge.h"
#include "android_webview/browser/cookie_manager.h"
#include "android_webview/browser/network_service/aw_proxy_config_monitor.h"
#include "android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h"
@ -596,19 +595,6 @@ AwContentBrowserClient::CreateURLLoaderThrottles(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
content::WebContents* web_contents = wc_getter.Run();
AwSettings* aw_settings = AwSettings::FromWebContents(web_contents);
if (request.is_outermost_main_frame &&
((aw_settings && aw_settings->GetRestrictSensitiveWebContentEnabled()) ||
base::FeatureList::IsEnabled(
features::kWebViewRestrictSensitiveContent))) {
auto* origin_verification_bridge =
AwOriginVerificationSchedulerBridge::GetInstance();
result.push_back(
BrowserURLLoaderThrottle::Create(origin_verification_bridge));
}
result.push_back(safe_browsing::BrowserURLLoaderThrottle::Create(
base::BindOnce(
[](AwContentBrowserClient* client) {

@ -638,17 +638,6 @@ AwSettings::UpdateXRequestedWithAllowListOriginMatcher(
return base::android::ToJavaArrayOfStrings(env, bad_rules);
}
void AwSettings::SetRestrictSensitiveWebContentEnabled(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean enabled) {
restrict_sensitive_web_content_enabled_ = enabled;
}
bool AwSettings::GetRestrictSensitiveWebContentEnabled() {
return restrict_sensitive_web_content_enabled();
}
scoped_refptr<AwContentsOriginMatcher> AwSettings::xrw_allowlist_matcher() {
return xrw_allowlist_matcher_;
}

@ -127,15 +127,6 @@ class AwSettings : public content::WebContentsObserver {
return enterprise_authentication_app_link_policy_enabled_;
}
void SetRestrictSensitiveWebContentEnabled(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean enabled);
bool GetRestrictSensitiveWebContentEnabled();
inline bool restrict_sensitive_web_content_enabled() {
return restrict_sensitive_web_content_enabled_;
}
base::android::ScopedJavaLocalRef<jobjectArray>
UpdateXRequestedWithAllowListOriginMatcher(
JNIEnv* env,
@ -159,7 +150,6 @@ class AwSettings : public content::WebContentsObserver {
// TODO(b/222053757,ayushsha): Change this policy to be by
// default false from next Android version(Maybe Android U).
bool enterprise_authentication_app_link_policy_enabled_{true};
bool restrict_sensitive_web_content_enabled_{false};
MixedContentMode mixed_content_mode_;
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher_;

@ -1,4 +0,0 @@
file://components/content_relationship_verification/OWNERS
rayankans@chromium.org
swestphal@chromium.org

@ -1,44 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/browser/content_relationship_verification/aw_origin_verification_scheduler_bridge.h"
#include <string>
#include "android_webview/browser_jni_headers/AwOriginVerificationSchedulerBridge_jni.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/no_destructor.h"
namespace android_webview {
// static
AwOriginVerificationSchedulerBridge*
AwOriginVerificationSchedulerBridge::GetInstance() {
static base::NoDestructor<AwOriginVerificationSchedulerBridge> instance;
return instance.get();
}
void AwOriginVerificationSchedulerBridge::Verify(
std::string url,
OriginVerifierCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
JNIEnv* env = base::android::AttachCurrentThread();
intptr_t callback_id = reinterpret_cast<intptr_t>(
new OriginVerifierCallback(std::move(callback)));
auto j_url = base::android::ConvertUTF8ToJavaString(env, url);
Java_AwOriginVerificationSchedulerBridge_verify(env, j_url, callback_id);
}
static void JNI_AwOriginVerificationSchedulerBridge_OnVerificationResult(
JNIEnv* env,
jlong callback_id,
jboolean verified) {
std::unique_ptr<OriginVerifierCallback> cb(
reinterpret_cast<OriginVerifierCallback*>(callback_id));
std::move(*cb).Run(verified);
}
} // namespace android_webview

@ -1,38 +0,0 @@
// Copyright 2023 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_CONTENT_RELATIONSHIP_VERIFICATION_AW_ORIGIN_VERIFICATION_SCHEDULER_BRIDGE_H_
#define ANDROID_WEBVIEW_BROWSER_CONTENT_RELATIONSHIP_VERIFICATION_AW_ORIGIN_VERIFICATION_SCHEDULER_BRIDGE_H_
#include "base/functional/callback.h"
#include "base/no_destructor.h"
#include "android_webview/browser/content_relationship_verification/browser_url_loader_throttle.h"
namespace android_webview {
using OriginVerifierCallback = base::OnceCallback<void(bool /*verified*/)>;
// Lifetime: Singleton
class AwOriginVerificationSchedulerBridge
: public BrowserURLLoaderThrottle::OriginVerificationSchedulerBridge {
public:
static AwOriginVerificationSchedulerBridge* GetInstance();
AwOriginVerificationSchedulerBridge(
const AwOriginVerificationSchedulerBridge&) = delete;
AwOriginVerificationSchedulerBridge& operator=(
const AwOriginVerificationSchedulerBridge&) = delete;
void Verify(std::string url, OriginVerifierCallback callback) override;
private:
AwOriginVerificationSchedulerBridge() = default;
~AwOriginVerificationSchedulerBridge() override = default;
friend class base::NoDestructor<AwOriginVerificationSchedulerBridge>;
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_CONTENT_RELATIONSHIP_VERIFICATION_AW_ORIGIN_VERIFICATION_SCHEDULER_BRIDGE_H_

@ -1,141 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/browser/content_relationship_verification/browser_url_loader_throttle.h"
#include "base/android/build_info.h"
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/trace_event/trace_event.h"
#include "components/content_relationship_verification/content_relationship_verification_constants.h"
#include "components/content_relationship_verification/response_header_verifier.h"
#include "content/public/browser/browser_thread.h"
#include "net/log/net_log_event_type.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
using content_relationship_verification::ResponseHeaderVerificationResult;
namespace android_webview {
BrowserURLLoaderThrottle::OriginVerificationSchedulerBridge::
OriginVerificationSchedulerBridge() = default;
BrowserURLLoaderThrottle::OriginVerificationSchedulerBridge::
~OriginVerificationSchedulerBridge() = default;
// static
std::unique_ptr<BrowserURLLoaderThrottle> BrowserURLLoaderThrottle::Create(
OriginVerificationSchedulerBridge* bridge) {
return base::WrapUnique<BrowserURLLoaderThrottle>(
new BrowserURLLoaderThrottle(bridge));
}
BrowserURLLoaderThrottle::BrowserURLLoaderThrottle(
OriginVerificationSchedulerBridge* bridge)
: bridge_(bridge) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
BrowserURLLoaderThrottle::~BrowserURLLoaderThrottle() = default;
bool BrowserURLLoaderThrottle::VerifyHeader(
const network::mojom::URLResponseHead& response_head) {
std::string header_value;
response_head.headers->GetNormalizedHeader(
content_relationship_verification::kEmbedderAncestorHeader,
&header_value);
ResponseHeaderVerificationResult header_verification_result =
content_relationship_verification::ResponseHeaderVerifier::Verify(
base::android::BuildInfo::GetInstance()->host_package_name(),
header_value);
if (header_verification_result == ResponseHeaderVerificationResult::kAllow) {
return true;
} else if (header_verification_result ==
ResponseHeaderVerificationResult::kMissing) {
// TODO(crbug.com/1376958): Check for permission.
return true;
}
return false;
}
void BrowserURLLoaderThrottle::WillStartRequest(
network::ResourceRequest* request,
bool* defer) {
url_ = request->url;
}
void BrowserURLLoaderThrottle::WillRedirectRequest(
net::RedirectInfo* redirect_info,
const network::mojom::URLResponseHead& response_head,
bool* defer,
std::vector<std::string>* to_be_removed_request_headers,
net::HttpRequestHeaders* modified_request_headers,
net::HttpRequestHeaders* modified_cors_exempt_request_headers) {
DCHECK(delegate_);
GURL originating_url = url_;
url_ = redirect_info->new_url;
if (VerifyHeader(response_head)) {
return;
}
*defer = true;
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&OriginVerificationSchedulerBridge::Verify, base::Unretained(bridge_),
url_.spec(),
base::BindOnce(&BrowserURLLoaderThrottle::OnDalVerificationComplete,
weak_factory_.GetWeakPtr(), originating_url.spec())));
}
void BrowserURLLoaderThrottle::WillProcessResponse(
const GURL& response_url,
network::mojom::URLResponseHead* response_head,
bool* defer) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(delegate_);
if (VerifyHeader(*response_head)) {
return;
}
*defer = true;
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&OriginVerificationSchedulerBridge::Verify, base::Unretained(bridge_),
response_url.spec(),
base::BindOnce(&BrowserURLLoaderThrottle::OnDalVerificationComplete,
weak_factory_.GetWeakPtr(), response_url.spec())));
}
void BrowserURLLoaderThrottle::OnDalVerificationComplete(std::string url,
bool dal_verified) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(delegate_);
if (dal_verified) {
delegate_->Resume();
return;
}
delegate_->CancelWithExtendedError(
content_relationship_verification::
kNetErrorCodeForContentRelationshipVerification,
static_cast<int>(content_relationship_verification::kExtendedErrorReason),
content_relationship_verification::kCustomCancelReasonForURLLoader);
}
const char* BrowserURLLoaderThrottle::NameForLoggingWillProcessResponse() {
return "DigitalAssetLinksBrowserThrottle";
}
} // namespace android_webview

@ -1,92 +0,0 @@
// Copyright 2023 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_CONTENT_RELATIONSHIP_VERIFICATION_BROWSER_URL_LOADER_THROTTLE_H_
#define ANDROID_WEBVIEW_BROWSER_CONTENT_RELATIONSHIP_VERIFICATION_BROWSER_URL_LOADER_THROTTLE_H_
#include <memory>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "components/content_relationship_verification/response_header_verifier.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "url/gurl.h"
namespace android_webview {
// BrowserURLLoaderThrottle is used in the browser process to perform a
// digital asset links verification to determine whether a URL and also its
// redirect URLs are considered first party content and will be loaded.
//
// This throttle never defers starting the URL request or following redirects.
// If any of the checks for the original URL and redirect chain are not complete
// by the time the response headers are available, the request is deferred
// until all the checks are done. It cancels the load if any URLs turn out to
// be bad.
//
// Lifetime: Temporary. Created and destroyed for every URL request.
class BrowserURLLoaderThrottle : public blink::URLLoaderThrottle {
public:
class OriginVerificationSchedulerBridge {
public:
using OriginVerifierCallback = base::OnceCallback<void(bool /*verified*/)>;
OriginVerificationSchedulerBridge();
virtual ~OriginVerificationSchedulerBridge();
OriginVerificationSchedulerBridge(
const OriginVerificationSchedulerBridge&) = delete;
OriginVerificationSchedulerBridge& operator=(
const OriginVerificationSchedulerBridge&) = delete;
virtual void Verify(std::string url, OriginVerifierCallback callback) = 0;
};
static std::unique_ptr<BrowserURLLoaderThrottle> Create(
OriginVerificationSchedulerBridge* bridge);
BrowserURLLoaderThrottle(const BrowserURLLoaderThrottle&) = delete;
BrowserURLLoaderThrottle& operator=(const BrowserURLLoaderThrottle&) = delete;
~BrowserURLLoaderThrottle() override;
// blink::URLLoaderThrottle implementation.
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override;
void WillRedirectRequest(
net::RedirectInfo* redirect_info,
const network::mojom::URLResponseHead& response_head,
bool* defer,
std::vector<std::string>* to_be_removed_request_headers,
net::HttpRequestHeaders* modified_request_headers,
net::HttpRequestHeaders* modified_cors_exempt_request_headers) override;
void WillProcessResponse(const GURL& response_url,
network::mojom::URLResponseHead* response_head,
bool* defer) override;
const char* NameForLoggingWillProcessResponse() override;
private:
explicit BrowserURLLoaderThrottle(OriginVerificationSchedulerBridge* bridge);
void OnDalVerificationComplete(std::string url, bool dal_verified);
bool VerifyHeader(const network::mojom::URLResponseHead& response_head);
raw_ptr<OriginVerificationSchedulerBridge> bridge_;
GURL url_;
base::WeakPtrFactory<BrowserURLLoaderThrottle> weak_factory_{this};
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_CONTENT_RELATIONSHIP_VERIFICATION_BROWSER_URL_LOADER_THROTTLE_H_

@ -26,10 +26,8 @@ import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwContentsStatics;
import org.chromium.android_webview.AwCookieManager;
import org.chromium.android_webview.AwDarkMode;
import org.chromium.android_webview.AwFeatureMap;
import org.chromium.android_webview.AwLocaleConfig;
import org.chromium.android_webview.AwNetworkChangeNotifierRegistrationPolicy;
import org.chromium.android_webview.AwOriginVerificationScheduler;
import org.chromium.android_webview.AwProxyController;
import org.chromium.android_webview.AwServiceWorkerController;
import org.chromium.android_webview.AwThreadUtils;
@ -38,7 +36,6 @@ import org.chromium.android_webview.HttpAuthDatabase;
import org.chromium.android_webview.ProductConfig;
import org.chromium.android_webview.R;
import org.chromium.android_webview.WebViewChromiumRunQueue;
import org.chromium.android_webview.common.AwFeatures;
import org.chromium.android_webview.common.AwResource;
import org.chromium.android_webview.common.AwSwitches;
import org.chromium.android_webview.gfx.AwDrawFnImpl;
@ -234,9 +231,6 @@ public class WebViewChromiumAwInit {
mFactory, awBrowserContext.getGeolocationPermissions());
mWebStorage =
new WebStorageAdapter(mFactory, mBrowserContext.getQuotaManagerBridge());
if (AwFeatureMap.isEnabled(AwFeatures.WEBVIEW_RESTRICT_SENSITIVE_CONTENT)) {
AwOriginVerificationScheduler.initAndScheduleAll(null);
}
mAwTracingController = getTracingController();
mServiceWorkerController = awBrowserContext.getServiceWorkerController();
mAwProxyController = new AwProxyController();

@ -1,7 +1,6 @@
include_rules = [
"+components/android_autofill",
"+components/autofill/android/java",
"+components/content_relationship_verification/android/java",
"+components/embedder_support/android/java",
"+components/embedder_support/android/metrics/java",
"+components/navigation_interception/android/java",

@ -1,82 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview;
import android.content.Context;
import androidx.annotation.Nullable;
import org.chromium.android_webview.common.Lifetime;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.components.content_relationship_verification.OriginVerificationScheduler;
import org.chromium.components.content_relationship_verification.OriginVerifier;
import org.chromium.components.content_relationship_verification.OriginVerifierHelper;
import org.chromium.components.embedder_support.util.Origin;
import java.util.Set;
/**
* Singleton.
* AwOriginVerificationScheduler provides a WebView specific implementation of {@link
* OriginVerificationScheduler}.
*
* Call {@link AwOriginVerificationScheduler#init} to initialize the statement list and call
* {@link AwOriginVerificationScheduler#validate} to perform a validation.
*/
@Lifetime.Singleton
public class AwOriginVerificationScheduler extends OriginVerificationScheduler {
private static final String TAG = "AwOriginVerification";
/** Lock on creation of sInstance. */
private static final Object sLock = new Object();
private static AwOriginVerificationScheduler sInstance;
private AwOriginVerificationScheduler(
AwOriginVerifier originVerifier, Set<Origin> pendingOrigins) {
super(originVerifier, pendingOrigins);
}
/**
* Initializes the AwOriginVerificationScheduler.
* This should be called exactly only once as it parses the AndroidManifest and statement list.
*
* @param packageName the package name of the host application.
* @param browserContext the browserContext to use for the simpleUrlLoader to download the asset
* links file.
* @param context a context associated with an Activity/Service to load resources.
*/
public static void init(String packageName, AwBrowserContext browserContext, Context context) {
ThreadUtils.assertOnUiThread();
synchronized (sLock) {
assert sInstance
== null
: "`init(String packageName, Context context)` must only be called once";
sInstance = new AwOriginVerificationScheduler(
new AwOriginVerifier(packageName, OriginVerifier.HANDLE_ALL_URLS,
browserContext, AwVerificationResultStore.getInstance()),
OriginVerifierHelper.getClaimedOriginsFromManifest(packageName, context));
}
}
public static void initAndScheduleAll(@Nullable Callback<Boolean> callback) {
synchronized (sLock) {
if (sInstance == null) {
Context context = ContextUtils.getApplicationContext();
init(context.getPackageName(), AwBrowserContext.getDefault(), context);
}
sInstance.scheduleAllPendingVerifications(callback);
}
}
public static AwOriginVerificationScheduler getInstance() {
synchronized (sLock) {
return sInstance;
}
}
}

@ -1,27 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
@JNINamespace("android_webview")
class AwOriginVerificationSchedulerBridge {
private AwOriginVerificationSchedulerBridge() {}
@CalledByNative
static void verify(String url, long nativeCallbackPtr) {
AwOriginVerificationScheduler.getInstance().verify(url, (verified) -> {
AwOriginVerificationSchedulerBridgeJni.get().onVerificationResult(
nativeCallbackPtr, verified);
});
}
@NativeMethods
interface Natives {
void onVerificationResult(long callbackPtr, boolean verified);
}
}

@ -1,65 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview;
import androidx.annotation.Nullable;
import org.chromium.android_webview.common.Lifetime;
import org.chromium.components.content_relationship_verification.OriginVerifier;
import org.chromium.components.content_relationship_verification.Relationship;
import org.chromium.components.embedder_support.util.Origin;
import java.util.List;
/**
* AwOriginVerifier performs OriginVerifications for WebView.
*/
@Lifetime.Singleton
public class AwOriginVerifier extends OriginVerifier {
public AwOriginVerifier(String packageName, String relationship,
AwBrowserContext browserContext,
@Nullable AwVerificationResultStore verificationResultStore) {
super(packageName, relationship, null, browserContext, verificationResultStore);
}
@Override
public boolean isAllowlisted(String packageName, Origin origin, String relation) {
return false;
}
@Override
public boolean wasPreviouslyVerified(Origin origin) {
return wasPreviouslyVerified(mPackageName, mSignatureFingerprints, origin, mRelation);
}
/**
* Returns whether an origin is first-party relative to a given package name.
*
* This only returns data from previously cached relations, and does not trigger an asynchronous
* validation.
*
* @param packageName The package name.
* @param signatureFingerprint The signatures of the package.
* @param origin The origin to verify.
* @param relation The Digital Asset Links relation to verify for.
*/
private static boolean wasPreviouslyVerified(String packageName,
List<String> signatureFingerprints, Origin origin, String relation) {
AwVerificationResultStore resultStore = AwVerificationResultStore.getInstance();
return resultStore.shouldOverride(packageName, origin, relation)
|| resultStore.isRelationshipSaved(
new Relationship(packageName, signatureFingerprints, origin, relation));
}
@Override
public void recordResultMetrics(OriginVerifier.VerifierResult result) {
// TODO(crbug.com/1376958): Implement UMA logging.
}
@Override
public void recordVerificationTimeMetrics(long duration, boolean online) {
// TODO(crbug.com/1376958): Implement UMA logging.
}
}

@ -2015,22 +2015,6 @@ public class AwSettings {
}
}
/**
* Enable sensitive web content restrictions per WebView.
*/
public void enableRestrictSensitiveWebContent() {
synchronized (mAwSettingsLock) {
mEventHandler.runOnUiThreadBlockingAndLocked(() -> {
assert Thread.holdsLock(mAwSettingsLock);
AwOriginVerificationScheduler.initAndScheduleAll(null);
if (mNativeAwSettings != 0) {
AwSettingsJni.get().setRestrictSensitiveWebContentEnabled(
mNativeAwSettings, AwSettings.this, true);
}
});
}
}
@NativeMethods
interface Natives {
long init(AwSettings caller, WebContents webContents);
@ -2056,7 +2040,5 @@ public class AwSettings {
boolean getEnterpriseAuthenticationAppLinkPolicyEnabled(
long nativeAwSettings, AwSettings caller);
String[] updateXRequestedWithAllowListOriginMatcher(long nativeAwSettings, String[] rules);
void setRestrictSensitiveWebContentEnabled(
long nativeAwSettings, AwSettings caller, boolean enabled);
}
}

@ -1,38 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview;
import org.chromium.android_webview.common.Lifetime;
import org.chromium.components.content_relationship_verification.VerificationResultStore;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* AwVerificationResultStore stores relationships in a local variable.
*/
@Lifetime.Singleton
public class AwVerificationResultStore extends VerificationResultStore {
private static final AwVerificationResultStore sInstance = new AwVerificationResultStore();
private Set<String> mVerifiedOrigins = Collections.synchronizedSet(new HashSet<>());
private AwVerificationResultStore() {}
public static AwVerificationResultStore getInstance() {
return sInstance;
}
@Override
protected Set<String> getRelationships() {
return mVerifiedOrigins;
}
@Override
protected void setRelationships(Set<String> relationships) {
mVerifiedOrigins = relationships;
}
}

@ -366,8 +366,6 @@ public final class ProductionSupportedFlagList {
Flag.baseFeature(AwFeatures.WEBVIEW_UMA_UPLOAD_QUALITY_OF_SERVICE_SET_TO_DEFAULT,
"If enabled, the frequency to upload UMA is increased."),
Flag.baseFeature("CanvasColorCache"),
Flag.baseFeature(AwFeatures.WEBVIEW_RESTRICT_SENSITIVE_CONTENT,
"Controls whether access to sensitive web content should be restricted."),
Flag.baseFeature(BlinkFeatures.KEYBOARD_FOCUSABLE_SCROLLERS,
"When enabled, can focus on a scroller element using the keyboard."),
Flag.commandLine(AwSwitches.WEBVIEW_ENABLE_TRUST_TOKENS_COMPONENT,

@ -1,282 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.test;
import android.content.Context;
import android.util.Pair;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwOriginVerificationScheduler;
import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.base.PackageUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.components.embedder_support.util.Origin;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.net.test.util.TestWebServer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
/**
* Tests for the restricting access sensitive web content.
*/
@RunWith(AwJUnit4ClassRunner.class)
public class AwRestrictSensitiveContentTest {
@Rule
public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
private static class OnProgressChangedClient extends TestAwContentsClient {
List<Integer> mProgresses = new ArrayList<Integer>();
@Override
public void onProgressChanged(int progress) {
super.onProgressChanged(progress);
mProgresses.add(Integer.valueOf(progress));
if (progress == 100 && mCallbackHelper.getCallCount() == 0) {
mCallbackHelper.notifyCalled();
}
}
public void waitForFullLoad() throws TimeoutException {
mCallbackHelper.waitForFirst();
}
private CallbackHelper mCallbackHelper = new CallbackHelper();
}
private TestWebServer mWebServer;
private OnProgressChangedClient mContentsClient;
private AwTestContainerView mTestContainerView;
private AwContents mAwContents;
@Before
public void setUp() throws Exception {
mContentsClient = new OnProgressChangedClient();
mTestContainerView = mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient);
mAwContents = mTestContainerView.getAwContents();
mWebServer = TestWebServer.start();
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
TestThreadUtils.runOnUiThreadBlocking(
()
-> AwOriginVerificationScheduler.init(context.getPackageName(),
mActivityTestRule.getAwBrowserContext(), context));
}
@After
public void tearDown() {
mWebServer.shutdown();
}
private String addPageToTestServer(TestWebServer webServer, String httpPath, String html) {
return addPageToTestServer(
webServer, httpPath, html, new ArrayList<Pair<String, String>>());
}
private String addPageToTestServer(TestWebServer webServer, String httpPath, String html,
List<Pair<String, String>> additionalHeaders) {
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("Content-Type", "text/html"));
headers.add(Pair.create("Cache-Control", "no-store"));
headers.addAll(additionalHeaders);
return webServer.setResponse(httpPath, html, headers);
}
private String addAboutPageToTestServer(
TestWebServer webServer, List<Pair<String, String>> additionalHeaders) {
return addPageToTestServer(webServer, "/" + CommonResources.ABOUT_FILENAME,
CommonResources.ABOUT_HTML, additionalHeaders);
}
private String addAssetListToTestServer(TestWebServer webServer, String fingerprint) {
return addPageToTestServer(webServer, CommonResources.ASSET_LINKS_PATH,
CommonResources.makeAssetFile(fingerprint));
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"disable-features=WebViewRestrictSensitiveContent"})
public void disablingFeatureDoesBlockOrRunValidation() throws Throwable {
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("X-Embedder-Ancestors", "none"));
final String aboutPageUrl = addAboutPageToTestServer(mWebServer, headers);
AwOriginVerificationScheduler scheduler = AwOriginVerificationScheduler.getInstance();
scheduler.addPendingOriginForTesting(Origin.create(aboutPageUrl));
Assert.assertEquals(2, scheduler.getPendingOriginsForTesting().size());
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mTestContainerView.getAwContents().loadUrl(aboutPageUrl, null));
mContentsClient.waitForFullLoad();
Assert.assertEquals(CommonResources.ABOUT_TITLE, mAwContents.getTitle());
Assert.assertEquals(2, scheduler.getPendingOriginsForTesting().size());
Assert.assertTrue(
scheduler.getPendingOriginsForTesting().contains(Origin.create(aboutPageUrl)));
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"enable-features=WebViewRestrictSensitiveContent"})
public void testInitAndScheduleAll() throws Throwable {
CountDownLatch countVerifiedLatch = new CountDownLatch(1);
mActivityTestRule.runOnUiThread(() -> {
AwOriginVerificationScheduler.initAndScheduleAll(
(res) -> { countVerifiedLatch.countDown(); });
});
countVerifiedLatch.await();
AwOriginVerificationScheduler scheduler = AwOriginVerificationScheduler.getInstance();
Assert.assertNotNull(scheduler);
Set<Origin> pendingOrigins = scheduler.getPendingOriginsForTesting();
Assert.assertEquals(0, pendingOrigins.size());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"enable-features=WebViewRestrictSensitiveContent"})
public void doesNotBlockDALVerifiedContent() throws Throwable {
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("X-Embedder-Ancestors", "none"));
final String aboutPageUrl = addAboutPageToTestServer(mWebServer, headers);
List<String> mSignatureFingerprints =
PackageUtils.getCertificateSHA256FingerprintForPackage(context.getPackageName());
final String assetLinksUrl =
addAssetListToTestServer(mWebServer, mSignatureFingerprints.get(0));
AwOriginVerificationScheduler scheduler = AwOriginVerificationScheduler.getInstance();
AwOriginVerificationScheduler.getInstance().addPendingOriginForTesting(
Origin.create(aboutPageUrl));
Set<Origin> pendingOrigins = scheduler.getPendingOriginsForTesting();
Assert.assertEquals(2, pendingOrigins.size());
Assert.assertTrue(pendingOrigins.contains(Origin.create(aboutPageUrl)));
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mTestContainerView.getAwContents().loadUrl(aboutPageUrl, null));
mContentsClient.waitForFullLoad();
Set<Origin> pendingOriginsAfterRequest = scheduler.getPendingOriginsForTesting();
Assert.assertEquals(1, pendingOriginsAfterRequest.size());
Assert.assertFalse(pendingOriginsAfterRequest.contains(Origin.create(aboutPageUrl)));
Assert.assertEquals(CommonResources.ABOUT_TITLE, mAwContents.getTitle());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"enable-features=WebViewRestrictSensitiveContent"})
public void doesNotBlockHeaderVerifiedContent() throws Throwable {
final String webpageNotAvailable = "Webpage not available";
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("X-Embedder-Ancestors", "*"));
final String aboutPageUrl = addAboutPageToTestServer(mWebServer, headers);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mTestContainerView.getAwContents().loadUrl(aboutPageUrl, null));
mContentsClient.waitForFullLoad();
Assert.assertEquals(CommonResources.ABOUT_TITLE, mAwContents.getTitle());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"enable-features=WebViewRestrictSensitiveContent"})
public void headerCanBlockRedirects() throws Throwable {
final String webpageNotAvailable = "Webpage not available";
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("X-Embedder-Ancestors", "*"));
final String aboutPageUrl = addAboutPageToTestServer(mWebServer, headers);
String redirect_path = "/redirect.html";
List<Pair<String, String>> blocking_headers = new ArrayList<Pair<String, String>>();
blocking_headers.add(Pair.create("X-Embedder-Ancestors", "none"));
final String initialUrl =
mWebServer.setRedirect(redirect_path, aboutPageUrl, blocking_headers);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mTestContainerView.getAwContents().loadUrl(initialUrl, null));
mContentsClient.waitForFullLoad();
Assert.assertEquals(webpageNotAvailable, mAwContents.getTitle());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"enable-features=WebViewRestrictSensitiveContent"})
public void allowDALVerifiedRedirects() throws Throwable {
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("X-Embedder-Ancestors", "*"));
final String aboutPageUrl = addAboutPageToTestServer(mWebServer, headers);
List<String> mSignatureFingerprints =
PackageUtils.getCertificateSHA256FingerprintForPackage(context.getPackageName());
final String assetLinksUrl =
addAssetListToTestServer(mWebServer, mSignatureFingerprints.get(0));
String redirect_path = "/redirect.html";
List<Pair<String, String>> blocking_headers = new ArrayList<Pair<String, String>>();
blocking_headers.add(Pair.create("X-Embedder-Ancestors", "none"));
final String initialUrl =
mWebServer.setRedirect(redirect_path, aboutPageUrl, blocking_headers);
AwOriginVerificationScheduler.getInstance().addPendingOriginForTesting(
Origin.create(initialUrl));
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mTestContainerView.getAwContents().loadUrl(initialUrl, null));
mContentsClient.waitForFullLoad();
Assert.assertEquals(CommonResources.ABOUT_TITLE, mAwContents.getTitle());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add({"enable-features=WebViewRestrictSensitiveContent"})
public void doesBlockForNotVerifiedContent() throws Throwable {
final String webpageNotAvailable = "Webpage not available";
List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
headers.add(Pair.create("X-Embedder-Ancestors", "none"));
final String aboutPageUrl = addAboutPageToTestServer(mWebServer, headers);
Set<Origin> pendingOrigins =
AwOriginVerificationScheduler.getInstance().getPendingOriginsForTesting();
Assert.assertFalse(pendingOrigins.contains(Origin.create(aboutPageUrl)));
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mTestContainerView.getAwContents().loadUrl(aboutPageUrl, null));
mContentsClient.waitForFullLoad();
Assert.assertEquals(webpageNotAvailable, mAwContents.getTitle());
}
}

@ -1,4 +0,0 @@
include_rules = [
"+components/content_relationship_verification/android/java",
"+content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java",
]

@ -1,147 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.robolectric;
import static org.robolectric.Shadows.shadowOf;
import android.os.Process;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;
import org.robolectric.annotation.Config;
import org.chromium.android_webview.AwBrowserContext;
import org.chromium.android_webview.AwOriginVerifier;
import org.chromium.android_webview.AwVerificationResultStore;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.JniMocker;
import org.chromium.components.content_relationship_verification.OriginVerifier;
import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener;
import org.chromium.components.content_relationship_verification.OriginVerifierJni;
import org.chromium.components.content_relationship_verification.OriginVerifierUnitTestSupport;
import org.chromium.components.content_relationship_verification.RelationshipCheckResult;
import org.chromium.components.embedder_support.util.Origin;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.concurrent.CountDownLatch;
/**
* JUnit tests for AwOriginVerifier.
*/
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class AwOriginVerifierTest {
public static final String TEST_BATCH_NAME = "aw_origin_verifier";
private static final String PACKAGE_NAME = "org.chromium.com";
private int mUid = Process.myUid();
private Origin mHttpsOrigin = Origin.create("https://www.example.com");
private AwOriginVerifier mAwVerifier;
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.WARN);
@Rule
public JniMocker mJniMocker = new JniMocker();
@Mock
private OriginVerifier.Natives mMockOriginVerifierJni;
private static class TestOriginVerificationListener implements OriginVerificationListener {
private CountDownLatch mLatch;
private boolean mVerified;
TestOriginVerificationListener(CountDownLatch latch) {
mLatch = latch;
}
@Override
public void onOriginVerified(
String packageName, Origin origin, boolean verified, Boolean online) {
mVerified = verified;
mLatch.countDown();
}
public boolean isVerified() {
return mVerified;
}
}
@Before
public void setUp() throws Exception {
OriginVerifierUnitTestSupport.registerPackageWithSignature(
shadowOf(ApplicationProvider.getApplicationContext().getPackageManager()),
PACKAGE_NAME, mUid);
mJniMocker.mock(OriginVerifierJni.TEST_HOOKS, mMockOriginVerifierJni);
Mockito.doAnswer(args -> { return 100L; })
.when(mMockOriginVerifierJni)
.init(Mockito.any(), Mockito.any());
mJniMocker.mock(OriginVerifierJni.TEST_HOOKS, mMockOriginVerifierJni);
Mockito.doAnswer(args -> {
String[] fingerprints = args.getArgument(3);
if (fingerprints == null) {
mAwVerifier.onOriginVerificationResult(
args.getArgument(4), RelationshipCheckResult.FAILURE);
return false;
}
// Ensure parsing of signature works.
assert fingerprints.length == 1;
assert fingerprints[0] != null;
mAwVerifier.onOriginVerificationResult(
args.getArgument(4), RelationshipCheckResult.SUCCESS);
return true;
})
.when(mMockOriginVerifierJni)
.verifyOrigin(ArgumentMatchers.anyLong(), Mockito.any(),
ArgumentMatchers.anyString(), Mockito.any(), ArgumentMatchers.anyString(),
ArgumentMatchers.anyString(), Mockito.any());
}
@Test
public void testVerification() throws Exception {
mAwVerifier = new AwOriginVerifier(PACKAGE_NAME,
"delegate_permission/common.handle_all_urls", Mockito.mock(AwBrowserContext.class),
AwVerificationResultStore.getInstance());
CountDownLatch verificationResultLatch = new CountDownLatch(1);
TestOriginVerificationListener resultListener =
new TestOriginVerificationListener(verificationResultLatch);
TestThreadUtils.runOnUiThreadBlocking(
() -> mAwVerifier.start(resultListener, mHttpsOrigin));
verificationResultLatch.await();
Assert.assertTrue(resultListener.isVerified());
}
@Test
public void testVerificationResultGetsCached() throws Exception {
AwVerificationResultStore store = AwVerificationResultStore.getInstance();
mAwVerifier =
new AwOriginVerifier(PACKAGE_NAME, "delegate_permission/common.handle_all_urls",
Mockito.mock(AwBrowserContext.class), store);
CountDownLatch verificationResultLatch = new CountDownLatch(1);
TestOriginVerificationListener resultListener =
new TestOriginVerificationListener(verificationResultLatch);
TestThreadUtils.runOnUiThreadBlocking(
() -> mAwVerifier.start(resultListener, mHttpsOrigin));
verificationResultLatch.await();
Assert.assertTrue(mAwVerifier.checkForSavedResult(mHttpsOrigin));
Assert.assertTrue(mAwVerifier.wasPreviouslyVerified(mHttpsOrigin));
}
}

@ -62,6 +62,4 @@ public interface WebSettingsBoundaryInterface {
void setEnterpriseAuthenticationAppLinkPolicyEnabled(boolean enabled);
boolean getEnterpriseAuthenticationAppLinkPolicyEnabled();
void enableRestrictSensitiveWebContent();
}

@ -244,5 +244,6 @@ public class Features {
public static final String IMAGE_DRAG_DROP = "IMAGE_DRAG_DROP";
// WebSettingsCompat.enableRestrictSensitiveWebContent
@Deprecated()
public static final String RESTRICT_SENSITIVE_WEB_CONTENT = "RESTRICT_SENSITIVE_WEB_CONTENT";
}

@ -238,13 +238,4 @@ class SupportLibWebSettingsAdapter implements WebSettingsBoundaryInterface {
return mAwSettings.getEnterpriseAuthenticationAppLinkPolicyEnabled();
}
}
@Override
public void enableRestrictSensitiveWebContent() {
try (TraceEvent event = TraceEvent.scoped(
"WebView.APICall.AndroidX.RESTRICT_SENSITIVE_WEB_CONTENT")) {
recordApiCall(ApiCall.RESTRICT_SENSITIVE_WEB_CONTENT);
mAwSettings.enableRestrictSensitiveWebContent();
}
}
}

@ -90,7 +90,6 @@ class SupportLibWebViewChromiumFactory implements WebViewProviderFactoryBoundary
Features.WEB_MESSAGE_ARRAY_BUFFER,
Features.REQUESTED_WITH_HEADER_ALLOW_LIST,
Features.IMAGE_DRAG_DROP + Features.DEV_SUFFIX,
Features.RESTRICT_SENSITIVE_WEB_CONTENT + Features.DEV_SUFFIX,
// Add new features above. New features must include `+ Features.DEV_SUFFIX`
// when they're initially added (this can be removed in a future CL). The final
// feature should have a trailing comma for cleaner diffs.
@ -171,7 +170,6 @@ class SupportLibWebViewChromiumFactory implements WebViewProviderFactoryBoundary
ApiCall.SERVICE_WORKER_SETTINGS_SET_REQUESTED_WITH_HEADER_ORIGIN_ALLOWLIST,
ApiCall.SERVICE_WORKER_SETTINGS_GET_REQUESTED_WITH_HEADER_ORIGIN_ALLOWLIST,
ApiCall.GET_IMAGE_DRAG_DROP_IMPLEMENTATION,
ApiCall.RESTRICT_SENSITIVE_WEB_CONTENT,
ApiCall.JS_REPLY_POST_MESSAGE_WITH_PAYLOAD,
// Add new constants above. The final constant should have a trailing comma for cleaner
// diffs.
@ -255,6 +253,7 @@ class SupportLibWebViewChromiumFactory implements WebViewProviderFactoryBoundary
int SERVICE_WORKER_SETTINGS_SET_REQUESTED_WITH_HEADER_ORIGIN_ALLOWLIST = 70;
int SERVICE_WORKER_SETTINGS_GET_REQUESTED_WITH_HEADER_ORIGIN_ALLOWLIST = 71;
int GET_IMAGE_DRAG_DROP_IMPLEMENTATION = 72;
@Deprecated
int RESTRICT_SENSITIVE_WEB_CONTENT = 73;
int JS_REPLY_POST_MESSAGE_WITH_PAYLOAD = 74;
// Remember to update AndroidXWebkitApiCall in enums.xml when adding new values here

@ -269,7 +269,6 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"//components/component_updater/android:embedded_component_loader_java",
"//components/content_capture/android:java",
"//components/content_capture/android/test_support:java",
"//components/content_relationship_verification/android:java",
"//components/embedder_support/android:util_java",
"//components/embedder_support/android:web_contents_delegate_java",
"//components/embedder_support/android/metrics:java",
@ -366,7 +365,6 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"../javatests/src/org/chromium/android_webview/test/AwPersistentOriginTrialTest.java",
"../javatests/src/org/chromium/android_webview/test/AwProxyControllerTest.java",
"../javatests/src/org/chromium/android_webview/test/AwQuotaManagerBridgeTest.java",
"../javatests/src/org/chromium/android_webview/test/AwRestrictSensitiveContentTest.java",
"../javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java",
"../javatests/src/org/chromium/android_webview/test/AwServiceWorkerClientTest.java",
"../javatests/src/org/chromium/android_webview/test/AwServiceWorkerSettingsTest.java",
@ -699,7 +697,6 @@ robolectric_binary("android_webview_junit_tests") {
"../junit/src/org/chromium/android_webview/robolectric/AwDisplayModeControllerTest.java",
"../junit/src/org/chromium/android_webview/robolectric/AwHttpAuthHandlerTest.java",
"../junit/src/org/chromium/android_webview/robolectric/AwLayoutSizerTest.java",
"../junit/src/org/chromium/android_webview/robolectric/AwOriginVerifierTest.java",
"../junit/src/org/chromium/android_webview/robolectric/AwScrollOffsetManagerTest.java",
"../junit/src/org/chromium/android_webview/robolectric/AwWebContentsMetricsRecorderTest.java",
"../junit/src/org/chromium/android_webview/robolectric/FindAddressTest.java",
@ -726,9 +723,6 @@ robolectric_binary("android_webview_junit_tests") {
"//base:base_java_test_support_uncommon",
"//base:base_junit_test_support",
"//components/component_updater/android:embedded_component_loader_java",
"//components/content_relationship_verification:java",
"//components/content_relationship_verification/android:java",
"//components/content_relationship_verification/android:junit_test_support",
"//components/embedder_support/android:util_java",
"//content/public/android:content_full_java",
"//content/public/test/android:content_java_test_support",

@ -14,4 +14,3 @@ IDR_WEBUI_JS_UTIL_TS_JS
IDR_WEBUI_JS_PROMISE_RESOLVER_JS
IDR_WEBUI_MOJO_MOJO_PUBLIC_JS_BINDINGS_JS
IDR_MOJO_BINDINGS_JS
IDR_ANDROID_ERROR_CONTENT_BLOCKED_ERROR_HTML

@ -13,7 +13,6 @@ static_library("android_system_error_page") {
deps = [
"//base",
"//base:i18n",
"//components/content_relationship_verification",
"//components/resources",
"//components/strings",
"//net",

@ -4,5 +4,4 @@ include_rules = [
"+net",
"+third_party/blink/public",
"+ui/base",
"+components/content_relationship_verification"
]

@ -8,7 +8,6 @@
#include "base/strings/escape.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/content_relationship_verification/content_relationship_verification_constants.h"
#include "components/grit/components_resources.h"
#include "components/strings/grit/components_strings.h"
#include "net/base/net_errors.h"
@ -46,18 +45,6 @@ void PopulateErrorPageHtml(const blink::WebURLError& error,
std::string escaped_url = base::EscapeForHTML(url_string);
// Restrict webview content error.
if (error.reason() == net::ERR_ACCESS_DENIED &&
error.extended_reason() ==
static_cast<int>(
content_relationship_verification::kExtendedErrorReason)) {
*error_html = base::ReplaceStringPlaceholders(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
IDR_ANDROID_ERROR_CONTENT_BLOCKED_ERROR_HTML),
{escaped_url}, nullptr);
return;
}
std::vector<std::string> replacements;
replacements.push_back(

@ -1,147 +0,0 @@
<html>
<head>
<title>Webpage not available</title>
<style type="text/css">
:root {
/* vars */
--button-back-background: #1B72E7;
--button-back-text: #FFFFFF;
--button-browser-background: #FFFFFF;
--button-browser-text: #6E7277;
--explanation-text: #5F6368;
--font-size-large: 3.5em;
--font-size-medium: 2.18em;
}
body {
padding: 0;
margin: 0;
overflow: hidden;
}
.container {
width: 100vw;
height: 100vh;
padding: 0 5vw;
box-sizing: border-box;
display: flex;
justify-content: center;
flex-direction: column;
}
.spacer {
min-height: 1px;
flex: 1;
}
.warning-icon {
margin-bottom: 3.5em;
}
.title {
font-family: 'Roboto';
font-size: var(--font-size-large);
line-height: 1.5;
margin-bottom: 0.5em;
}
.explanation {
font-family: 'Roboto';
color: var(--explanation-text);
line-height: 2;
font-size: var(--font-size-medium);
flex: 2;
}
button {
border: 0;
border-radius: 0.35em;
background-color: var(--button-back-background);
color: var(--button-back-text);
font-weight: bold;
font-size: var(--font-size-medium);
height: 4em;
user-select: none;
}
button.back-button {
margin-bottom: 1em;
}
button.browser-button {
margin-bottom: 3em;
background-color: var(--button-browser-background);
color: var(--button-browser-text);
}
</style>
</head>
<body>
<div class="container">
<div class="spacer"></div>
<div class="warning-icon">
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_7_79" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="16" width="184" height="159">
<path fill-rule="evenodd" clip-rule="evenodd" d="M191.667 175L100 16.6667L8.33373 175H191.667Z" fill="#DA4437">
</mask>
<g mask="url(#mask0_7_79)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M191.667 175L100 16.6667L8.3335 175H191.667ZM91.6668 150V133.333H108.334V150H91.6668ZM91.6668 116.667H108.334V83.3333H91.6668V116.667Z" fill="#DA4437">
<path d="M108.308 83.313L91.6392 116.651L171.163 196.163L199 174L108.308 83.313Z" fill="url(#paint0_linear_7_79)">
<path d="M108.336 132.999L91.667 150.004L171.191 229.516L199.028 223.686L108.336 132.999Z" fill="url(#paint1_linear_7_79)">
<g filter="url(#filter0_d_7_79)">
<path d="M108.334 116.667H91.667V83.3333H108.334V116.667Z" fill="white">
</g>
<g filter="url(#filter1_d_7_79)">
<path d="M91.667 133.333V150H108.334V133.333H91.667Z" fill="white">
</g>
</g>
<defs>
<filter id="filter0_d_7_79" x="87.667" y="79.3333" width="24.6667" height="41.3333" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix">
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha">
<feOffset>
<feGaussianBlur stdDeviation="2">
<feComposite in2="hardAlpha" operator="out">
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0">
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_79">
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_79" result="shape">
</filter>
<filter id="filter1_d_7_79" x="87.667" y="129.333" width="24.6667" height="24.6667" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix">
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha">
<feOffset>
<feGaussianBlur stdDeviation="2">
<feComposite in2="hardAlpha" operator="out">
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0">
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7_79">
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7_79" result="shape">
</filter>
<linearGradient id="paint0_linear_7_79" x1="91.6392" y1="116.876" x2="164.22" y2="188.767" gradientUnits="userSpaceOnUse">
<stop stop-color="#202125" stop-opacity="0.1">
<stop offset="0.776042" stop-color="#202125" stop-opacity="0">
</linearGradient>
<linearGradient id="paint1_linear_7_79" x1="91.667" y1="150.23" x2="164.248" y2="222.12" gradientUnits="userSpaceOnUse">
<stop stop-color="#202125" stop-opacity="0.1">
<stop offset="0.776042" stop-color="#202125" stop-opacity="0">
</linearGradient>
</defs>
</svg>
</div>
<div class="title" >This site cannot be viewed in the current app</div>
<div class="explanation">The current app is prevented from opening <b>$1</b> because it may intend to access and modify the site data or collect usage data without your permission.</div>
<button class="back-button" >Go back</button>
<button class="browser-button" >Open in default browser</button>
</div>
</body>
</html>

@ -4,8 +4,6 @@
source_set("content_relationship_verification") {
sources = [
"content_relationship_verification_constants.cc",
"content_relationship_verification_constants.h",
"digital_asset_links_handler.cc",
"digital_asset_links_handler.h",
"response_header_verifier.cc",

@ -10,5 +10,4 @@ include_rules = [
"+services/network/test",
"+third_party/blink/public/common/loader/url_loader_throttle.h",
"+third_party/blink/public/mojom",
"+third_party/blink/public/platform/resource_request_blocked_reason.h"
]

@ -1,21 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/content_relationship_verification/content_relationship_verification_constants.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
namespace content_relationship_verification {
const char kCustomCancelReasonForURLLoader[] =
"ContentRelationshipVerification";
const int kNetErrorCodeForContentRelationshipVerification =
net::ERR_ACCESS_DENIED;
const blink::ResourceRequestBlockedReason kExtendedErrorReason =
blink::ResourceRequestBlockedReason::kContentRelationshipVerification;
} // namespace content_relationship_verification

@ -1,26 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_CONTENT_RELATIONSHIP_VERIFICATION_CONSTANTS_H_
#define COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_CONTENT_RELATIONSHIP_VERIFICATION_CONSTANTS_H_
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
namespace content_relationship_verification {
// When a network::mojom::URLLoader is cancelled because of content relationship
// verification, this custom cancellation reason could be used to notify the
// implementation side. Please see
// network::mojom::URLLoader::kClientDisconnectReason for more details.
extern const char kCustomCancelReasonForURLLoader[];
// error_code to use when content relationship verification blocks a request.
extern const int kNetErrorCodeForContentRelationshipVerification;
// extended_reason() to use when content relationship verification blocks a
// request.
extern const blink::ResourceRequestBlockedReason kExtendedErrorReason;
} // namespace content_relationship_verification
#endif // COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_CONTENT_RELATIONSHIP_VERIFICATION_CONSTANTS_H_

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<include name="IDR_ANDROID_ERROR_PAGE_LOAD_ERROR_HTML" file="../android_system_error_page/resources/load_error.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_ANDROID_ERROR_CONTENT_BLOCKED_ERROR_HTML" file="../android_system_error_page/resources/content_blocked_error.html" flattenhtml="true" type="BINDATA" />
</grit-part>

@ -1994,8 +1994,6 @@ String blockedReason(blink::ResourceRequestBlockedReason reason) {
CorpNotSameOriginAfterDefaultedToSameOriginByCoep;
case blink::ResourceRequestBlockedReason::kCorpNotSameSite:
return protocol::Network::BlockedReasonEnum::CorpNotSameSite;
case blink::ResourceRequestBlockedReason::kContentRelationshipVerification:
return protocol::Network::BlockedReasonEnum::Other;
case blink::ResourceRequestBlockedReason::kConversionRequest:
// This is actually never reached, as the conversion request
// is marked as successful and no blocking reason is reported.

@ -16,7 +16,6 @@ enum class ResourceRequestBlockedReason {
kInspector,
kSubresourceFilter,
kContentType,
kContentRelationshipVerification,
kCoepFrameResourceNeedsCoepHeader,
kCoopSandboxedIFrameCannotNavigateToCoopPage,
kCorpNotSameOrigin,

@ -419,8 +419,6 @@ String BuildBlockedReason(ResourceRequestBlockedReason reason) {
CorpNotSameOriginAfterDefaultedToSameOriginByCoep;
case blink::ResourceRequestBlockedReason::kCorpNotSameSite:
return protocol::Network::BlockedReasonEnum::CorpNotSameSite;
case blink::ResourceRequestBlockedReason::kContentRelationshipVerification:
return protocol::Network::BlockedReasonEnum::Other;
case ResourceRequestBlockedReason::kConversionRequest:
// This is actually never reached, as the conversion request
// is marked as successful and no blocking reason is reported.

@ -298,9 +298,6 @@ String DescriptionForBlockedByClientOrResponse(
case ResourceRequestBlockedReason::kContentType:
detail = "ContentType";
break;
case ResourceRequestBlockedReason::kContentRelationshipVerification:
detail = "ContentRelationshipVerification";
break;
case ResourceRequestBlockedReason::kCoepFrameResourceNeedsCoepHeader:
detail = "ResponseNeedsCrossOriginEmbedderPolicy";
break;

@ -3139,7 +3139,7 @@ Unknown properties are collapsed to zero. -->
WebViewProviderFactory#getDropDataProviderImplementation()
</int>
<int value="73" label="RESTRICT_SENSITIVE_WEB_CONTENT">
WebSettingsCompat#enableRestrictSensitiveWebContent()
WebSettingsCompat#enableRestrictSensitiveWebContent() (deprecated)
</int>
<int value="74" label="JS_REPLY_POST_MESSAGE_WITH_PAYLOAD">
JsReplyProxy#postMessageWithPayload(WebMessagePayload)