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 |