Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Side by Side Diff: content/browser/service_worker/service_worker_version.cc

Issue 912753002: Stop Service Workers that execute JavaScript for too long. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix timeout value Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/service_worker/service_worker_version.h" 5 #include "content/browser/service_worker/service_worker_version.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/ref_counted.h" 8 #include "base/memory/ref_counted.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/strings/string16.h" 10 #include "base/strings/string16.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 // (Note that if all references to the version is dropped the worker 77 // (Note that if all references to the version is dropped the worker
78 // is also stopped without delay) 78 // is also stopped without delay)
79 const int64 kStopWorkerDelay = 30; // 30 secs. 79 const int64 kStopWorkerDelay = 30; // 30 secs.
80 80
81 // Delay for attempting to stop a doomed worker with in-flight requests. 81 // Delay for attempting to stop a doomed worker with in-flight requests.
82 const int64 kStopDoomedWorkerDelay = 5; // 5 secs. 82 const int64 kStopDoomedWorkerDelay = 5; // 5 secs.
83 83
84 // Default delay for scheduled update. 84 // Default delay for scheduled update.
85 const int kUpdateDelaySeconds = 1; 85 const int kUpdateDelaySeconds = 1;
86 86
87 // Delay between sending pings to the worker.
88 const int kPingIntervalTime = 10; // 10 secs.
89
90 // Timeout for waiting for a response to a ping.
91 const int kPingTimeoutTime = 30; // 30 secs.
kinuko 2015/02/18 13:06:25 nit: can you include these numbers in the CL descr
falken 2015/02/23 05:00:06 Done.
92
87 const char kClaimClientsStateErrorMesage[] = 93 const char kClaimClientsStateErrorMesage[] =
88 "Only the active worker can claim clients."; 94 "Only the active worker can claim clients.";
89 95
90 const char kClaimClientsShutdownErrorMesage[] = 96 const char kClaimClientsShutdownErrorMesage[] =
91 "Failed to claim clients due to Service Worker system shutdown."; 97 "Failed to claim clients due to Service Worker system shutdown.";
92 98
93 void RunSoon(const base::Closure& callback) { 99 void RunSoon(const base::Closure& callback) {
94 if (!callback.is_null()) 100 if (!callback.is_null())
95 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 101 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
96 } 102 }
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 ServiceWorkerRegistration* registration, 283 ServiceWorkerRegistration* registration,
278 const GURL& script_url, 284 const GURL& script_url,
279 int64 version_id, 285 int64 version_id,
280 base::WeakPtr<ServiceWorkerContextCore> context) 286 base::WeakPtr<ServiceWorkerContextCore> context)
281 : version_id_(version_id), 287 : version_id_(version_id),
282 registration_id_(kInvalidServiceWorkerVersionId), 288 registration_id_(kInvalidServiceWorkerVersionId),
283 script_url_(script_url), 289 script_url_(script_url),
284 status_(NEW), 290 status_(NEW),
285 context_(context), 291 context_(context),
286 script_cache_map_(this, context), 292 script_cache_map_(this, context),
293 ping_timed_out_(false),
287 is_doomed_(false), 294 is_doomed_(false),
288 skip_waiting_(false), 295 skip_waiting_(false),
289 weak_factory_(this) { 296 weak_factory_(this) {
290 DCHECK(context_); 297 DCHECK(context_);
291 DCHECK(registration); 298 DCHECK(registration);
292 if (registration) { 299 if (registration) {
293 registration_id_ = registration->id(); 300 registration_id_ = registration->id();
294 scope_ = registration->pattern(); 301 scope_ = registration->pattern();
295 } 302 }
296 context_->AddLiveVersion(this); 303 context_->AddLiveVersion(this);
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 void ServiceWorkerVersion::Doom() { 792 void ServiceWorkerVersion::Doom() {
786 if (is_doomed_) 793 if (is_doomed_)
787 return; 794 return;
788 is_doomed_ = true; 795 is_doomed_ = true;
789 if (!HasControllee()) 796 if (!HasControllee())
790 DoomInternal(); 797 DoomInternal();
791 } 798 }
792 799
793 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { 800 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
794 embedded_worker()->set_devtools_attached(attached); 801 embedded_worker()->set_devtools_attached(attached);
795 if (!attached && !stop_worker_timer_.IsRunning()) { 802 if (attached)
796 // If devtools is detached from this version and stop-worker-timer is not 803 return;
797 // running, try scheduling stop-worker-timer now. 804 // If devtools is detached try scheduling the timers for stopping the worker
805 // now.
806 if (!stop_worker_timer_.IsRunning())
798 ScheduleStopWorker(); 807 ScheduleStopWorker();
799 } 808 if (!ping_worker_timer_.IsRunning())
809 StartPingWorker();
800 } 810 }
801 811
802 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( 812 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
803 const net::HttpResponseInfo& http_info) { 813 const net::HttpResponseInfo& http_info) {
804 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); 814 main_script_http_info_.reset(new net::HttpResponseInfo(http_info));
805 } 815 }
806 816
807 const net::HttpResponseInfo* 817 const net::HttpResponseInfo*
808 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { 818 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
809 return main_script_http_info_.get(); 819 return main_script_http_info_.get();
810 } 820 }
811 821
822 void ServiceWorkerVersion::OnScriptLoaded() {
823 DCHECK_EQ(STARTING, running_status());
824 StartPingWorker();
825 }
826
812 void ServiceWorkerVersion::OnStarted() { 827 void ServiceWorkerVersion::OnStarted() {
813 DCHECK_EQ(RUNNING, running_status()); 828 DCHECK_EQ(RUNNING, running_status());
814 DCHECK(cache_listener_.get()); 829 DCHECK(cache_listener_.get());
815 ScheduleStopWorker(); 830 ScheduleStopWorker();
816 831
817 // Fire all start callbacks. 832 // Fire all start callbacks.
818 scoped_refptr<ServiceWorkerVersion> protect(this); 833 scoped_refptr<ServiceWorkerVersion> protect(this);
819 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); 834 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK);
820 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); 835 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this));
821 } 836 }
822 837
823 void ServiceWorkerVersion::OnStopped( 838 void ServiceWorkerVersion::OnStopped(
824 EmbeddedWorkerInstance::Status old_status) { 839 EmbeddedWorkerInstance::Status old_status) {
825 DCHECK_EQ(STOPPED, running_status()); 840 DCHECK_EQ(STOPPED, running_status());
826 scoped_refptr<ServiceWorkerVersion> protect(this); 841 scoped_refptr<ServiceWorkerVersion> protect(this);
827 842
828 bool should_restart = !is_doomed() && !start_callbacks_.empty() && 843 bool should_restart = !is_doomed() && !start_callbacks_.empty() &&
829 (old_status != EmbeddedWorkerInstance::STARTING); 844 (old_status != EmbeddedWorkerInstance::STARTING);
830 845
846 ping_worker_timer_.Stop();
847 if (ping_timed_out_)
848 should_restart = false;
849
831 // Fire all stop callbacks. 850 // Fire all stop callbacks.
832 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); 851 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK);
833 852
834 if (!should_restart) { 853 if (!should_restart) {
835 // Let all start callbacks fail. 854 // Let all start callbacks fail.
836 RunCallbacks(this, &start_callbacks_, 855 RunCallbacks(this, &start_callbacks_,
837 SERVICE_WORKER_ERROR_START_WORKER_FAILED); 856 SERVICE_WORKER_ERROR_START_WORKER_FAILED);
838 } 857 }
839 858
840 // Let all message callbacks fail (this will also fire and clear all 859 // Let all message callbacks fail (this will also fire and clear all
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, 949 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow,
931 OnOpenWindow) 950 OnOpenWindow)
932 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, 951 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument,
933 OnPostMessageToDocument) 952 OnPostMessageToDocument)
934 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, 953 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient,
935 OnFocusClient) 954 OnFocusClient)
936 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, 955 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting,
937 OnSkipWaiting) 956 OnSkipWaiting)
938 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, 957 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients,
939 OnClaimClients) 958 OnClaimClients)
959 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_Pong, OnPongFromWorker)
940 IPC_MESSAGE_UNHANDLED(handled = false) 960 IPC_MESSAGE_UNHANDLED(handled = false)
941 IPC_END_MESSAGE_MAP() 961 IPC_END_MESSAGE_MAP()
942 return handled; 962 return handled;
943 } 963 }
944 964
945 void ServiceWorkerVersion::OnStartMessageSent( 965 void ServiceWorkerVersion::OnStartMessageSent(
946 ServiceWorkerStatusCode status) { 966 ServiceWorkerStatusCode status) {
947 if (status != SERVICE_WORKER_OK) 967 if (status != SERVICE_WORKER_OK)
948 RunCallbacks(this, &start_callbacks_, status); 968 RunCallbacks(this, &start_callbacks_, status);
949 } 969 }
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 1340
1321 ServiceWorkerRegistration* registration = 1341 ServiceWorkerRegistration* registration =
1322 context_->GetLiveRegistration(registration_id_); 1342 context_->GetLiveRegistration(registration_id_);
1323 if (!registration) { 1343 if (!registration) {
1324 callback.Run(SERVICE_WORKER_ERROR_ABORT); 1344 callback.Run(SERVICE_WORKER_ERROR_ABORT);
1325 return; 1345 return;
1326 } 1346 }
1327 registration->ClaimClients(callback); 1347 registration->ClaimClients(callback);
1328 } 1348 }
1329 1349
1350 void ServiceWorkerVersion::OnPongFromWorker() {
1351 if (ping_timed_out_)
1352 return;
1353 SchedulePingWorker();
1354 }
1355
1330 void ServiceWorkerVersion::DidClaimClients( 1356 void ServiceWorkerVersion::DidClaimClients(
1331 int request_id, ServiceWorkerStatusCode status) { 1357 int request_id, ServiceWorkerStatusCode status) {
1332 if (status == SERVICE_WORKER_ERROR_STATE) { 1358 if (status == SERVICE_WORKER_ERROR_STATE) {
1333 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( 1359 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError(
1334 request_id, blink::WebServiceWorkerError::ErrorTypeState, 1360 request_id, blink::WebServiceWorkerError::ErrorTypeState,
1335 base::ASCIIToUTF16(kClaimClientsStateErrorMesage))); 1361 base::ASCIIToUTF16(kClaimClientsStateErrorMesage)));
1336 return; 1362 return;
1337 } 1363 }
1338 if (status == SERVICE_WORKER_ERROR_ABORT) { 1364 if (status == SERVICE_WORKER_ERROR_ABORT) {
1339 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( 1365 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError(
(...skipping 18 matching lines...) Expand all
1358 1384
1359 // We can get info for a frame that was navigating end ended up with a 1385 // We can get info for a frame that was navigating end ended up with a
1360 // different URL than expected. In such case, we should make sure to not 1386 // different URL than expected. In such case, we should make sure to not
1361 // expose cross-origin WindowClient. 1387 // expose cross-origin WindowClient.
1362 if (info.url.GetOrigin() != script_url_.GetOrigin()) 1388 if (info.url.GetOrigin() != script_url_.GetOrigin())
1363 return; 1389 return;
1364 1390
1365 callback->AddClientInfo(client_id, info); 1391 callback->AddClientInfo(client_id, info);
1366 } 1392 }
1367 1393
1394 void ServiceWorkerVersion::PingWorker() {
1395 if (running_status() != STARTING && running_status() != RUNNING)
1396 return;
1397 ServiceWorkerStatusCode status =
1398 embedded_worker_->SendMessage(ServiceWorkerMsg_Ping());
1399 if (status != SERVICE_WORKER_OK) {
1400 OnPingTimeout();
kinuko 2015/02/18 13:06:25 Call this here feels a bit weird to me, especially
falken 2015/02/23 05:00:06 Hmm, actually what do you think is best to do here
1401 return;
1402 }
1403 ping_worker_timer_.Start(FROM_HERE,
1404 base::TimeDelta::FromSeconds(kPingTimeoutTime),
1405 base::Bind(&ServiceWorkerVersion::OnPingTimeout,
1406 weak_factory_.GetWeakPtr()));
1407 }
1408
1409 void ServiceWorkerVersion::StartPingWorker() {
1410 ping_timed_out_ = false;
1411 SchedulePingWorker();
1412 }
1413
1414 void ServiceWorkerVersion::SchedulePingWorker() {
1415 DCHECK(!ping_timed_out_);
1416 ping_worker_timer_.Stop();
1417 ping_worker_timer_.Start(FROM_HERE,
1418 base::TimeDelta::FromSeconds(kPingIntervalTime),
1419 base::Bind(&ServiceWorkerVersion::PingWorker,
1420 weak_factory_.GetWeakPtr()));
1421 }
1422
1423 void ServiceWorkerVersion::OnPingTimeout() {
1424 if (running_status() != STARTING && running_status() != RUNNING)
1425 return;
1426 ping_timed_out_ = true;
1427 // TODO(falken): Show a message to the developer that the SW was stopped due
1428 // to timeout (crbug.com/457968).
1429 StopWorkerIfIdle();
1430 }
1431
1368 void ServiceWorkerVersion::ScheduleStopWorker() { 1432 void ServiceWorkerVersion::ScheduleStopWorker() {
1369 if (running_status() != RUNNING) 1433 if (running_status() != RUNNING)
1370 return; 1434 return;
1371 stop_worker_timer_.Stop(); 1435 stop_worker_timer_.Stop();
1372 stop_worker_timer_.Start( 1436 stop_worker_timer_.Start(
1373 FROM_HERE, base::TimeDelta::FromSeconds( 1437 FROM_HERE, base::TimeDelta::FromSeconds(
1374 is_doomed_ ? kStopDoomedWorkerDelay : kStopWorkerDelay), 1438 is_doomed_ ? kStopDoomedWorkerDelay : kStopWorkerDelay),
1375 base::Bind(&ServiceWorkerVersion::StopWorkerIfIdle, 1439 base::Bind(&ServiceWorkerVersion::StopWorkerIfIdle,
1376 weak_factory_.GetWeakPtr())); 1440 weak_factory_.GetWeakPtr()));
1377 } 1441 }
1378 1442
1379 void ServiceWorkerVersion::StopWorkerIfIdle() { 1443 void ServiceWorkerVersion::StopWorkerIfIdle() {
1380 // Reschedule the stop the worker while there're inflight requests. 1444 if (HasInflightRequests() && !ping_timed_out_) {
1381 // (Note: we'll probably need to revisit this so that we can kill 'bad' SW.
1382 // See https://github.com/slightlyoff/ServiceWorker/issues/527)
1383 if (HasInflightRequests()) {
1384 ScheduleStopWorker(); 1445 ScheduleStopWorker();
1385 return; 1446 return;
1386 } 1447 }
1387 if (running_status() == STOPPED || running_status() == STOPPING || 1448 if (running_status() == STOPPED || running_status() == STOPPING ||
1388 !stop_callbacks_.empty()) { 1449 !stop_callbacks_.empty()) {
1389 return; 1450 return;
1390 } 1451 }
1391 embedded_worker_->StopIfIdle(); 1452 embedded_worker_->StopIfIdle();
1392 } 1453 }
1393 1454
(...skipping 28 matching lines...) Expand all
1422 int request_id) { 1483 int request_id) {
1423 callbacks->Remove(request_id); 1484 callbacks->Remove(request_id);
1424 if (is_doomed_) { 1485 if (is_doomed_) {
1425 // The stop should be already scheduled, but try to stop immediately, in 1486 // The stop should be already scheduled, but try to stop immediately, in
1426 // order to release worker resources soon. 1487 // order to release worker resources soon.
1427 StopWorkerIfIdle(); 1488 StopWorkerIfIdle();
1428 } 1489 }
1429 } 1490 }
1430 1491
1431 } // namespace content 1492 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698