Skip to content

Commit

Permalink
Partition persistent origin trial tokens
Browse files Browse the repository at this point in the history
Adding new fields to the protobuffer to store top-level sites and
whether the token has been set in a first-party context.

Bug: 1382841
Change-Id: Ibc0829e2437390d4c14590049305c4dd1e12d56f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4136233
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Jason Chase <chasej@chromium.org>
Reviewed-by: Bence Béky <bnc@chromium.org>
Reviewed-by: Peter Beverloo <peter@chromium.org>
Commit-Queue: Peter Pakkenberg <pbirk@chromium.org>
Auto-Submit: Peter Pakkenberg <pbirk@chromium.org>
Reviewed-by: Chris Fredrickson <cfredric@chromium.org>
Reviewed-by: Alexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1096925}
  • Loading branch information
Peter Birk Pakkenberg authored and Chromium LUCI CQ committed Jan 25, 2023
1 parent 1778d6d commit f62286a
Show file tree
Hide file tree
Showing 29 changed files with 911 additions and 236 deletions.
14 changes: 10 additions & 4 deletions android_webview/browser/aw_content_browser_client.cc
Expand Up @@ -771,7 +771,7 @@ bool AwContentBrowserClient::HandleExternalProtocol(
new android_webview::AwProxyingURLLoaderFactory(
frame_tree_node_id, std::move(receiver), mojo::NullRemote(),
true /* intercept_only */, absl::nullopt /* security_options */,
nullptr /* xrw_allowlist_matcher */);
nullptr /* xrw_allowlist_matcher */, url::Origin());
} else {
content::GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
Expand All @@ -783,7 +783,7 @@ bool AwContentBrowserClient::HandleExternalProtocol(
frame_tree_node_id, std::move(receiver), mojo::NullRemote(),
true /* intercept_only */,
absl::nullopt /* security_options */,
nullptr /* xrw_allowlist_matcher */);
nullptr /* xrw_allowlist_matcher */, url::Origin());
},
std::move(receiver), frame_tree_node_id));
}
Expand Down Expand Up @@ -930,16 +930,21 @@ bool AwContentBrowserClient::WillCreateURLLoaderFactory(
auto xrw_allowlist_matcher =
AwSettings::FromWebContents(web_contents)->xrw_allowlist_matcher();

url::Origin top_frame_origin =
frame->GetOutermostMainFrame()->GetLastCommittedOrigin();

content::GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&AwProxyingURLLoaderFactory::CreateProxy,
frame->GetFrameTreeNodeId(), std::move(proxied_receiver),
std::move(target_factory_remote), security_options,
std::move(xrw_allowlist_matcher)));
std::move(xrw_allowlist_matcher),
std::move(top_frame_origin)));
} else {
// A service worker and worker subresources set nullptr to |frame|, and
// work without seeing the AllowUniversalAccessFromFileURLs setting. So,
// we don't pass a valid |security_options| here.
// At the same time, we also don't have a valid |top_frame_origin|.
AwBrowserContext* aw_browser_context =
static_cast<AwBrowserContext*>(browser_context);
content::GetIOThreadTaskRunner({})->PostTask(
Expand All @@ -949,7 +954,8 @@ bool AwContentBrowserClient::WillCreateURLLoaderFactory(
content::RenderFrameHost::kNoFrameTreeNodeId,
std::move(proxied_receiver), std::move(target_factory_remote),
absl::nullopt /* security_options */,
aw_browser_context->service_worker_xrw_allowlist_matcher()));
aw_browser_context->service_worker_xrw_allowlist_matcher(),
url::Origin() /* top_level_origin */));
}
return true;
}
Expand Down
Expand Up @@ -47,7 +47,9 @@
#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace android_webview {

Expand Down Expand Up @@ -83,7 +85,8 @@ class InterceptedRequest : public network::mojom::URLLoader,
bool intercept_only,
absl::optional<AwProxyingURLLoaderFactory::SecurityOptions>
security_options,
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher);
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
url::Origin top_frame_origin);

InterceptedRequest(const InterceptedRequest&) = delete;
InterceptedRequest& operator=(const InterceptedRequest&) = delete;
Expand Down Expand Up @@ -195,6 +198,7 @@ class InterceptedRequest : public network::mojom::URLLoader,
mojo::Remote<network::mojom::URLLoader> target_loader_;
mojo::Remote<network::mojom::URLLoaderFactory> target_factory_;
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher_;
url::Origin top_frame_origin_;

base::WeakPtrFactory<InterceptedRequest> weak_factory_{this};
};
Expand Down Expand Up @@ -290,7 +294,8 @@ InterceptedRequest::InterceptedRequest(
bool intercept_only,
absl::optional<AwProxyingURLLoaderFactory::SecurityOptions>
security_options,
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher)
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
url::Origin top_frame_origin)
: frame_tree_node_id_(frame_tree_node_id),
request_id_(request_id),
options_(options),
Expand All @@ -303,7 +308,8 @@ InterceptedRequest::InterceptedRequest(
proxied_loader_receiver_(this, std::move(loader_receiver)),
target_client_(std::move(client)),
target_factory_(std::move(target_factory)),
xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)) {
xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)),
top_frame_origin_(std::move(top_frame_origin)) {
// If there is a client error, clean up the request.
target_client_.set_disconnect_handler(base::BindOnce(
&InterceptedRequest::OnURLLoaderClientError, base::Unretained(this)));
Expand All @@ -321,6 +327,7 @@ namespace {
// Persistent Origin Trials can only be checked on the UI thread.
// |result_args| is owned by a BarrierClosure that executes after this call.
void CheckXrwOriginTrialOnUiThread(GURL request_url,
url::Origin partition_origin,
InterceptResponseReceivedArgs* result_args) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::OriginTrialsControllerDelegate* delegate =
Expand All @@ -329,8 +336,8 @@ void CheckXrwOriginTrialOnUiThread(GURL request_url,
return;

result_args->xrw_origin_trial_enabled = delegate->IsTrialPersistedForOrigin(
url::Origin::Create(request_url), "WebViewXRequestedWithDeprecation",
base::Time::Now());
url::Origin::Create(request_url), partition_origin,
"WebViewXRequestedWithDeprecation", base::Time::Now());
base::UmaHistogramBoolean(
"Android.WebView.RequestedWithHeader.OriginTrialEnabled",
result_args->xrw_origin_trial_enabled);
Expand All @@ -347,11 +354,13 @@ void CheckXrwOriginTrialOnUiThread(GURL request_url,
// for |request_url|, saving the result in |result_args|.
// |result_args| is owned by the |done_callback|.
void CheckXrwOriginTrialAsync(GURL request_url,
url::Origin partition_origin,
InterceptResponseReceivedArgs* result_args,
base::OnceClosure done_callback) {
content::GetUIThreadTaskRunner({})->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&CheckXrwOriginTrialOnUiThread, request_url,
std::move(partition_origin),
base::Unretained(result_args)),
std::move(done_callback));
}
Expand Down Expand Up @@ -388,13 +397,22 @@ void InterceptedRequest::Restart() {

request_.load_flags =
UpdateLoadFlags(request_.load_flags, io_thread_client.get());

url::Origin partition_origin = top_frame_origin_;
// Main frame navigation request should partition by the request URL.
if (static_cast<blink::mojom::ResourceType>(request_.resource_type) ==
blink::mojom::ResourceType::kMainFrame) {
partition_origin = url::Origin::Create(request_.url);
}
if (!io_thread_client || ShouldNotInterceptRequest()) {
// equivalent to no interception
std::unique_ptr<InterceptResponseReceivedArgs>
intercept_response_received_args =
std::make_unique<InterceptResponseReceivedArgs>();

CheckXrwOriginTrialAsync(
request_.url, intercept_response_received_args.get(),
request_.url, std::move(partition_origin),
intercept_response_received_args.get(),
base::BindOnce(&InterceptedRequest::InterceptResponseReceived,
weak_factory_.GetWeakPtr(),
std::move(intercept_response_received_args)));
Expand All @@ -419,7 +437,8 @@ void InterceptedRequest::Restart() {
weak_factory_.GetWeakPtr(), std::move(call_args)));
}

CheckXrwOriginTrialAsync(request_.url, intercept_response_received_args,
CheckXrwOriginTrialAsync(request_.url, std::move(partition_origin),
intercept_response_received_args,
arg_ready_closure);

// TODO: verify the case when WebContents::RenderFrameDeleted is called
Expand Down Expand Up @@ -866,11 +885,13 @@ AwProxyingURLLoaderFactory::AwProxyingURLLoaderFactory(
mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote,
bool intercept_only,
absl::optional<SecurityOptions> security_options,
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher)
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
url::Origin top_frame_origin)
: frame_tree_node_id_(frame_tree_node_id),
intercept_only_(intercept_only),
security_options_(security_options),
xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)) {
xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)),
top_frame_origin_(std::move(top_frame_origin)) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(!(intercept_only_ && target_factory_remote));
if (target_factory_remote) {
Expand All @@ -885,22 +906,23 @@ AwProxyingURLLoaderFactory::AwProxyingURLLoaderFactory(
base::Unretained(this)));
}

