Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |