blob: b4dbbdb4dee7ba7eeb4092af938327309cd70230 [file] [log] [blame]
// Copyright 2015 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.
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/web_service_worker_impl.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ipc/ipc_test_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class ServiceWorkerTestSender : public ThreadSafeSender {
public:
explicit ServiceWorkerTestSender(IPC::TestSink* ipc_sink)
: ThreadSafeSender(nullptr, nullptr),
ipc_sink_(ipc_sink) {}
bool Send(IPC::Message* message) override {
return ipc_sink_->Send(message);
}
private:
~ServiceWorkerTestSender() override {}
IPC::TestSink* ipc_sink_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTestSender);
};
class ServiceWorkerDispatcherTest : public testing::Test {
public:
ServiceWorkerDispatcherTest() {}
void SetUp() override {
sender_ = new ServiceWorkerTestSender(&ipc_sink_);
dispatcher_.reset(new ServiceWorkerDispatcher(sender_.get(), nullptr));
}
void CreateObjectInfoAndVersionAttributes(
ServiceWorkerRegistrationObjectInfo* info,
ServiceWorkerVersionAttributes* attrs) {
info->handle_id = 10;
info->registration_id = 20;
attrs->active.handle_id = 100;
attrs->active.version_id = 200;
attrs->waiting.handle_id = 101;
attrs->waiting.version_id = 201;
attrs->installing.handle_id = 102;
attrs->installing.version_id = 202;
}
WebServiceWorkerRegistrationImpl* FindOrCreateRegistration(
const ServiceWorkerRegistrationObjectInfo& info,
const ServiceWorkerVersionAttributes& attrs) {
return dispatcher_->FindOrCreateRegistration(info, attrs);
}
bool ContainsServiceWorker(int handle_id) {
return ContainsKey(dispatcher_->service_workers_, handle_id);
}
bool ContainsRegistration(int registration_handle_id) {
return ContainsKey(dispatcher_->registrations_, registration_handle_id);
}
ServiceWorkerDispatcher* dispatcher() { return dispatcher_.get(); }
IPC::TestSink* ipc_sink() { return &ipc_sink_; }
private:
IPC::TestSink ipc_sink_;
scoped_ptr<ServiceWorkerDispatcher> dispatcher_;
scoped_refptr<ServiceWorkerTestSender> sender_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherTest);
};
// TODO(nhiroki): Add tests for message handlers especially to receive reference
// counts like OnAssociateRegistration().
TEST_F(ServiceWorkerDispatcherTest, GetServiceWorker) {
ServiceWorkerRegistrationObjectInfo info;
ServiceWorkerVersionAttributes attrs;
CreateObjectInfoAndVersionAttributes(&info, &attrs);
// Should return a worker object newly created with incrementing refcount.
bool adopt_handle = false;
scoped_ptr<WebServiceWorkerImpl> worker(
dispatcher()->GetServiceWorker(attrs.installing, adopt_handle));
EXPECT_TRUE(worker);
EXPECT_TRUE(ContainsServiceWorker(attrs.installing.handle_id));
EXPECT_EQ(1UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
ipc_sink()->ClearMessages();
// Should return the existing worker object.
adopt_handle = false;
WebServiceWorkerImpl* existing_worker =
dispatcher()->GetServiceWorker(attrs.installing, adopt_handle);
EXPECT_EQ(worker, existing_worker);
EXPECT_EQ(0UL, ipc_sink()->message_count());
// Should return the existing worker object with adopting refcount.
adopt_handle = true;
existing_worker =
dispatcher()->GetServiceWorker(attrs.installing, adopt_handle);
EXPECT_EQ(worker, existing_worker);
ASSERT_EQ(1UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
ipc_sink()->ClearMessages();
// Should return another worker object newly created with adopting refcount.
adopt_handle = true;
scoped_ptr<WebServiceWorkerImpl> another_worker(
dispatcher()->GetServiceWorker(attrs.waiting, adopt_handle));
EXPECT_NE(worker.get(), another_worker.get());
EXPECT_TRUE(ContainsServiceWorker(attrs.waiting.handle_id));
EXPECT_EQ(0UL, ipc_sink()->message_count());
// Should return nullptr when a given object info is invalid.
adopt_handle = false;
WebServiceWorkerImpl* invalid_worker =
dispatcher()->GetServiceWorker(ServiceWorkerObjectInfo(), adopt_handle);
EXPECT_FALSE(invalid_worker);
EXPECT_EQ(0UL, ipc_sink()->message_count());
adopt_handle = true;
invalid_worker =
dispatcher()->GetServiceWorker(ServiceWorkerObjectInfo(), adopt_handle);
EXPECT_FALSE(invalid_worker);
EXPECT_EQ(0UL, ipc_sink()->message_count());
}
TEST_F(ServiceWorkerDispatcherTest, CreateServiceWorkerRegistration) {
ServiceWorkerRegistrationObjectInfo info;
ServiceWorkerVersionAttributes attrs;
CreateObjectInfoAndVersionAttributes(&info, &attrs);
// Should return a registration object newly created with incrementing
// refcount.
bool adopt_handle = false;
scoped_ptr<WebServiceWorkerRegistrationImpl> registration(
dispatcher()->CreateServiceWorkerRegistration(info, adopt_handle));
EXPECT_TRUE(registration);
EXPECT_TRUE(ContainsRegistration(info.handle_id));
ASSERT_EQ(1UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_IncrementRegistrationRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
registration.reset();
EXPECT_FALSE(ContainsRegistration(info.handle_id));
ipc_sink()->ClearMessages();
// Should return another registration object newly created with adopting
// refcount.
adopt_handle = true;
scoped_ptr<WebServiceWorkerRegistrationImpl> another_registration(
dispatcher()->CreateServiceWorkerRegistration(info, adopt_handle));
EXPECT_TRUE(another_registration);
EXPECT_TRUE(ContainsRegistration(info.handle_id));
EXPECT_EQ(0UL, ipc_sink()->message_count());
another_registration.reset();
ipc_sink()->ClearMessages();
// should return nullptr when a given object info is invalid.
adopt_handle = false;
scoped_ptr<WebServiceWorkerRegistrationImpl> invalid_registration(
dispatcher()->CreateServiceWorkerRegistration(
ServiceWorkerRegistrationObjectInfo(), adopt_handle));
EXPECT_FALSE(invalid_registration);
EXPECT_FALSE(ContainsRegistration(info.handle_id));
EXPECT_EQ(0UL, ipc_sink()->message_count());
adopt_handle = true;
invalid_registration.reset(dispatcher()->CreateServiceWorkerRegistration(
ServiceWorkerRegistrationObjectInfo(), adopt_handle));
EXPECT_FALSE(invalid_registration);
EXPECT_FALSE(ContainsRegistration(info.handle_id));
EXPECT_EQ(0UL, ipc_sink()->message_count());
}
TEST_F(ServiceWorkerDispatcherTest, FindOrCreateRegistration) {
ServiceWorkerRegistrationObjectInfo info;
ServiceWorkerVersionAttributes attrs;
CreateObjectInfoAndVersionAttributes(&info, &attrs);
// Should return a registration object newly created with adopting refcounts.
scoped_ptr<WebServiceWorkerRegistrationImpl> registration(
FindOrCreateRegistration(info, attrs));
EXPECT_TRUE(registration);
EXPECT_EQ(info.registration_id, registration->registration_id());
EXPECT_EQ(0UL, ipc_sink()->message_count());
// Should return the existing registration object with adopting refcounts.
WebServiceWorkerRegistrationImpl* existing_registration =
FindOrCreateRegistration(info, attrs);
EXPECT_EQ(registration, existing_registration);
ASSERT_EQ(4UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(1)->type());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(2)->type());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(3)->type());
}
} // namespace content