AwProxyingURLLoaderFactory::~AwProxyingURLLoaderFactory() {}
AwProxyingURLLoaderFactory::~AwProxyingURLLoaderFactory() = default;

// static
void AwProxyingURLLoaderFactory::CreateProxy(
int frame_tree_node_id,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote,
absl::optional<SecurityOptions> security_options,
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher) {
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
url::Origin top_frame_origin) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

// will manage its own lifetime
new AwProxyingURLLoaderFactory(frame_tree_node_id, std::move(loader_receiver),
std::move(target_factory_remote), false,
security_options,
std::move(xrw_allowlist_matcher));
new AwProxyingURLLoaderFactory(
frame_tree_node_id, std::move(loader_receiver),
std::move(target_factory_remote), false, security_options,
std::move(xrw_allowlist_matcher), std::move(top_frame_origin));
}

void AwProxyingURLLoaderFactory::CreateLoaderAndStart(
Expand Down Expand Up @@ -938,7 +960,8 @@ void AwProxyingURLLoaderFactory::CreateLoaderAndStart(
InterceptedRequest* req = new InterceptedRequest(
frame_tree_node_id_, request_id, options, request, traffic_annotation,
std::move(loader), std::move(client), std::move(target_factory_clone),
intercept_only_, security_options_, xrw_allowlist_matcher_);
intercept_only_, security_options_, xrw_allowlist_matcher_,
top_frame_origin_);
req->Restart();
}

Expand Down
Expand Up @@ -15,6 +15,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"

namespace net {
struct MutableNetworkTrafficAnnotationTag;
Expand Down Expand Up @@ -71,7 +72,8 @@ class AwProxyingURLLoaderFactory : public network::mojom::URLLoaderFactory {
target_factory_remote,
bool intercept_only,
absl::optional<SecurityOptions> security_options,
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher);
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
url::Origin top_frame_origin);

AwProxyingURLLoaderFactory(const AwProxyingURLLoaderFactory&) = delete;
AwProxyingURLLoaderFactory& operator=(const AwProxyingURLLoaderFactory&) =
Expand All @@ -86,7 +88,8 @@ class AwProxyingURLLoaderFactory : public network::mojom::URLLoaderFactory {
mojo::PendingRemote<network::mojom::URLLoaderFactory>
target_factory_remote,
absl::optional<SecurityOptions> security_options,
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher);
scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher,
url::Origin top_frame_origin);

void CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> loader,
Expand Down Expand Up @@ -117,6 +120,8 @@ class AwProxyingURLLoaderFactory : public network::mojom::URLLoaderFactory {

scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher_;

url::Origin top_frame_origin_;

base::WeakPtrFactory<AwProxyingURLLoaderFactory> weak_factory_{this};
};

Expand Down
Expand Up @@ -3806,7 +3806,7 @@ TEST_F(ChromeBrowsingDataRemoverDelegateOriginTrialsTest,
std::vector<std::string> tokens{kPersistentOriginTrialToken};
content::OriginTrialsControllerDelegate* delegate =
profile->GetOriginTrialsControllerDelegate();
delegate->PersistTrialsFromTokens(origin, tokens,
delegate->PersistTrialsFromTokens(origin, /*partition_origin=*/origin, tokens,
kPersistentOriginTrialValidTime);

// Delete all data types that trigger website setting deletions.
Expand All @@ -3816,12 +3816,14 @@ TEST_F(ChromeBrowsingDataRemoverDelegateOriginTrialsTest,

EXPECT_FALSE(
delegate
->GetPersistedTrialsForOrigin(origin, kPersistentOriginTrialValidTime)
->GetPersistedTrialsForOrigin(origin, /*partition_origin=*/origin,
kPersistentOriginTrialValidTime)
.empty());

BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), mask, false);
EXPECT_TRUE(
delegate
->GetPersistedTrialsForOrigin(origin, kPersistentOriginTrialValidTime)
.empty());
EXPECT_TRUE(delegate
->GetPersistedTrialsForOrigin(origin,
/*partition_origin=*/origin,
kPersistentOriginTrialValidTime)
.empty());
}

0 comments on commit f62286a

Please sign in to comment.