Commit e8c7efa7 authored by Mugdha Lakhani's avatar Mugdha Lakhani Committed by Commit Bot

[Periodic Background Sync] Require main frame host for registration.

Only allow Periodic Background Sync registration if the requesting
origin has a main frame host present.

Add browsertests to verify this behavior.

Corresponding PR against the spec: https://github.com/WICG/BackgroundSync/pull/160

Bug: 1029712
Change-Id: I1142578edbde62f3f27ae95b9ca602855df3543b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1942433
Commit-Queue: Mugdha Lakhani <nator@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720483}
parent 69503031
......@@ -29,6 +29,8 @@ const char kDefaultTestURL[] = "/background_sync/test.html";
const char kEmptyURL[] = "/background_sync/empty.html";
const char kRegisterSyncFromIFrameURL[] =
"/background_sync/register_sync_from_iframe.html";
const char kRegisterPeriodicSyncFromIFrameURL[] =
"/background_sync/register_periodicsync_from_iframe.html";
const char kRegisterSyncFromSWURL[] =
"/background_sync/register_sync_from_sw.html";
const char kSuccessfulOperationPrefix[] = "ok - ";
......
......@@ -402,32 +402,16 @@ void BackgroundSyncManager::Register(
DCHECK(options.min_interval >= 0 ||
options.min_interval == kMinIntervalForOneShotSync);
if (GetBackgroundSyncType(options) == BackgroundSyncType::ONE_SHOT) {
auto id = op_scheduler_.CreateId();
op_scheduler_.ScheduleOperation(
id, CacheStorageSchedulerMode::kExclusive,
CacheStorageSchedulerOp::kBackgroundSync,
CacheStorageSchedulerPriority::kNormal,
base::BindOnce(
&BackgroundSyncManager::RegisterCheckIfHasMainFrame,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
std::move(options),
op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
} else {
// Periodic Background Sync events already have a pre-defined cadence which
// the user agent decides. Don't block registration if there's no top level
// frame at the time of registration.
auto id = op_scheduler_.CreateId();
op_scheduler_.ScheduleOperation(
id, CacheStorageSchedulerMode::kExclusive,
CacheStorageSchedulerOp::kBackgroundSync,
CacheStorageSchedulerPriority::kNormal,
base::BindOnce(
&BackgroundSyncManager::RegisterImpl,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
std::move(options),
op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
}
auto id = op_scheduler_.CreateId();
op_scheduler_.ScheduleOperation(
id, CacheStorageSchedulerMode::kExclusive,
CacheStorageSchedulerOp::kBackgroundSync,
CacheStorageSchedulerPriority::kNormal,
base::BindOnce(
&BackgroundSyncManager::RegisterCheckIfHasMainFrame,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
std::move(options),
op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
}
void BackgroundSyncManager::UnregisterPeriodicSync(
......
......@@ -24,8 +24,11 @@ class PeriodicBackgroundSyncBrowserTest : public BackgroundSyncBaseBrowserTest {
~PeriodicBackgroundSyncBrowserTest() override {}
bool Register(const std::string& tag, int min_interval_ms);
bool RegisterFromIFrame(const std::string& tag, int min_interval_ms);
bool RegisterNoMinInterval(const std::string& tag);
bool RegisterFromServiceWorker(const std::string& tag, int min_interval_ms);
bool RegisterFromCrossOriginFrame(const std::string& frame_url,
std::string* script_result);
bool RegisterFromServiceWorkerNoMinInterval(const std::string& tag);
bool HasTag(const std::string& tag);
bool HasTagFromServiceWorker(const std::string& tag);
......@@ -50,6 +53,31 @@ bool PeriodicBackgroundSyncBrowserTest::Register(const std::string& tag,
return script_result == BuildExpectedResult(tag, "registered");
}
bool PeriodicBackgroundSyncBrowserTest::RegisterFromIFrame(
const std::string& tag,
int min_interval_ms) {
std::string script_result;
EXPECT_TRUE(RunScript(
base::StringPrintf("%s('%s', %d);", "registerPeriodicSyncFromIFrame",
tag.c_str(), min_interval_ms),
&script_result));
return script_result == BuildExpectedResult(tag, "registered");
}
bool PeriodicBackgroundSyncBrowserTest::RegisterFromCrossOriginFrame(
const std::string& frame_url,
std::string* script_result) {
// Start a second https server to use as a second origin.
net::EmbeddedTestServer alt_server(net::EmbeddedTestServer::TYPE_HTTPS);
alt_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
EXPECT_TRUE(alt_server.Start());
GURL url = alt_server.GetURL(frame_url);
return RunScript(
BuildScriptString("registerPeriodicSyncFromCrossOriginFrame", url.spec()),
script_result);
}
bool PeriodicBackgroundSyncBrowserTest::RegisterNoMinInterval(
const std::string& tag) {
std::string script_result;
......@@ -137,6 +165,30 @@ IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromIFrameWithTopLevelFrameForOrigin) {
std::string script_result;
GURL url = https_server()->GetURL(kEmptyURL);
EXPECT_TRUE(RunScript(
BuildScriptString("registerPeriodicSyncFromLocalFrame", url.spec()),
&script_result));
// This succeeds because there's a top level frame for the origin.
EXPECT_EQ(BuildExpectedResult("iframe", "registered periodicSync"),
script_result);
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromIFrameWithoutTopLevelFrameForOrigin) {
std::string script_result;
EXPECT_TRUE(RegisterFromCrossOriginFrame(kRegisterPeriodicSyncFromIFrameURL,
&script_result));
// This fails because there's no top level frame open for the origin.
EXPECT_EQ(BuildExpectedResult("frame", "failed to register periodicSync"),
script_result);
}
// Verify that Register works in a service worker
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromServiceWorker) {
......
......@@ -102,7 +102,7 @@ function registerPeriodicSync(tag, minInterval) {
.catch(sendErrorToTest);
}
function registerPeriodicSyncFromLocalFrame(frame_url, minInterval) {
function registerPeriodicSyncFromLocalFrame(frame_url) {
let frameWindow;
return createFrame(frame_url)
.then((frame) => {
......@@ -114,14 +114,26 @@ function registerPeriodicSyncFromLocalFrame(frame_url, minInterval) {
})
.then((frame_registration) => {
return frame_registration.periodicSync.register(
'foo', {minInterval: minInterval});
'foo', {});
})
.then(() => {
sendResultToTest('ok - iframe registered periodic sync');
sendResultToTest('ok - iframe registered periodicSync');
})
.catch(sendErrorToTest);
}
function registerPeriodicSyncFromCrossOriginFrame(cross_frame_url) {
return createFrame(cross_frame_url)
.then((frame) => receiveMessage())
.then((message) => {
if (message !== 'registration failed') {
sendResultToTest('failed - ' + message);
return;
}
sendResultToTest('ok - frame failed to register periodicSync');
});
}
function registerPeriodicSyncFromServiceWorker(tag, minInterval) {
navigator.serviceWorker.ready
.then((swRegistration) => {
......
<!DOCTYPE html>
<html>
<head>
<title>Periodic Background Sync Register From IFrame Test</title>
<script src="register_periodicsync_from_iframe.js"></script>
</head>
</html>
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
navigator.serviceWorker.register('empty_service_worker.js')
.then(() => navigator.serviceWorker.ready)
.then(registration => registration.periodicSync.register('foo', {}))
.then(() => parent.postMessage('registration succeeded', '*'),
() => parent.postMessage('registration failed', '*'));
......@@ -8,4 +8,4 @@ navigator.serviceWorker.register('empty_service_worker.js')
.then(() => navigator.serviceWorker.ready)
.then(registration => registration.sync.register('foo'))
.then(() => parent.postMessage('registration succeeded', '*'),
() => parent.postMessage('registration failed', '*'));
() => parent.postMessage('registration failed', '*'));
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