diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-15 19:31:27 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-15 19:31:27 +0000 |
commit | 59f7d173f32295f6fd0bd4e2c99340632f68e2c9 (patch) | |
tree | f9b5488ec0773b8a3c7626f860f24bfe167acac9 /content/browser/service_worker | |
parent | c8bb080c880d3e57ff15b0725341f8fcc3e30375 (diff) | |
download | chromium_src-59f7d173f32295f6fd0bd4e2c99340632f68e2c9.zip chromium_src-59f7d173f32295f6fd0bd4e2c99340632f68e2c9.tar.gz chromium_src-59f7d173f32295f6fd0bd4e2c99340632f68e2c9.tar.bz2 |
Add basic browser test for EmbeddedWorker/ServiceWorker
This test does:
- kick registerServiceWorker (primarily for installing ServiceWorkerProviderHost)
- manually associate ServiceWorkerProviderHost to an EmbeddedWorker (eventually this should be done via ServiceWorkerVersion)
- Start and stop the EmbeddedWorker, and observe OnStarted/OnStopped msgs are sent from the child process
BUG=313530, 285976
TEST=ServiceWorkerBrowserTest.EmbeddedWorkerBasic
Review URL: https://codereview.chromium.org/127573002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244960 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/service_worker')
5 files changed, 201 insertions, 0 deletions
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 88c4b03..a376562 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc @@ -85,12 +85,22 @@ void EmbeddedWorkerInstance::OnStarted(int thread_id) { DCHECK(status_ == STARTING); status_ = RUNNING; thread_id_ = thread_id; + FOR_EACH_OBSERVER(Observer, observer_list_, OnStarted()); } void EmbeddedWorkerInstance::OnStopped() { status_ = STOPPED; process_id_ = -1; thread_id_ = -1; + FOR_EACH_OBSERVER(Observer, observer_list_, OnStopped()); +} + +void EmbeddedWorkerInstance::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void EmbeddedWorkerInstance::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); } bool EmbeddedWorkerInstance::ChooseProcess() { diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h index 5a992a2..fcc2c34 100644 --- a/content/browser/service_worker/embedded_worker_instance.h +++ b/content/browser/service_worker/embedded_worker_instance.h @@ -12,6 +12,7 @@ #include "base/gtest_prod_util.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/observer_list.h" #include "content/common/content_export.h" class GURL; @@ -33,6 +34,13 @@ class CONTENT_EXPORT EmbeddedWorkerInstance { STOPPING, }; + class Observer { + public: + virtual ~Observer() {} + virtual void OnStarted() = 0; + virtual void OnStopped() = 0; + }; + ~EmbeddedWorkerInstance(); // Starts the worker. It is invalid to call this when the worker is @@ -63,6 +71,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance { int process_id() const { return process_id_; } int thread_id() const { return thread_id_; } + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + private: friend class EmbeddedWorkerRegistry; FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop); @@ -99,6 +110,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance { int thread_id_; ProcessRefMap process_refs_; + ObserverList<Observer> observer_list_; DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance); }; diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc new file mode 100644 index 0000000..e4894bb --- /dev/null +++ b/content/browser/service_worker/service_worker_browsertest.cc @@ -0,0 +1,159 @@ +// Copyright 2014 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 "base/bind.h" +#include "base/callback.h" +#include "base/command_line.h" +#include "base/location.h" +#include "base/run_loop.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" +#include "content/shell/browser/shell.h" +#include "content/test/content_browser_test.h" +#include "content/test/content_browser_test_utils.h" +#include "net/test/embedded_test_server/embedded_test_server.h" + +namespace content { + +class ServiceWorkerBrowserTest : public ContentBrowserTest, + public EmbeddedWorkerInstance::Observer { + public: + typedef ServiceWorkerBrowserTest self; + + ServiceWorkerBrowserTest() + : last_worker_status_(EmbeddedWorkerInstance::STOPPED) {} + virtual ~ServiceWorkerBrowserTest() {} + + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { + command_line->AppendSwitch(switches::kEnableServiceWorker); + } + + virtual void SetUpOnMainThread() OVERRIDE { + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + StoragePartition* partition = BrowserContext::GetDefaultStoragePartition( + shell()->web_contents()->GetBrowserContext()); + wrapper_ = partition->GetServiceWorkerContext(); + } + + virtual void TearDownOnMainThread() OVERRIDE { + base::RunLoop run_loop; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&self::TearDownOnIOThread, this, run_loop.QuitClosure())); + run_loop.Run(); + wrapper_ = NULL; + } + + void TearDownOnIOThread(const base::Closure& done_closure) { + if (worker_) { + worker_->RemoveObserver(this); + worker_.reset(); + } + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure); + } + + void StartEmbeddedWorkerOnIOThread() { + ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + worker_ = wrapper_->context()->embedded_worker_registry()->CreateWorker(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker_->status()); + worker_->AddObserver(this); + + // TODO(kinuko): this manual wiring should go away when this gets wired + // in the actual code path. + ServiceWorkerProviderHost* provider_host = GetRegisteredProviderHost(); + worker_->AddProcessReference(provider_host->process_id()); + + const int64 service_worker_version_id = 33L; + const GURL script_url = embedded_test_server()->GetURL( + "/service_worker/worker.js"); + const bool started = worker_->Start(service_worker_version_id, script_url); + + last_worker_status_ = worker_->status(); + EXPECT_TRUE(started); + EXPECT_EQ(EmbeddedWorkerInstance::STARTING, last_worker_status_); + + if (!started && !done_closure_.is_null()) + done_closure_.Run(); + } + + void StopEmbeddedWorkerOnIOThread() { + ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker_->status()); + + const bool stopped = worker_->Stop(); + + last_worker_status_ = worker_->status(); + EXPECT_TRUE(stopped); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, last_worker_status_); + + if (!stopped && !done_closure_.is_null()) + done_closure_.Run(); + } + + protected: + // Embe3ddedWorkerInstance::Observer overrides: + virtual void OnStarted() OVERRIDE { + ASSERT_TRUE(worker_ != NULL); + ASSERT_FALSE(done_closure_.is_null()); + last_worker_status_ = worker_->status(); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_); + } + virtual void OnStopped() OVERRIDE { + ASSERT_TRUE(worker_ != NULL); + ASSERT_FALSE(done_closure_.is_null()); + last_worker_status_ = worker_->status(); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_); + } + + ServiceWorkerProviderHost* GetRegisteredProviderHost() { + // Assumes only one provider host is registered at this point. + std::vector<ServiceWorkerProviderHost*> providers; + wrapper_->context()->GetAllProviderHosts(&providers); + DCHECK_EQ(1U, providers.size()); + return providers[0]; + } + + scoped_refptr<ServiceWorkerContextWrapper> wrapper_; + scoped_ptr<EmbeddedWorkerInstance> worker_; + EmbeddedWorkerInstance::Status last_worker_status_; + + // Called by EmbeddedWorkerInstance::Observer overrides so that + // test code can wait for the worker status notifications. + base::Closure done_closure_; +}; + +IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, EmbeddedWorkerBasic) { + // Navigate to the page to set up a provider. + NavigateToURLBlockUntilNavigationsComplete( + shell(), embedded_test_server()->GetURL("/service_worker/index.html"), 1); + + // Start a worker and wait until OnStarted() is called. + base::RunLoop start_run_loop; + done_closure_ = start_run_loop.QuitClosure(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&self::StartEmbeddedWorkerOnIOThread, this)); + start_run_loop.Run(); + + ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_); + + // Stop a worker and wait until OnStopped() is called. + base::RunLoop stop_run_loop; + done_closure_ = stop_run_loop.QuitClosure(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&self::StopEmbeddedWorkerOnIOThread, this)); + stop_run_loop.Run(); + + ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_); +} + +} // namespace content diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index 88897ac..0a30b7b 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc @@ -99,4 +99,19 @@ void ServiceWorkerContextCore::RegistrationComplete( callback.Run(status, registration->id()); } +void ServiceWorkerContextCore::GetAllProviderHosts( + std::vector<ServiceWorkerProviderHost*>* providers) { + DCHECK(providers); + + ProcessToProviderMap::iterator map_iter(&providers_); + while (!map_iter.IsAtEnd()) { + ProviderMap::iterator iter(map_iter.GetCurrentValue()); + while (!iter.IsAtEnd()) { + providers->push_back(iter.GetCurrentValue()); + iter.Advance(); + } + map_iter.Advance(); + } +} + } // namespace content diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index e911e4c..4ab4351 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h @@ -81,6 +81,8 @@ class CONTENT_EXPORT ServiceWorkerContextCore } private: + friend class ServiceWorkerBrowserTest; + typedef IDMap<ServiceWorkerProviderHost, IDMapOwnPointer> ProviderMap; typedef IDMap<ProviderMap, IDMapOwnPointer> ProcessToProviderMap; @@ -93,6 +95,9 @@ class CONTENT_EXPORT ServiceWorkerContextCore ServiceWorkerRegistrationStatus status, const scoped_refptr<ServiceWorkerRegistration>& registration); + // Used only for testing. + void GetAllProviderHosts(std::vector<ServiceWorkerProviderHost*>* providers); + ProcessToProviderMap providers_; scoped_ptr<ServiceWorkerStorage> storage_; scoped_ptr<ServiceWorkerJobCoordinator> job_coordinator_; |