summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-16 13:18:03 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-16 13:18:03 +0000
commitf56fb35d0305ad053d08f7b366d8338375f50112 (patch)
tree7dc53680dbf2cc02cf609ae9fc0bad4e2a88a9de /content
parentdfc613d04ae69dde45d4e99c100feac6447fe9de (diff)
downloadchromium_src-f56fb35d0305ad053d08f7b366d8338375f50112.zip
chromium_src-f56fb35d0305ad053d08f7b366d8338375f50112.tar.gz
chromium_src-f56fb35d0305ad053d08f7b366d8338375f50112.tar.bz2
Retry: Stop ServiceWorker context when no controllee is associated
Re-landing https://codereview.chromium.org/272183005 with leak fix. BUG=372673 TBR=michaeln@chromium.org,horo@chromium.org Review URL: https://codereview.chromium.org/282263008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271004 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/service_worker/embedded_worker_instance.cc2
-rw-r--r--content/browser/service_worker/embedded_worker_registry.cc5
-rw-r--r--content/browser/service_worker/embedded_worker_test_helper.cc4
-rw-r--r--content/browser/service_worker/service_worker_context_unittest.cc19
-rw-r--r--content/browser/service_worker/service_worker_version.cc34
-rw-r--r--content/browser/service_worker/service_worker_version.h6
6 files changed, 55 insertions, 15 deletions
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 24d2a95..891fc22 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -22,6 +22,8 @@ struct SecondGreater {
} // namespace
EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
+ if (status_ == STARTING || status_ == RUNNING)
+ Stop();
registry_->RemoveWorker(process_id_, embedded_worker_id_);
}
diff --git a/content/browser/service_worker/embedded_worker_registry.cc b/content/browser/service_worker/embedded_worker_registry.cc
index a859268..6889672 100644
--- a/content/browser/service_worker/embedded_worker_registry.cc
+++ b/content/browser/service_worker/embedded_worker_registry.cc
@@ -249,13 +249,14 @@ void EmbeddedWorkerRegistry::StartWorkerWithProcessId(
}
ServiceWorkerStatusCode EmbeddedWorkerRegistry::Send(
- int process_id, IPC::Message* message) {
+ int process_id, IPC::Message* message_ptr) {
+ scoped_ptr<IPC::Message> message(message_ptr);
if (!context_)
return SERVICE_WORKER_ERROR_ABORT;
ProcessToSenderMap::iterator found = process_sender_map_.find(process_id);
if (found == process_sender_map_.end())
return SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND;
- if (!found->second->Send(message))
+ if (!found->second->Send(message.release()))
return SERVICE_WORKER_ERROR_IPC_FAILED;
return SERVICE_WORKER_OK;
}
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index 3d8790f..c43808b 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -154,8 +154,8 @@ void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
void EmbeddedWorkerTestHelper::SimulateWorkerStopped(
int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
- ASSERT_TRUE(worker != NULL);
- registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
+ if (worker != NULL)
+ registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
}
void EmbeddedWorkerTestHelper::SimulateSend(
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index 6a8088b..1afb47d 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -13,6 +13,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
@@ -150,11 +151,15 @@ TEST_F(ServiceWorkerContextTest, Register) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
+ EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StartWorker::ID));
EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_InstallEvent::ID));
EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StopWorker::ID));
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
@@ -189,11 +194,15 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
+ EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StartWorker::ID));
EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_InstallEvent::ID));
EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StopWorker::ID));
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
@@ -228,11 +237,15 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
+ EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StartWorker::ID));
EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_InstallEvent::ID));
EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_ActivateEvent::ID));
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ EmbeddedWorkerMsg_StopWorker::ID));
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 0bcec89..274daf0 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -11,6 +11,7 @@
#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_registration.h"
+#include "content/browser/service_worker/service_worker_utils.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
@@ -22,6 +23,12 @@ typedef ServiceWorkerVersion::MessageCallback MessageCallback;
namespace {
+// Default delay to stop the worker context after all documents that
+// are associated to the worker are closed.
+// (Note that if all references to the version is dropped the worker
+// is also stopped without delay)
+const int64 kStopWorkerDelay = 30; // 30 secs.
+
void RunSoon(const base::Closure& callback) {
if (!callback.is_null())
base::MessageLoop::current()->PostTask(FROM_HERE, callback);
@@ -103,12 +110,10 @@ ServiceWorkerVersion::ServiceWorkerVersion(
}
ServiceWorkerVersion::~ServiceWorkerVersion() {
- if (embedded_worker_) {
- embedded_worker_->RemoveListener(this);
- embedded_worker_.reset();
- }
+ embedded_worker_->RemoveListener(this);
if (context_)
context_->RemoveLiveVersion(version_id_);
+ // EmbeddedWorker's dtor sends StopWorker if it's still running.
}
void ServiceWorkerVersion::SetStatus(Status status) {
@@ -148,7 +153,6 @@ void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) {
void ServiceWorkerVersion::StartWorkerWithCandidateProcesses(
const std::vector<int>& possible_process_ids,
const StatusCallback& callback) {
- DCHECK(embedded_worker_);
switch (running_status()) {
case RUNNING:
RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
@@ -173,7 +177,6 @@ void ServiceWorkerVersion::StartWorkerWithCandidateProcesses(
}
void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
- DCHECK(embedded_worker_);
if (running_status() == STOPPED) {
RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
return;
@@ -190,7 +193,6 @@ void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
void ServiceWorkerVersion::SendMessage(
const IPC::Message& message, const StatusCallback& callback) {
- DCHECK(embedded_worker_);
if (running_status() != RUNNING) {
// Schedule calling this method after starting the worker.
StartWorker(base::Bind(&RunTaskAfterStartWorker,
@@ -318,6 +320,8 @@ void ServiceWorkerVersion::AddControllee(
int controllee_id = controllee_by_id_.Add(provider_host);
controllee_map_[provider_host] = controllee_id;
AddProcessToWorker(provider_host->process_id());
+ if (stop_worker_timer_.IsRunning())
+ stop_worker_timer_.Stop();
}
void ServiceWorkerVersion::RemoveControllee(
@@ -327,6 +331,8 @@ void ServiceWorkerVersion::RemoveControllee(
controllee_by_id_.Remove(found->second);
controllee_map_.erase(found);
RemoveProcessFromWorker(provider_host->process_id());
+ if (!HasControllee())
+ ScheduleStopWorker();
// TODO(kinuko): Fire NoControllees notification when the # of controllees
// reaches 0, so that a new pending version can be activated (which will
// deactivate this version).
@@ -565,4 +571,18 @@ void ServiceWorkerVersion::OnPostMessageToDocument(
provider_host->PostMessage(message, sent_message_port_ids);
}
+void ServiceWorkerVersion::ScheduleStopWorker() {
+ if (running_status() != RUNNING)
+ return;
+ if (stop_worker_timer_.IsRunning()) {
+ stop_worker_timer_.Reset();
+ return;
+ }
+ stop_worker_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(kStopWorkerDelay),
+ base::Bind(&ServiceWorkerVersion::StopWorker,
+ weak_factory_.GetWeakPtr(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)));
+}
+
} // namespace content
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 56c5cf2..e0dde76 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
+#include "base/timer/timer.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/service_worker_script_cache_map.h"
#include "content/common/content_export.h"
@@ -188,7 +189,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
void AddPendingControllee(ServiceWorkerProviderHost* provider_host);
void RemovePendingControllee(ServiceWorkerProviderHost* provider_host);
- // Returns if it has (non-pending) controllee.
+ // Returns if it has controllee.
bool HasControllee() const { return !controllee_map_.empty(); }
// Adds and removes Listeners.
@@ -240,6 +241,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
const base::string16& message,
const std::vector<int>& sent_message_port_ids);
+ void ScheduleStopWorker();
+
const int64 version_id_;
int64 registration_id_;
GURL script_url_;
@@ -261,6 +264,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
base::WeakPtr<ServiceWorkerContextCore> context_;
ObserverList<Listener> listeners_;
ServiceWorkerScriptCacheMap script_cache_map_;
+ base::OneShotTimer<ServiceWorkerVersion> stop_worker_timer_;
base::WeakPtrFactory<ServiceWorkerVersion> weak_factory_;