summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authoriclelland <iclelland@chromium.org>2015-07-23 12:23:26 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-23 19:24:54 +0000
commit213183fe6e8958d2ef43543c806dc3d34ce3509e (patch)
tree5b3a72d280fc2562770aaee7cc3f653536113d35 /content
parentc28691dacdd323cebbdddc5e92526cb2623429b8 (diff)
downloadchromium_src-213183fe6e8958d2ef43543c806dc3d34ce3509e.zip
chromium_src-213183fe6e8958d2ef43543c806dc3d34ce3509e.tar.gz
chromium_src-213183fe6e8958d2ef43543c806dc3d34ce3509e.tar.bz2
[Background Sync] Restrict sync registration to service workers with window clients.
BUG=479658 Review URL: https://codereview.chromium.org/1234353004 Cr-Commit-Position: refs/heads/master@{#340141}
Diffstat (limited to 'content')
-rw-r--r--content/browser/background_sync/background_sync_manager.cc33
-rw-r--r--content/browser/background_sync/background_sync_manager.h3
-rw-r--r--content/browser/background_sync/background_sync_manager_unittest.cc40
-rw-r--r--content/browser/background_sync/background_sync_service_impl.cc7
-rw-r--r--content/browser/background_sync/background_sync_service_impl_unittest.cc27
-rw-r--r--content/browser/service_worker/service_worker_version.cc33
-rw-r--r--content/browser/service_worker/service_worker_version.h6
-rw-r--r--content/child/background_sync/background_sync_provider.cc21
-rw-r--r--content/common/background_sync_service.mojom3
9 files changed, 142 insertions, 31 deletions
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index 2a79df5..6c33d51 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -320,6 +320,26 @@ void BackgroundSyncManager::RegisterImpl(
return;
}
+ ServiceWorkerRegistration* sw_registration =
+ service_worker_context_->GetLiveRegistration(sw_registration_id);
+ if (!sw_registration || !sw_registration->active_version()) {
+ BackgroundSyncMetrics::CountRegister(
+ options.periodicity, registration_could_fire,
+ BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
+ ERROR_TYPE_NO_SERVICE_WORKER);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, ERROR_TYPE_NO_SERVICE_WORKER,
+ BackgroundSyncRegistration()));
+ return;
+ }
+
+ if (!sw_registration->active_version()->HasWindowClients()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_ALLOWED,
+ BackgroundSyncRegistration()));
+ return;
+ }
+
BackgroundSyncRegistration* existing_registration =
LookupRegistration(sw_registration_id, RegistrationKey(options));
if (existing_registration &&
@@ -351,19 +371,6 @@ void BackgroundSyncManager::RegisterImpl(
&sw_to_registrations_map_[sw_registration_id];
new_registration.set_id(registrations->next_id++);
- ServiceWorkerRegistration* sw_registration =
- service_worker_context_->GetLiveRegistration(sw_registration_id);
- if (!sw_registration || !sw_registration->active_version()) {
- BackgroundSyncMetrics::CountRegister(
- options.periodicity, registration_could_fire,
- BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE,
- ERROR_TYPE_NO_SERVICE_WORKER);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, ERROR_TYPE_NO_SERVICE_WORKER,
- BackgroundSyncRegistration()));
- return;
- }
-
AddRegistrationToMap(sw_registration_id,
sw_registration->pattern().GetOrigin(),
new_registration);
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h
index 07b7c43..49f2c92 100644
--- a/content/browser/background_sync/background_sync_manager.h
+++ b/content/browser/background_sync/background_sync_manager.h
@@ -49,7 +49,8 @@ class CONTENT_EXPORT BackgroundSyncManager
ERROR_TYPE_STORAGE,
ERROR_TYPE_NOT_FOUND,
ERROR_TYPE_NO_SERVICE_WORKER,
- ERROR_TYPE_MAX = ERROR_TYPE_NO_SERVICE_WORKER
+ ERROR_TYPE_NOT_ALLOWED,
+ ERROR_TYPE_MAX = ERROR_TYPE_NOT_ALLOWED
};
using StatusCallback = base::Callback<void(ErrorType)>;
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
index 6728ae4..362238b 100644
--- a/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -256,6 +256,18 @@ class BackgroundSyncManagerTest : public testing::Test {
EXPECT_TRUE(called_1);
EXPECT_TRUE(called_2);
+ // Register window clients for the service workers
+ host_1_.reset(new ServiceWorkerProviderHost(
+ 34 /* dummy render proces id */, MSG_ROUTING_NONE /* render_frame_id */,
+ 1 /* dummy provider id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ helper_->context()->AsWeakPtr(), nullptr));
+ host_1_->SetDocumentUrl(GURL(kPattern1));
+ host_2_.reset(new ServiceWorkerProviderHost(
+ 34 /* dummy render proces id */, MSG_ROUTING_NONE /* render_frame_id */,
+ 1 /* dummy provider id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ helper_->context()->AsWeakPtr(), nullptr));
+ host_2_->SetDocumentUrl(GURL(kPattern2));
+
// Hang onto the registrations as they need to be "live" when
// calling BackgroundSyncManager::Register.
helper_->context_wrapper()->FindRegistrationForId(
@@ -268,6 +280,14 @@ class BackgroundSyncManagerTest : public testing::Test {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(sw_registration_1_);
EXPECT_TRUE(sw_registration_2_);
+
+ sw_registration_1_->active_version()->AddControllee(host_1_.get());
+ sw_registration_2_->active_version()->AddControllee(host_2_.get());
+ }
+
+ void RemoveWindowClients() {
+ sw_registration_1_->active_version()->RemoveControllee(host_1_.get());
+ sw_registration_2_->active_version()->RemoveControllee(host_2_.get());
}
void SetNetwork(net::NetworkChangeNotifier::ConnectionType connection_type) {
@@ -482,6 +502,8 @@ class BackgroundSyncManagerTest : public testing::Test {
scoped_ptr<BackgroundSyncManager> background_sync_manager_;
TestBackgroundSyncManager* test_background_sync_manager_;
+ scoped_ptr<ServiceWorkerProviderHost> host_1_;
+ scoped_ptr<ServiceWorkerProviderHost> host_2_;
int64 sw_registration_id_1_;
int64 sw_registration_id_2_;
scoped_refptr<ServiceWorkerRegistration> sw_registration_1_;
@@ -1238,4 +1260,22 @@ TEST_F(BackgroundSyncManagerTest, KillManagerMidSync) {
EXPECT_EQ(2, sync_events_called_);
}
+TEST_F(BackgroundSyncManagerTest, RegisterFailsWithoutWindow) {
+ RemoveWindowClients();
+ EXPECT_FALSE(Register(sync_options_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, RegisterExistingFailsWithoutWindow) {
+ EXPECT_TRUE(Register(sync_options_1_));
+ RemoveWindowClients();
+ EXPECT_FALSE(Register(sync_options_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, UnregisterSucceedsWithoutWindow) {
+ EXPECT_TRUE(Register(sync_options_1_));
+ RemoveWindowClients();
+ EXPECT_TRUE(Unregister(callback_registration_));
+ EXPECT_FALSE(GetRegistration(sync_options_1_));
+}
+
} // namespace content
diff --git a/content/browser/background_sync/background_sync_service_impl.cc b/content/browser/background_sync/background_sync_service_impl.cc
index 0975c148..6c5c5af 100644
--- a/content/browser/background_sync/background_sync_service_impl.cc
+++ b/content/browser/background_sync/background_sync_service_impl.cc
@@ -59,9 +59,10 @@ COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_NOT_FOUND,
COMPILE_ASSERT_MATCHING_ENUM(
BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER,
BackgroundSyncManager::ERROR_TYPE_NO_SERVICE_WORKER);
-COMPILE_ASSERT_MATCHING_ENUM(
- BACKGROUND_SYNC_ERROR_MAX,
- BackgroundSyncManager::ERROR_TYPE_NO_SERVICE_WORKER);
+COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_NOT_ALLOWED,
+ BackgroundSyncManager::ERROR_TYPE_NOT_ALLOWED);
+COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_MAX,
+ BackgroundSyncManager::ERROR_TYPE_NOT_ALLOWED);
COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_ANY,
SyncNetworkState::NETWORK_STATE_ANY);
diff --git a/content/browser/background_sync/background_sync_service_impl_unittest.cc b/content/browser/background_sync/background_sync_service_impl_unittest.cc
index dbea4ba..39a8166 100644
--- a/content/browser/background_sync/background_sync_service_impl_unittest.cc
+++ b/content/browser/background_sync/background_sync_service_impl_unittest.cc
@@ -142,11 +142,25 @@ class BackgroundSyncServiceImplTest : public testing::Test {
&sw_registration_id_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
+
+ // Register window client for the service worker
+ provider_host_.reset(new ServiceWorkerProviderHost(
+ 34 /* dummy render proces id */, MSG_ROUTING_NONE /* render_frame_id */,
+ 1 /* dummy provider id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ embedded_worker_helper_->context()->AsWeakPtr(), nullptr));
+ provider_host_->SetDocumentUrl(GURL(kServiceWorkerPattern));
+
embedded_worker_helper_->context_wrapper()->FindRegistrationForId(
sw_registration_id_, GURL(kServiceWorkerPattern).GetOrigin(),
base::Bind(FindServiceWorkerRegistrationCallback, &sw_registration_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(sw_registration_);
+
+ sw_registration_->active_version()->AddControllee(provider_host_.get());
+ }
+
+ void RemoveWindowClient() {
+ sw_registration_->active_version()->RemoveControllee(provider_host_.get());
}
void CreateBackgroundSyncServiceImpl() {
@@ -199,6 +213,7 @@ class BackgroundSyncServiceImplTest : public testing::Test {
scoped_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
scoped_ptr<base::PowerMonitor> power_monitor_;
scoped_refptr<BackgroundSyncContextImpl> background_sync_context_;
+ scoped_ptr<ServiceWorkerProviderHost> provider_host_;
int64 sw_registration_id_;
scoped_refptr<ServiceWorkerRegistration> sw_registration_;
BackgroundSyncServicePtr service_ptr_;
@@ -220,6 +235,18 @@ TEST_F(BackgroundSyncServiceImplTest, Register) {
EXPECT_EQ("", reg->tag);
}
+TEST_F(BackgroundSyncServiceImplTest, RegisterWithoutWindow) {
+ bool called = false;
+ BackgroundSyncError error;
+ SyncRegistrationPtr reg;
+ RemoveWindowClient();
+ RegisterOneShot(
+ default_sync_registration_.Clone(),
+ base::Bind(&ErrorAndRegistrationCallback, &called, &error, &reg));
+ EXPECT_TRUE(called);
+ EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NOT_ALLOWED, error);
+}
+
TEST_F(BackgroundSyncServiceImplTest, Unregister) {
bool unregister_called = false;
BackgroundSyncError unregister_error;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index d2889ee..9d232d5 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -977,6 +977,10 @@ void ServiceWorkerVersion::RemoveControllee(
FOR_EACH_OBSERVER(Listener, listeners_, OnNoControllees(this));
}
+bool ServiceWorkerVersion::HasWindowClients() {
+ return !GetWindowClientsInternal(false /* include_uncontrolled */).empty();
+}
+
void ServiceWorkerVersion::AddStreamingURLRequestJob(
const ServiceWorkerURLRequestJob* request_job) {
DCHECK(streaming_url_request_jobs_.find(request_job) ==
@@ -1745,17 +1749,8 @@ void ServiceWorkerVersion::GetWindowClients(
const ServiceWorkerClientQueryOptions& options) {
DCHECK(options.client_type == blink::WebServiceWorkerClientTypeWindow ||
options.client_type == blink::WebServiceWorkerClientTypeAll);
- std::vector<base::Tuple<int, int, std::string>> clients_info;
- if (!options.include_uncontrolled) {
- for (auto& controllee : controllee_map_)
- AddWindowClient(controllee.second, &clients_info);
- } else {
- for (auto it =
- context_->GetClientProviderHostIterator(script_url_.GetOrigin());
- !it->IsAtEnd(); it->Advance()) {
- AddWindowClient(it->GetProviderHost(), &clients_info);
- }
- }
+ const std::vector<base::Tuple<int, int, std::string>>& clients_info =
+ GetWindowClientsInternal(options.include_uncontrolled);
if (clients_info.empty()) {
DidGetWindowClients(request_id, options,
@@ -1770,6 +1765,22 @@ void ServiceWorkerVersion::GetWindowClients(
weak_factory_.GetWeakPtr(), request_id, options)));
}
+const std::vector<base::Tuple<int, int, std::string>>
+ServiceWorkerVersion::GetWindowClientsInternal(bool include_uncontrolled) {
+ std::vector<base::Tuple<int, int, std::string>> clients_info;
+ if (!include_uncontrolled) {
+ for (auto& controllee : controllee_map_)
+ AddWindowClient(controllee.second, &clients_info);
+ } else {
+ for (auto it =
+ context_->GetClientProviderHostIterator(script_url_.GetOrigin());
+ !it->IsAtEnd(); it->Advance()) {
+ AddWindowClient(it->GetProviderHost(), &clients_info);
+ }
+ }
+ return clients_info;
+}
+
void ServiceWorkerVersion::DidGetWindowClients(
int request_id,
const ServiceWorkerClientQueryOptions& options,
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 3f29230..934103a 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -274,6 +274,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Returns if it has controllee.
bool HasControllee() const { return !controllee_map_.empty(); }
+ // Returns whether the service worker has active window clients under its
+ // control.
+ bool HasWindowClients();
+
// Adds and removes |request_job| as a dependent job not to stop the
// ServiceWorker while |request_job| is reading the stream of the fetch event
// response from the ServiceWorker.
@@ -473,6 +477,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
void GetWindowClients(int request_id,
const ServiceWorkerClientQueryOptions& options);
+ const std::vector<base::Tuple<int, int, std::string>>
+ GetWindowClientsInternal(bool include_uncontolled);
void DidGetWindowClients(int request_id,
const ServiceWorkerClientQueryOptions& options,
scoped_ptr<ServiceWorkerClients> clients);
diff --git a/content/child/background_sync/background_sync_provider.cc b/content/child/background_sync/background_sync_provider.cc
index 2bee9bb..bbe67d5 100644
--- a/content/child/background_sync/background_sync_provider.cc
+++ b/content/child/background_sync/background_sync_provider.cc
@@ -159,6 +159,11 @@ void BackgroundSyncProvider::RegisterCallback(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"Background Sync is disabled."));
break;
+ case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ callbacks->onError(new blink::WebSyncError(
+ blink::WebSyncError::ErrorTypeNoPermission,
+ "Cannot register a sync event without a window client."));
+ break;
case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
callbacks->onError(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
@@ -183,6 +188,11 @@ void BackgroundSyncProvider::UnregisterCallback(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"Background Sync is disabled."));
break;
+ case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ // This error should never be returned from
+ // BackgroundSyncManager::Unregister
+ NOTREACHED();
+ break;
case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
callbacks->onError(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
@@ -212,6 +222,11 @@ void BackgroundSyncProvider::GetRegistrationCallback(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"Background Sync is disabled."));
break;
+ case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ // This error should never be returned from
+ // BackgroundSyncManager::GetRegistration
+ NOTREACHED();
+ break;
case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
callbacks->onError(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
@@ -237,7 +252,8 @@ void BackgroundSyncProvider::GetRegistrationsCallback(
callbacks->onSuccess(results);
break;
case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- // This error should never be returned from
+ case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ // These errors should never be returned from
// BackgroundSyncManager::GetRegistrations
NOTREACHED();
break;
@@ -277,7 +293,8 @@ void BackgroundSyncProvider::GetPermissionStatusCallback(
}
break;
case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- // This error should never be returned from
+ case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ // These errors should never be returned from
// BackgroundSyncManager::GetPermissionStatus
NOTREACHED();
break;
diff --git a/content/common/background_sync_service.mojom b/content/common/background_sync_service.mojom
index 69a6001..c829960 100644
--- a/content/common/background_sync_service.mojom
+++ b/content/common/background_sync_service.mojom
@@ -13,7 +13,8 @@ enum BackgroundSyncError {
STORAGE,
NOT_FOUND,
NO_SERVICE_WORKER,
- MAX=NO_SERVICE_WORKER
+ NOT_ALLOWED,
+ MAX=NOT_ALLOWED
};
interface BackgroundSyncService {