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. | |
| 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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 ServiceWorkerRegistration* registration, | 278 ServiceWorkerRegistration* registration, |
| 273 const GURL& script_url, | 279 const GURL& script_url, |
| 274 int64 version_id, | 280 int64 version_id, |
| 275 base::WeakPtr<ServiceWorkerContextCore> context) | 281 base::WeakPtr<ServiceWorkerContextCore> context) |
| 276 : version_id_(version_id), | 282 : version_id_(version_id), |
| 277 registration_id_(kInvalidServiceWorkerVersionId), | 283 registration_id_(kInvalidServiceWorkerVersionId), |
| 278 script_url_(script_url), | 284 script_url_(script_url), |
| 279 status_(NEW), | 285 status_(NEW), |
| 280 context_(context), | 286 context_(context), |
| 281 script_cache_map_(this, context), | 287 script_cache_map_(this, context), |
| 288 ping_timed_out_(false), | |
| 282 is_doomed_(false), | 289 is_doomed_(false), |
| 283 skip_waiting_(false), | 290 skip_waiting_(false), |
| 284 weak_factory_(this) { | 291 weak_factory_(this) { |
| 285 DCHECK(context_); | 292 DCHECK(context_); |
| 286 DCHECK(registration); | 293 DCHECK(registration); |
| 287 if (registration) { | 294 if (registration) { |
| 288 registration_id_ = registration->id(); | 295 registration_id_ = registration->id(); |
| 289 scope_ = registration->pattern(); | 296 scope_ = registration->pattern(); |
| 290 } | 297 } |
| 291 context_->AddLiveVersion(this); | 298 context_->AddLiveVersion(this); |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 780 void ServiceWorkerVersion::Doom() { | 787 void ServiceWorkerVersion::Doom() { |
| 781 if (is_doomed_) | 788 if (is_doomed_) |
| 782 return; | 789 return; |
| 783 is_doomed_ = true; | 790 is_doomed_ = true; |
| 784 if (!HasControllee()) | 791 if (!HasControllee()) |
| 785 DoomInternal(); | 792 DoomInternal(); |
| 786 } | 793 } |
| 787 | 794 |
| 788 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { | 795 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { |
| 789 embedded_worker()->set_devtools_attached(attached); | 796 embedded_worker()->set_devtools_attached(attached); |
| 790 if (!attached && !stop_worker_timer_.IsRunning()) { | 797 if (attached) |
| 791 // If devtools is detached from this version and stop-worker-timer is not | 798 return; |
| 792 // running, try scheduling stop-worker-timer now. | 799 // If devtools is detached try scheduling the timers for stopping the worker |
| 800 // now. | |
| 801 if (!stop_worker_timer_.IsRunning()) | |
| 793 ScheduleStopWorker(); | 802 ScheduleStopWorker(); |
| 794 } | 803 if (!ping_worker_timer_.IsRunning()) |
| 804 SchedulePingWorker(); | |
| 795 } | 805 } |
| 796 | 806 |
| 797 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( | 807 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( |
| 798 const net::HttpResponseInfo& http_info) { | 808 const net::HttpResponseInfo& http_info) { |
| 799 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); | 809 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); |
| 800 } | 810 } |
| 801 | 811 |
| 802 const net::HttpResponseInfo* | 812 const net::HttpResponseInfo* |
| 803 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { | 813 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { |
| 804 return main_script_http_info_.get(); | 814 return main_script_http_info_.get(); |
| 805 } | 815 } |
| 806 | 816 |
| 817 void ServiceWorkerVersion::OnScriptLoaded() { | |
| 818 DCHECK_EQ(STARTING, running_status()); | |
| 819 SchedulePingWorker(); | |
|
michaeln
2015/02/11 01:02:21
Would it make sense to only turn the ping monitor
falken
2015/02/11 16:10:24
That's a good thing to think about. In practice, p
| |
| 820 } | |
| 821 | |
| 807 void ServiceWorkerVersion::OnStarted() { | 822 void ServiceWorkerVersion::OnStarted() { |
| 808 DCHECK_EQ(RUNNING, running_status()); | 823 DCHECK_EQ(RUNNING, running_status()); |
| 809 DCHECK(cache_listener_.get()); | 824 DCHECK(cache_listener_.get()); |
| 810 ScheduleStopWorker(); | 825 ScheduleStopWorker(); |
| 811 | 826 |
| 812 // Fire all start callbacks. | 827 // Fire all start callbacks. |
| 813 scoped_refptr<ServiceWorkerVersion> protect(this); | 828 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 814 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); | 829 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); |
| 815 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); | 830 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); |
| 816 } | 831 } |
| 817 | 832 |
| 818 void ServiceWorkerVersion::OnStopped( | 833 void ServiceWorkerVersion::OnStopped( |
| 819 EmbeddedWorkerInstance::Status old_status) { | 834 EmbeddedWorkerInstance::Status old_status) { |
| 820 DCHECK_EQ(STOPPED, running_status()); | 835 DCHECK_EQ(STOPPED, running_status()); |
| 821 scoped_refptr<ServiceWorkerVersion> protect(this); | 836 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 822 | 837 |
| 823 bool should_restart = !is_doomed() && !start_callbacks_.empty() && | 838 bool should_restart = !is_doomed() && !start_callbacks_.empty() && |
| 824 (old_status != EmbeddedWorkerInstance::STARTING); | 839 (old_status != EmbeddedWorkerInstance::STARTING); |
| 825 | 840 |
| 841 ping_worker_timer_.Stop(); | |
| 842 if (ping_timed_out_) | |
| 843 should_restart = false; | |
| 844 | |
| 826 // Fire all stop callbacks. | 845 // Fire all stop callbacks. |
| 827 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); | 846 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); |
| 828 | 847 |
| 829 if (!should_restart) { | 848 if (!should_restart) { |
| 830 // Let all start callbacks fail. | 849 // Let all start callbacks fail. |
| 831 RunCallbacks(this, &start_callbacks_, | 850 RunCallbacks(this, &start_callbacks_, |
| 832 SERVICE_WORKER_ERROR_START_WORKER_FAILED); | 851 SERVICE_WORKER_ERROR_START_WORKER_FAILED); |
| 833 } | 852 } |
| 834 | 853 |
| 835 // Let all message callbacks fail (this will also fire and clear all | 854 // 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... | |
| 925 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, | 944 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, |
| 926 OnOpenWindow) | 945 OnOpenWindow) |
| 927 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, | 946 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, |
| 928 OnPostMessageToDocument) | 947 OnPostMessageToDocument) |
| 929 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, | 948 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, |
| 930 OnFocusClient) | 949 OnFocusClient) |
| 931 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, | 950 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, |
| 932 OnSkipWaiting) | 951 OnSkipWaiting) |
| 933 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, | 952 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, |
| 934 OnClaimClients) | 953 OnClaimClients) |
| 954 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_Pong, OnPongFromWorker) | |
| 935 IPC_MESSAGE_UNHANDLED(handled = false) | 955 IPC_MESSAGE_UNHANDLED(handled = false) |
| 936 IPC_END_MESSAGE_MAP() | 956 IPC_END_MESSAGE_MAP() |
| 937 return handled; | 957 return handled; |
| 938 } | 958 } |
| 939 | 959 |
| 940 void ServiceWorkerVersion::OnStartMessageSent( | 960 void ServiceWorkerVersion::OnStartMessageSent( |
| 941 ServiceWorkerStatusCode status) { | 961 ServiceWorkerStatusCode status) { |
| 942 if (status != SERVICE_WORKER_OK) | 962 if (status != SERVICE_WORKER_OK) |
| 943 RunCallbacks(this, &start_callbacks_, status); | 963 RunCallbacks(this, &start_callbacks_, status); |
| 944 } | 964 } |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1315 | 1335 |
| 1316 ServiceWorkerRegistration* registration = | 1336 ServiceWorkerRegistration* registration = |
| 1317 context_->GetLiveRegistration(registration_id_); | 1337 context_->GetLiveRegistration(registration_id_); |
| 1318 if (!registration) { | 1338 if (!registration) { |
| 1319 callback.Run(SERVICE_WORKER_ERROR_ABORT); | 1339 callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| 1320 return; | 1340 return; |
| 1321 } | 1341 } |
| 1322 registration->ClaimClients(callback); | 1342 registration->ClaimClients(callback); |
| 1323 } | 1343 } |
| 1324 | 1344 |
| 1345 void ServiceWorkerVersion::OnPongFromWorker() { | |
| 1346 ping_worker_timer_.Stop(); | |
| 1347 SchedulePingWorker(); | |
| 1348 } | |
| 1349 | |
| 1325 void ServiceWorkerVersion::DidClaimClients( | 1350 void ServiceWorkerVersion::DidClaimClients( |
| 1326 int request_id, ServiceWorkerStatusCode status) { | 1351 int request_id, ServiceWorkerStatusCode status) { |
| 1327 if (status == SERVICE_WORKER_ERROR_STATE) { | 1352 if (status == SERVICE_WORKER_ERROR_STATE) { |
| 1328 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( | 1353 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( |
| 1329 request_id, blink::WebServiceWorkerError::ErrorTypeState, | 1354 request_id, blink::WebServiceWorkerError::ErrorTypeState, |
| 1330 base::ASCIIToUTF16(kClaimClientsStateErrorMesage))); | 1355 base::ASCIIToUTF16(kClaimClientsStateErrorMesage))); |
| 1331 return; | 1356 return; |
| 1332 } | 1357 } |
| 1333 if (status == SERVICE_WORKER_ERROR_ABORT) { | 1358 if (status == SERVICE_WORKER_ERROR_ABORT) { |
| 1334 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( | 1359 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1353 | 1378 |
| 1354 // We can get info for a frame that was navigating end ended up with a | 1379 // We can get info for a frame that was navigating end ended up with a |
| 1355 // different URL than expected. In such case, we should make sure to not | 1380 // different URL than expected. In such case, we should make sure to not |
| 1356 // expose cross-origin WindowClient. | 1381 // expose cross-origin WindowClient. |
| 1357 if (info.url.GetOrigin() != script_url_.GetOrigin()) | 1382 if (info.url.GetOrigin() != script_url_.GetOrigin()) |
| 1358 return; | 1383 return; |
| 1359 | 1384 |
| 1360 callback->AddClientInfo(client_id, info); | 1385 callback->AddClientInfo(client_id, info); |
| 1361 } | 1386 } |
| 1362 | 1387 |
| 1388 void ServiceWorkerVersion::PingWorker() { | |
| 1389 if (running_status() != STARTING && running_status() != RUNNING) | |
| 1390 return; | |
| 1391 ServiceWorkerStatusCode status = | |
| 1392 embedded_worker_->SendMessage(ServiceWorkerMsg_Ping()); | |
| 1393 if (status != SERVICE_WORKER_OK) { | |
| 1394 OnPingTimeout(); | |
| 1395 return; | |
| 1396 } | |
| 1397 ping_worker_timer_.Start(FROM_HERE, | |
| 1398 base::TimeDelta::FromSeconds(kPingTimeoutTime), | |
| 1399 base::Bind(&ServiceWorkerVersion::OnPingTimeout, | |
| 1400 weak_factory_.GetWeakPtr())); | |
| 1401 } | |
| 1402 | |
| 1403 void ServiceWorkerVersion::SchedulePingWorker() { | |
| 1404 DCHECK(!ping_worker_timer_.IsRunning()); | |
| 1405 ping_timed_out_ = false; | |
| 1406 ping_worker_timer_.Start(FROM_HERE, | |
| 1407 base::TimeDelta::FromSeconds(kPingIntervalTime), | |
| 1408 base::Bind(&ServiceWorkerVersion::PingWorker, | |
| 1409 weak_factory_.GetWeakPtr())); | |
| 1410 } | |
| 1411 | |
| 1412 void ServiceWorkerVersion::OnPingTimeout() { | |
| 1413 if (running_status() != STARTING && running_status() != RUNNING) | |
| 1414 return; | |
| 1415 ping_timed_out_ = true; | |
| 1416 StopWorkerIfIdle(); | |
|
kinuko
2015/02/10 09:15:52
In this case we should probably show some error or
falken
2015/02/11 16:10:24
Yes I agree. I don't know a good place we'd show t
| |
| 1417 } | |
| 1418 | |
| 1363 void ServiceWorkerVersion::ScheduleStopWorker() { | 1419 void ServiceWorkerVersion::ScheduleStopWorker() { |
| 1364 if (running_status() != RUNNING) | 1420 if (running_status() != RUNNING) |
| 1365 return; | 1421 return; |
| 1366 stop_worker_timer_.Stop(); | 1422 stop_worker_timer_.Stop(); |
| 1367 stop_worker_timer_.Start( | 1423 stop_worker_timer_.Start( |
| 1368 FROM_HERE, base::TimeDelta::FromSeconds( | 1424 FROM_HERE, base::TimeDelta::FromSeconds( |
| 1369 is_doomed_ ? kStopDoomedWorkerDelay : kStopWorkerDelay), | 1425 is_doomed_ ? kStopDoomedWorkerDelay : kStopWorkerDelay), |
| 1370 base::Bind(&ServiceWorkerVersion::StopWorkerIfIdle, | 1426 base::Bind(&ServiceWorkerVersion::StopWorkerIfIdle, |
| 1371 weak_factory_.GetWeakPtr())); | 1427 weak_factory_.GetWeakPtr())); |
| 1372 } | 1428 } |
| 1373 | 1429 |
| 1374 void ServiceWorkerVersion::StopWorkerIfIdle() { | 1430 void ServiceWorkerVersion::StopWorkerIfIdle() { |
| 1375 // Reschedule the stop the worker while there're inflight requests. | 1431 if (HasInflightRequests() && !ping_timed_out_) { |
| 1376 // (Note: we'll probably need to revisit this so that we can kill 'bad' SW. | |
| 1377 // See https://github.com/slightlyoff/ServiceWorker/issues/527) | |
| 1378 if (HasInflightRequests()) { | |
| 1379 ScheduleStopWorker(); | 1432 ScheduleStopWorker(); |
| 1380 return; | 1433 return; |
| 1381 } | 1434 } |
| 1382 if (running_status() == STOPPED || running_status() == STOPPING || | 1435 if (running_status() == STOPPED || running_status() == STOPPING || |
| 1383 !stop_callbacks_.empty()) { | 1436 !stop_callbacks_.empty()) { |
| 1384 return; | 1437 return; |
| 1385 } | 1438 } |
| 1386 embedded_worker_->StopIfIdle(); | 1439 embedded_worker_->StopIfIdle(); |
| 1387 } | 1440 } |
| 1388 | 1441 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1417 int request_id) { | 1470 int request_id) { |
| 1418 callbacks->Remove(request_id); | 1471 callbacks->Remove(request_id); |
| 1419 if (is_doomed_) { | 1472 if (is_doomed_) { |
| 1420 // The stop should be already scheduled, but try to stop immediately, in | 1473 // The stop should be already scheduled, but try to stop immediately, in |
| 1421 // order to release worker resources soon. | 1474 // order to release worker resources soon. |
| 1422 StopWorkerIfIdle(); | 1475 StopWorkerIfIdle(); |
| 1423 } | 1476 } |
| 1424 } | 1477 } |
| 1425 | 1478 |
| 1426 } // namespace content | 1479 } // namespace content |
| OLD | NEW |