summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/service_worker/embedded_worker_instance.cc10
-rw-r--r--content/browser/service_worker/embedded_worker_instance.h12
-rw-r--r--content/browser/service_worker/service_worker_browsertest.cc159
-rw-r--r--content/browser/service_worker/service_worker_context_core.cc15
-rw-r--r--content/browser/service_worker/service_worker_context_core.h5
-rw-r--r--content/browser/storage_partition_impl.h3
6 files changed, 202 insertions, 2 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_;
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index ab48b04..717038e 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -42,6 +42,7 @@ class StoragePartitionImpl : public StoragePartition {
virtual webkit_database::DatabaseTracker* GetDatabaseTracker() OVERRIDE;
virtual DOMStorageContextWrapper* GetDOMStorageContext() OVERRIDE;
virtual IndexedDBContextImpl* GetIndexedDBContext() OVERRIDE;
+ virtual ServiceWorkerContextWrapper* GetServiceWorkerContext() OVERRIDE;
virtual void ClearDataForOrigin(
uint32 remove_mask,
@@ -56,8 +57,6 @@ class StoragePartitionImpl : public StoragePartition {
const base::Time end,
const base::Closure& callback) OVERRIDE;
- ServiceWorkerContextWrapper* GetServiceWorkerContext();
-
WebRTCIdentityStore* GetWebRTCIdentityStore();
struct DataDeletionHelper;