blob: 9c74777cfea20bacd1ff848ab42263ba602f4c85 [file] [log] [blame]
// Copyright 2013 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/browser/service_worker/service_worker_dispatcher_host.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
static const int kRenderProcessId = 1;
class ServiceWorkerDispatcherHostTest : public testing::Test {
protected:
ServiceWorkerDispatcherHostTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
virtual void SetUp() {
helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
}
virtual void TearDown() {
helper_.reset();
}
ServiceWorkerContextCore* context() { return helper_->context(); }
ServiceWorkerContextWrapper* context_wrapper() {
return helper_->context_wrapper();
}
TestBrowserThreadBundle browser_thread_bundle_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
};
class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
public:
TestingServiceWorkerDispatcherHost(
int process_id,
ServiceWorkerContextWrapper* context_wrapper,
EmbeddedWorkerTestHelper* helper)
: ServiceWorkerDispatcherHost(process_id, NULL),
bad_messages_received_count_(0),
helper_(helper) {
Init(context_wrapper);
}
virtual bool Send(IPC::Message* message) OVERRIDE {
return helper_->Send(message);
}
IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
virtual void BadMessageReceived() OVERRIDE {
++bad_messages_received_count_;
}
int bad_messages_received_count_;
protected:
EmbeddedWorkerTestHelper* helper_;
virtual ~TestingServiceWorkerDispatcherHost() {}
};
TEST_F(ServiceWorkerDispatcherHostTest, DisabledCausesError) {
DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorker));
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
new TestingServiceWorkerDispatcherHost(
kRenderProcessId, context_wrapper(), helper_.get());
bool handled;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()),
&handled);
EXPECT_TRUE(handled);
// TODO(alecflett): Pump the message loop when this becomes async.
ASSERT_EQ(1UL, dispatcher_host->ipc_sink()->message_count());
EXPECT_TRUE(dispatcher_host->ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID));
}
// Disable this since now we cache command-line switch in
// ServiceWorkerUtils::IsFeatureEnabled() and this could be flaky depending
// on testing order. (crbug.com/352581)
// TODO(kinuko): Just remove DisabledCausesError test above and enable
// this test when we remove the --enable-service-worker flag.
TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_Enabled) {
DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorker));
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableServiceWorker);
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
new TestingServiceWorkerDispatcherHost(
kRenderProcessId, context_wrapper(), helper_.get());
bool handled;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()),
&handled);
EXPECT_TRUE(handled);
base::RunLoop().RunUntilIdle();
// TODO(alecflett): Pump the message loop when this becomes async.
ASSERT_EQ(2UL, dispatcher_host->ipc_sink()->message_count());
EXPECT_TRUE(dispatcher_host->ipc_sink()->GetUniqueMessageMatching(
EmbeddedWorkerMsg_StartWorker::ID));
EXPECT_TRUE(dispatcher_host->ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_ServiceWorkerRegistered::ID));
}
TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorker));
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableServiceWorker);
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
new TestingServiceWorkerDispatcherHost(
kRenderProcessId, context_wrapper(), helper_.get());
helper_->ShutdownContext();
bool handled;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()),
&handled);
EXPECT_TRUE(handled);
// TODO(alecflett): Pump the message loop when this becomes async.
ASSERT_EQ(1UL, dispatcher_host->ipc_sink()->message_count());
EXPECT_TRUE(dispatcher_host->ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID));
}
TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
new TestingServiceWorkerDispatcherHost(
kRenderProcessId, context_wrapper(), helper_.get());
const int kProviderId = 1001; // Test with a value != kRenderProcessId.
bool handled = false;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_ProviderCreated(kProviderId),
&handled);
EXPECT_TRUE(handled);
EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
// Two with the same ID should be seen as a bad message.
handled = false;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_ProviderCreated(kProviderId),
&handled);
EXPECT_TRUE(handled);
EXPECT_EQ(1, dispatcher_host->bad_messages_received_count_);
handled = false;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_ProviderDestroyed(kProviderId),
&handled);
EXPECT_TRUE(handled);
EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
// Destroying an ID that does not exist warrants a bad message.
handled = false;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_ProviderDestroyed(kProviderId),
&handled);
EXPECT_TRUE(handled);
EXPECT_EQ(2, dispatcher_host->bad_messages_received_count_);
// Deletion of the dispatcher_host should cause providers for that
// process to get deleted as well.
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_ProviderCreated(kProviderId),
&handled);
EXPECT_TRUE(handled);
EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
EXPECT_TRUE(dispatcher_host->HasOneRef());
dispatcher_host = NULL;
EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
}
} // namespace content