Skip to content

Commit

Permalink
[M116] Enable the static routing API via OriginTrial token
Browse files Browse the repository at this point in the history
This CL enables the static routing API in ServiceWorker via Origin Trial
token.  SeriviceWorker stores OriginTrial tokens on its database and
this CL look into that.

This CL changes |router_evaluator| being set only when the feature is
enabled by the feature flag or OriginTrial token. This change simplifies
the feature detection in both main resource and subresource because the
only thing we have to check is |router_evaluator|.

(cherry picked from commit bcdbb26)

Bug: 1371756
Change-Id: Iddc6c01a3936894d0f5cceb5c6970795af824d96
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4629430
Reviewed-by: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
Commit-Queue: Shunya Shishido <sisidovski@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1160545}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4644931
Reviewed-by: Minoru Chikamune <chikamune@chromium.org>
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Commit-Queue: Kouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/branch-heads/5845@{#127}
Cr-Branched-From: 5a5dff6-refs/heads/main@{#1160321}
  • Loading branch information
sisidovski authored and Chromium LUCI CQ committed Jun 27, 2023
1 parent 0e6643b commit ad0ac4e
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 24 deletions.
123 changes: 123 additions & 0 deletions content/browser/service_worker/service_worker_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6095,4 +6095,127 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerStaticRouterBrowserTest,
EXPECT_EQ(1, GetRequestCount("/service_worker/direct"));
}

class ServiceWorkerStaticRouterOriginTrialBrowserTest
: public ServiceWorkerStaticRouterBrowserTest {
public:
ServiceWorkerStaticRouterOriginTrialBrowserTest() {
// Explicitly disable the feature to ensure the feature is enabled by the
// Origin Trial token.
feature_list_.InitWithFeatures({}, {features::kServiceWorkerStaticRouter});
}

void SetUpCommandLine(base::CommandLine* command_line) override {
// The public key for the default privatey key used by the
// tools/origin_trials/generate_token.py tool.
static constexpr char kOriginTrialTestPublicKey[] =
"dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=";
command_line->AppendSwitchASCII("origin-trial-public-key",
kOriginTrialTestPublicKey);
}

private:
base::test::ScopedFeatureList feature_list_;
};

IN_PROC_BROWSER_TEST_F(ServiceWorkerStaticRouterOriginTrialBrowserTest,
Fallback) {
embedded_test_server()->StartAcceptingConnections();

// The URL that was used to register the Origin Trial token.
static constexpr char kOriginUrl[] = "https://127.0.0.1:44444";
// Generated by running (in tools/origin_trials):
// tools/origin_trials/generate_token.py https://127.0.0.1:44444 \
// ServiceWorkerBypassFetchHandlerWithRaceNetworkRequest \
// --expire-timestamp=2000000000
static constexpr char kOriginTrialToken[] =
"AzX0kWd3mFeKWSeRT8ffvcxWodihqbB/WzApFm94qJPZmSbhO2a6fLLk1ilkzxf88qOOYI/"
"TYr+"
"K9VKvgI4w3QgAAABjeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmV"
"hdHVyZSI6ICJTZXJ2aWNlV29ya2VyU3RhdGljUm91dGVyIiwgImV4cGlyeSI6IDIwMDAwMDA"
"wMDB9";

const GURL registation_url(
base::StrCat({kOriginUrl, "/create_service_worker.html"}));
const GURL network_fallback_url(
base::StrCat({kOriginUrl, "/service_worker/direct"}));
const GURL service_worker_url(
base::StrCat({kOriginUrl, "/static_router.js"}));

std::map<GURL, int /* number_of_invocations */> expected_request_urls = {
{registation_url, 1},
{network_fallback_url, 2},
{service_worker_url, 1},
};

base::RunLoop run_loop;

// The origin trial token is associated with an origin. We can't guarantee the
// EmbeddedTestServer to use a specific port. So the URLLoaderInterceptor is
// used instead.
URLLoaderInterceptor service_worker_loader(base::BindLambdaForTesting(
[&](URLLoaderInterceptor::RequestParams* params) {
auto it = expected_request_urls.find(params->url_request.url);
if (it == expected_request_urls.end()) {
return false;
}

const std::string content_type =
base::EndsWith(params->url_request.url.path_piece(), ".js")
? "text/javascript"
: "text/html";

const std::string origin_trial_token =
params->url_request.url == service_worker_url ? kOriginTrialToken
: "";

const std::string headers = base::ReplaceStringPlaceholders(
"HTTP/1.1 200 OK\n"
"Content-type: $1\n"
"Origin-Trial: $2\n"
"\n",
{content_type, origin_trial_token}, {});

if (base::Contains(params->url_request.url.path(), "/direct")) {
const std::string body =
"[ServiceWorkerStaticRouter] Response from the network";
URLLoaderInterceptor::WriteResponse(
headers, body, params->client.get(),
absl::optional<net::SSLInfo>(), params->url_request.url);
} else {
URLLoaderInterceptor::WriteResponse(
"content/test/data/service_worker" +
params->url_request.url.path(),
params->client.get(), &headers, absl::optional<net::SSLInfo>(),
params->url_request.url);
}

if (--it->second == 0) {
expected_request_urls.erase(it);
}
if (expected_request_urls.empty()) {
run_loop.Quit();
}
return true;
}));

// Register a service worker.
WorkerRunningStatusObserver observer(public_context());
EXPECT_TRUE(NavigateToURL(shell(), registation_url));
EXPECT_EQ("DONE",
EvalJs(GetPrimaryMainFrame(), "register('/static_router.js')"));
observer.WaitUntilRunning();
scoped_refptr<ServiceWorkerVersion> version =
wrapper()->GetLiveVersion(observer.version_id());
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());

// The result should be got from the network, both for main resource and
// subresource.
EXPECT_TRUE(NavigateToURL(shell(), network_fallback_url));
EXPECT_EQ("[ServiceWorkerStaticRouter] Response from the network",
GetInnerText());
EXPECT_EQ("[ServiceWorkerStaticRouter] Response from the network",
EvalJs(GetPrimaryMainFrame(),
"fetch('/service_worker/direct').then(response => "
"response.text())"));
}
} // namespace content
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ void ServiceWorkerMainResourceLoader::StartRequest(
DCHECK(context);

// Check if registered static route rules match the request.
if (base::FeatureList::IsEnabled(features::kServiceWorkerStaticRouter) &&
active_worker->router_evaluator()) {
if (active_worker->router_evaluator()) {
CHECK(active_worker->router_evaluator()->IsValid());
auto sources =
active_worker->router_evaluator()->Evaluate(resource_request_);
Expand Down
2 changes: 1 addition & 1 deletion content/browser/service_worker/service_worker_registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ ServiceWorkerRegistry::GetOrCreateRegistration(
base::MakeRefCounted<PolicyContainerHost>(
PolicyContainerPolicies(*data.policy_container_policies)));
}
if (data.router_rules) {
if (data.router_rules && version->IsStaticRouterEnabled()) {
bool status = version->SetupRouterEvaluator(*data.router_rules);
DCHECK(status) << "Failed to setup RouterEvaluator from the provided "
<< "rules. Possibly the database is corrupted.";
Expand Down
21 changes: 19 additions & 2 deletions content/browser/service_worker/service_worker_version.cc
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,7 @@ void ServiceWorkerVersion::RegisterStatusChangeCallback(
ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
absl::optional<std::string> router_rules;
if (base::FeatureList::IsEnabled(features::kServiceWorkerStaticRouter) &&
router_evaluator_) {
if (router_evaluator_) {
router_rules = router_evaluator_->ToString();
}
ServiceWorkerVersionInfo info(
Expand Down Expand Up @@ -1821,6 +1820,12 @@ void ServiceWorkerVersion::SkipWaiting(SkipWaitingCallback callback) {
void ServiceWorkerVersion::RegisterRouter(
const blink::ServiceWorkerRouterRules& rules,
RegisterRouterCallback callback) {
if (!IsStaticRouterEnabled()) {
// This renderer should have called this only when the feature is enabled.
receiver_.ReportBadMessage(
"Unexpected router registration call during the feature is disabled.");
return;
}
if (router_evaluator()) {
// The renderer should have denied calling this twice.
receiver_.ReportBadMessage("The ServiceWorker router rules are set twice.");
Expand Down Expand Up @@ -2886,6 +2891,7 @@ void ServiceWorkerVersion::SetResources(

bool ServiceWorkerVersion::SetupRouterEvaluator(
const blink::ServiceWorkerRouterRules& rules) {
CHECK(IsStaticRouterEnabled());
CHECK(!router_evaluator_);
router_evaluator_ = std::make_unique<ServiceWorkerRouterEvaluator>(rules);
if (!router_evaluator_->IsValid()) {
Expand All @@ -2895,6 +2901,17 @@ bool ServiceWorkerVersion::SetupRouterEvaluator(
return true;
}

bool ServiceWorkerVersion::IsStaticRouterEnabled() {
if (base::FeatureList::IsEnabled(features::kServiceWorkerStaticRouter)) {
return true;
}
if (origin_trial_tokens_ &&
origin_trial_tokens_->contains("ServiceWorkerStaticRouter")) {
return true;
}
return false;
}

base::WeakPtr<ServiceWorkerVersion> ServiceWorkerVersion::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
Expand Down
4 changes: 4 additions & 0 deletions content/browser/service_worker/service_worker_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
return sha256_script_checksum_;
}

// Check if the static router API is enabled. It checks if the feature flag is
// enabled or having a valid trial token.
bool IsStaticRouterEnabled();

// Timeout for a request to be handled.
static constexpr base::TimeDelta kRequestTimeout = base::Minutes(5);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,17 @@ TEST_F(ServiceWorkerVersionTest, SetResources) {
version->sha256_script_checksum());
}

TEST_F(ServiceWorkerVersionTest, SetRouterEvaluator) {
class ServiceWorkerVersionStaticRouterTest : public ServiceWorkerVersionTest {
public:
ServiceWorkerVersionStaticRouterTest() {
feature_list_.InitWithFeatures({features::kServiceWorkerStaticRouter}, {});
}

private:
base::test::ScopedFeatureList feature_list_;
};

TEST_F(ServiceWorkerVersionStaticRouterTest, SetRouterEvaluator) {
// Create a new version
scoped_refptr<ServiceWorkerVersion> version = CreateNewServiceWorkerVersion(
helper_->context()->registry(), registration_.get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,24 +373,22 @@ void ServiceWorkerSubresourceLoader::DispatchFetchEvent() {
}
}

if (base::FeatureList::IsEnabled(features::kServiceWorkerStaticRouter)) {
auto* router_evaluator = controller_connector_->router_evaluator();
if (router_evaluator) {
CHECK(router_evaluator->IsValid());
auto sources = router_evaluator->Evaluate(resource_request_);
if (!sources.empty()) { // matched the rule.
// TODO(crbug.com/1371756): support other sources in the full form.
// https://github.com/yoshisatoyanagisawa/service-worker-static-routing-api/blob/main/final-form.md
if (sources[0].type ==
blink::ServiceWorkerRouterSource::SourceType::kNetwork) {
// Network fallback is requested.
fallback_factory_->CreateLoaderAndStart(
url_loader_receiver_.Unbind(), request_id_, options_,
resource_request_, url_loader_client_.Unbind(),
traffic_annotation_);
delete this;
return;
}
auto* router_evaluator = controller_connector_->router_evaluator();
if (router_evaluator) {
CHECK(router_evaluator->IsValid());
auto sources = router_evaluator->Evaluate(resource_request_);
if (!sources.empty()) { // matched the rule.
// TODO(crbug.com/1371756): support other sources in the full form.
// https://github.com/yoshisatoyanagisawa/service-worker-static-routing-api/blob/main/final-form.md
if (sources[0].type ==
blink::ServiceWorkerRouterSource::SourceType::kNetwork) {
// Network fallback is requested.
fallback_factory_->CreateLoaderAndStart(
url_loader_receiver_.Unbind(), request_id_, options_,
resource_request_, url_loader_client_.Unbind(),
traffic_annotation_);
delete this;
return;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3215,6 +3215,7 @@
{
name: "ServiceWorkerStaticRouter",
base_feature: "none",
origin_trial_feature_name: "ServiceWorkerStaticRouter",
public: true,
},
{
Expand Down

0 comments on commit ad0ac4e

Please sign in to comment.