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/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 const int kUpdateDelaySeconds = 1; | 52 const int kUpdateDelaySeconds = 1; |
53 | 53 |
54 // Timeout for waiting for a response to a ping. | 54 // Timeout for waiting for a response to a ping. |
55 const int kPingTimeoutSeconds = 30; | 55 const int kPingTimeoutSeconds = 30; |
56 | 56 |
57 // Timeout for the worker to start. | 57 // Timeout for the worker to start. |
58 const int kStartWorkerTimeoutMinutes = 5; | 58 const int kStartWorkerTimeoutMinutes = 5; |
59 | 59 |
60 // If the SW was destructed while starting up, how many seconds it | 60 // If the SW was destructed while starting up, how many seconds it |
61 // had to start up for this to be considered a timeout occurrence. | 61 // had to start up for this to be considered a timeout occurrence. |
62 const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5; // 5 secs. | 62 const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5; // 5 secs. |
nhiroki
2015/03/10 00:37:10
nit: This comment "// 5 secs." would be pointless
falken
2015/03/10 06:56:36
Done.
| |
63 | 63 |
64 const char kClaimClientsStateErrorMesage[] = | 64 const char kClaimClientsStateErrorMesage[] = |
65 "Only the active worker can claim clients."; | 65 "Only the active worker can claim clients."; |
66 | 66 |
67 const char kClaimClientsShutdownErrorMesage[] = | 67 const char kClaimClientsShutdownErrorMesage[] = |
68 "Failed to claim clients due to Service Worker system shutdown."; | 68 "Failed to claim clients due to Service Worker system shutdown."; |
69 | 69 |
70 void RunSoon(const base::Closure& callback) { | 70 void RunSoon(const base::Closure& callback) { |
71 if (!callback.is_null()) | 71 if (!callback.is_null()) |
72 base::MessageLoop::current()->PostTask(FROM_HERE, callback); | 72 base::MessageLoop::current()->PostTask(FROM_HERE, callback); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 ServiceWorkerRegistration* registration, | 300 ServiceWorkerRegistration* registration, |
301 const GURL& script_url, | 301 const GURL& script_url, |
302 int64 version_id, | 302 int64 version_id, |
303 base::WeakPtr<ServiceWorkerContextCore> context) | 303 base::WeakPtr<ServiceWorkerContextCore> context) |
304 : version_id_(version_id), | 304 : version_id_(version_id), |
305 registration_id_(kInvalidServiceWorkerVersionId), | 305 registration_id_(kInvalidServiceWorkerVersionId), |
306 script_url_(script_url), | 306 script_url_(script_url), |
307 status_(NEW), | 307 status_(NEW), |
308 context_(context), | 308 context_(context), |
309 script_cache_map_(this, context), | 309 script_cache_map_(this, context), |
310 ping_timed_out_(false), | 310 ping_state_(PING_NOT_STARTED), |
311 is_doomed_(false), | 311 is_doomed_(false), |
312 skip_waiting_(false), | 312 skip_waiting_(false), |
313 weak_factory_(this) { | 313 weak_factory_(this) { |
314 DCHECK(context_); | 314 DCHECK(context_); |
315 DCHECK(registration); | 315 DCHECK(registration); |
316 if (registration) { | 316 if (registration) { |
317 registration_id_ = registration->id(); | 317 registration_id_ = registration->id(); |
318 scope_ = registration->pattern(); | 318 scope_ = registration->pattern(); |
319 } | 319 } |
320 context_->AddLiveVersion(this); | 320 context_->AddLiveVersion(this); |
321 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); | 321 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); |
322 embedded_worker_->AddListener(this); | 322 embedded_worker_->AddListener(this); |
323 } | 323 } |
324 | 324 |
325 ServiceWorkerVersion::~ServiceWorkerVersion() { | 325 ServiceWorkerVersion::~ServiceWorkerVersion() { |
326 // The user may have closed the tab waiting for SW to start up. | 326 // The user may have closed the tab waiting for SW to start up. |
327 if (start_worker_timeout_timer_.IsRunning() && | 327 if (GetTickDuration(start_time_) > |
328 GetTickDuration(start_timing_) > | 328 base::TimeDelta::FromSeconds( |
329 base::TimeDelta::FromSeconds( | 329 kDestructedStartingWorkerTimeoutThresholdSeconds)) { |
330 kDestructedStartingWorkerTimeoutThresholdSeconds)) { | 330 DCHECK(timeout_timer_.IsRunning()); |
331 DCHECK(!embedded_worker_->devtools_attached()); | |
331 RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT); | 332 RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT); |
332 } | 333 } |
333 | 334 |
334 embedded_worker_->RemoveListener(this); | 335 embedded_worker_->RemoveListener(this); |
335 if (context_) | 336 if (context_) |
336 context_->RemoveLiveVersion(version_id_); | 337 context_->RemoveLiveVersion(version_id_); |
337 // EmbeddedWorker's dtor sends StopWorker if it's still running. | 338 // EmbeddedWorker's dtor sends StopWorker if it's still running. |
338 } | 339 } |
339 | 340 |
340 void ServiceWorkerVersion::SetStatus(Status status) { | 341 void ServiceWorkerVersion::SetStatus(Status status) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); | 386 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
386 return; | 387 return; |
387 } | 388 } |
388 switch (running_status()) { | 389 switch (running_status()) { |
389 case RUNNING: | 390 case RUNNING: |
390 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); | 391 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
391 return; | 392 return; |
392 case STOPPING: | 393 case STOPPING: |
393 case STOPPED: | 394 case STOPPED: |
394 case STARTING: | 395 case STARTING: |
395 if (!start_worker_timeout_timer_.IsRunning()) | 396 if (!timeout_timer_.IsRunning()) |
396 ScheduleStartWorkerTimeout(); | 397 StartTimeoutTimer(); |
397 start_callbacks_.push_back(callback); | 398 start_callbacks_.push_back(callback); |
398 if (running_status() == STOPPED) { | 399 if (running_status() == STOPPED) { |
399 DCHECK(!cache_listener_.get()); | 400 DCHECK(!cache_listener_.get()); |
400 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); | 401 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); |
401 embedded_worker_->Start( | 402 embedded_worker_->Start( |
402 version_id_, scope_, script_url_, pause_after_download, | 403 version_id_, scope_, script_url_, pause_after_download, |
403 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, | 404 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, |
404 weak_factory_.GetWeakPtr())); | 405 weak_factory_.GetWeakPtr())); |
405 } | 406 } |
406 return; | 407 return; |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
782 return; | 783 return; |
783 is_doomed_ = true; | 784 is_doomed_ = true; |
784 if (!HasControllee()) | 785 if (!HasControllee()) |
785 DoomInternal(); | 786 DoomInternal(); |
786 } | 787 } |
787 | 788 |
788 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { | 789 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { |
789 embedded_worker()->set_devtools_attached(attached); | 790 embedded_worker()->set_devtools_attached(attached); |
790 if (attached) { | 791 if (attached) { |
791 // Set to null time so we don't record the startup time metric. | 792 // Set to null time so we don't record the startup time metric. |
792 ClearTick(&start_timing_); | 793 ClearTick(&start_time_); |
793 return; | 794 return; |
794 } | 795 } |
795 // If devtools is detached try scheduling the timers for stopping the worker | |
796 // now. | |
797 if (!timeout_timer_.IsRunning()) | 796 if (!timeout_timer_.IsRunning()) |
798 StartTimeoutTimer(); | 797 StartTimeoutTimer(); |
799 if (!start_worker_timeout_timer_.IsRunning() && !start_callbacks_.empty()) | |
800 ScheduleStartWorkerTimeout(); | |
801 } | 798 } |
802 | 799 |
803 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( | 800 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( |
804 const net::HttpResponseInfo& http_info) { | 801 const net::HttpResponseInfo& http_info) { |
805 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); | 802 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); |
806 } | 803 } |
807 | 804 |
808 const net::HttpResponseInfo* | 805 const net::HttpResponseInfo* |
809 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { | 806 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { |
810 return main_script_http_info_.get(); | 807 return main_script_http_info_.get(); |
811 } | 808 } |
812 | 809 |
813 void ServiceWorkerVersion::OnScriptLoaded() { | 810 void ServiceWorkerVersion::OnScriptLoaded() { |
814 DCHECK_EQ(STARTING, running_status()); | 811 DCHECK_EQ(STARTING, running_status()); |
815 StartTimeoutTimer(); | 812 ping_state_ = PING_STARTED; |
kinuko
2015/03/09 09:30:40
nit: This line (or enum name) may look a bit crypt
falken
2015/03/09 10:10:55
Agreed. I renamed the enums and added a comment.
| |
816 } | 813 } |
817 | 814 |
818 void ServiceWorkerVersion::OnStarted() { | 815 void ServiceWorkerVersion::OnStarted() { |
819 DCHECK_EQ(RUNNING, running_status()); | 816 DCHECK_EQ(RUNNING, running_status()); |
820 DCHECK(cache_listener_.get()); | 817 DCHECK(cache_listener_.get()); |
821 RestartTick(&idle_time_); | 818 RestartTick(&idle_time_); |
822 | 819 |
823 // Fire all start callbacks. | 820 // Fire all start callbacks. |
824 scoped_refptr<ServiceWorkerVersion> protect(this); | 821 scoped_refptr<ServiceWorkerVersion> protect(this); |
825 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); | 822 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); |
826 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); | 823 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); |
827 } | 824 } |
828 | 825 |
829 void ServiceWorkerVersion::OnStopped( | 826 void ServiceWorkerVersion::OnStopped( |
830 EmbeddedWorkerInstance::Status old_status) { | 827 EmbeddedWorkerInstance::Status old_status) { |
831 DCHECK_EQ(STOPPED, running_status()); | 828 DCHECK_EQ(STOPPED, running_status()); |
832 scoped_refptr<ServiceWorkerVersion> protect(this); | 829 scoped_refptr<ServiceWorkerVersion> protect(this); |
833 | 830 |
834 bool should_restart = !is_doomed() && !start_callbacks_.empty() && | 831 bool should_restart = !is_doomed() && !start_callbacks_.empty() && |
835 (old_status != EmbeddedWorkerInstance::STARTING); | 832 (old_status != EmbeddedWorkerInstance::STARTING); |
836 | 833 |
837 StopTimeoutTimer(); | 834 StopTimeoutTimer(); |
838 if (ping_timed_out_) | 835 if (ping_state_ == PING_TIMED_OUT) |
839 should_restart = false; | 836 should_restart = false; |
840 | 837 |
841 // Fire all stop callbacks. | 838 // Fire all stop callbacks. |
842 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); | 839 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); |
843 | 840 |
844 if (!should_restart) { | 841 if (!should_restart) { |
845 // Let all start callbacks fail. | 842 // Let all start callbacks fail. |
846 RunCallbacks(this, &start_callbacks_, | 843 RunCallbacks(this, &start_callbacks_, |
847 SERVICE_WORKER_ERROR_START_WORKER_FAILED); | 844 SERVICE_WORKER_ERROR_START_WORKER_FAILED); |
848 } | 845 } |
(...skipping 25 matching lines...) Expand all Loading... | |
874 | 871 |
875 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this)); | 872 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this)); |
876 | 873 |
877 // There should be no more communication from/to a stopped worker. Deleting | 874 // There should be no more communication from/to a stopped worker. Deleting |
878 // the listener prevents any pending completion callbacks from causing | 875 // the listener prevents any pending completion callbacks from causing |
879 // messages to be sent to the stopped worker. | 876 // messages to be sent to the stopped worker. |
880 cache_listener_.reset(); | 877 cache_listener_.reset(); |
881 | 878 |
882 // Restart worker if we have any start callbacks and the worker isn't doomed. | 879 // Restart worker if we have any start callbacks and the worker isn't doomed. |
883 if (should_restart) { | 880 if (should_restart) { |
884 start_worker_timeout_timer_.Reset(); | 881 if (embedded_worker_->devtools_attached()) |
882 ClearTick(&start_time_); | |
883 else | |
884 RestartTick(&start_time_); | |
885 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); | 885 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); |
886 embedded_worker_->Start( | 886 embedded_worker_->Start( |
887 version_id_, scope_, script_url_, false /* pause_after_download */, | 887 version_id_, scope_, script_url_, false /* pause_after_download */, |
888 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, | 888 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, |
889 weak_factory_.GetWeakPtr())); | 889 weak_factory_.GetWeakPtr())); |
890 } | 890 } |
891 } | 891 } |
892 | 892 |
893 void ServiceWorkerVersion::OnReportException( | 893 void ServiceWorkerVersion::OnReportException( |
894 const base::string16& error_message, | 894 const base::string16& error_message, |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1419 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1419 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1420 if (running_status() != RUNNING) | 1420 if (running_status() != RUNNING) |
1421 return; | 1421 return; |
1422 | 1422 |
1423 embedded_worker_->SendMessage( | 1423 embedded_worker_->SendMessage( |
1424 ServiceWorkerMsg_DidGetClients(request_id, clients)); | 1424 ServiceWorkerMsg_DidGetClients(request_id, clients)); |
1425 } | 1425 } |
1426 | 1426 |
1427 void ServiceWorkerVersion::StartTimeoutTimer() { | 1427 void ServiceWorkerVersion::StartTimeoutTimer() { |
1428 DCHECK(!timeout_timer_.IsRunning()); | 1428 DCHECK(!timeout_timer_.IsRunning()); |
1429 | |
1430 if (embedded_worker_->devtools_attached()) | |
1431 ClearTick(&start_time_); | |
1432 else | |
1433 RestartTick(&start_time_); | |
1434 start_callbacks_.push_back( | |
1435 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, | |
1436 weak_factory_.GetWeakPtr())); | |
1437 | |
1429 ClearTick(&idle_time_); | 1438 ClearTick(&idle_time_); |
1430 ClearTick(&ping_time_); | 1439 ClearTick(&ping_time_); |
1431 ping_timed_out_ = false; | 1440 ping_state_ = PING_NOT_STARTED; |
1441 | |
1432 timeout_timer_.Start(FROM_HERE, | 1442 timeout_timer_.Start(FROM_HERE, |
1433 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), | 1443 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), |
1434 this, &ServiceWorkerVersion::OnTimeoutTimer); | 1444 this, &ServiceWorkerVersion::OnTimeoutTimer); |
1435 } | 1445 } |
1436 | 1446 |
1437 void ServiceWorkerVersion::StopTimeoutTimer() { | 1447 void ServiceWorkerVersion::StopTimeoutTimer() { |
1438 timeout_timer_.Stop(); | 1448 timeout_timer_.Stop(); |
1439 } | 1449 } |
1440 | 1450 |
1441 void ServiceWorkerVersion::OnTimeoutTimer() { | 1451 void ServiceWorkerVersion::OnTimeoutTimer() { |
1452 DCHECK(running_status() == STARTING || running_status() == RUNNING || | |
1453 running_status() == STOPPING) | |
1454 << running_status(); | |
1455 | |
1456 if (GetTickDuration(start_time_) > | |
kinuko
2015/03/09 09:30:40
nit: Could we have one-line comments for each of t
falken
2015/03/09 10:10:55
Done.
| |
1457 base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) { | |
1458 DCHECK_NE(RUNNING, running_status()); | |
1459 scoped_refptr<ServiceWorkerVersion> protect(this); | |
1460 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); | |
1461 if (running_status() == STARTING) | |
1462 embedded_worker_->Stop(); | |
1463 StopTimeoutTimer(); | |
1464 return; | |
1465 } | |
1466 | |
1442 if (running_status() == STOPPING) | 1467 if (running_status() == STOPPING) |
1443 return; | 1468 return; |
kinuko
2015/03/09 09:30:40
nit: could this check be done before we check star
falken
2015/03/09 10:10:55
Thanks for pointing this out. The start_time timeo
falken
2015/03/10 06:56:36
Updated this... the timeout timer now continues un
| |
1444 DCHECK(running_status() == STARTING || running_status() == RUNNING); | 1469 |
1445 if (GetTickDuration(idle_time_) > | 1470 if (GetTickDuration(idle_time_) > |
1446 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { | 1471 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { |
1447 StopWorkerIfIdle(); | 1472 StopWorkerIfIdle(); |
1448 StopTimeoutTimer(); | 1473 StopTimeoutTimer(); |
1449 return; | 1474 return; |
1450 } | 1475 } |
1451 if (GetTickDuration(ping_time_) > | 1476 if (GetTickDuration(ping_time_) > |
1452 base::TimeDelta::FromSeconds(kPingTimeoutSeconds)) { | 1477 base::TimeDelta::FromSeconds(kPingTimeoutSeconds)) { |
1453 OnPingTimeout(); | 1478 OnPingTimeout(); |
1454 StopTimeoutTimer(); | 1479 StopTimeoutTimer(); |
1455 return; | 1480 return; |
1456 } | 1481 } |
1457 | 1482 |
1458 if (ping_time_.is_null()) | 1483 if (ping_state_ == PING_STARTED && ping_time_.is_null()) |
1459 PingWorker(); | 1484 PingWorker(); |
1460 } | 1485 } |
1461 | 1486 |
1462 void ServiceWorkerVersion::PingWorker() { | 1487 void ServiceWorkerVersion::PingWorker() { |
1463 DCHECK(running_status() == STARTING || running_status() == RUNNING); | 1488 DCHECK(running_status() == STARTING || running_status() == RUNNING); |
1489 DCHECK_EQ(PING_STARTED, ping_state_); | |
1464 ServiceWorkerStatusCode status = | 1490 ServiceWorkerStatusCode status = |
1465 embedded_worker_->SendMessage(ServiceWorkerMsg_Ping()); | 1491 embedded_worker_->SendMessage(ServiceWorkerMsg_Ping()); |
1466 if (status != SERVICE_WORKER_OK) { | 1492 if (status != SERVICE_WORKER_OK) { |
1467 // TODO(falken): Maybe try resending Ping a few times first? | 1493 // TODO(falken): Maybe try resending Ping a few times first? |
1468 ping_timed_out_ = true; | 1494 ping_state_ = PING_TIMED_OUT; |
1469 StopWorkerIfIdle(); | 1495 StopWorkerIfIdle(); |
1470 return; | 1496 return; |
1471 } | 1497 } |
1472 RestartTick(&ping_time_); | 1498 RestartTick(&ping_time_); |
1473 } | 1499 } |
1474 | 1500 |
1475 void ServiceWorkerVersion::OnPingTimeout() { | 1501 void ServiceWorkerVersion::OnPingTimeout() { |
1476 DCHECK(running_status() == STARTING || running_status() == RUNNING); | 1502 DCHECK(running_status() == STARTING || running_status() == RUNNING); |
1477 ping_timed_out_ = true; | 1503 ping_state_ = PING_TIMED_OUT; |
1478 // TODO(falken): Show a message to the developer that the SW was stopped due | 1504 // TODO(falken): Show a message to the developer that the SW was stopped due |
1479 // to timeout (crbug.com/457968). Also, change the error code to | 1505 // to timeout (crbug.com/457968). Also, change the error code to |
1480 // SERVICE_WORKER_ERROR_TIMEOUT. | 1506 // SERVICE_WORKER_ERROR_TIMEOUT. |
1481 StopWorkerIfIdle(); | 1507 StopWorkerIfIdle(); |
1482 } | 1508 } |
1483 | 1509 |
1484 void ServiceWorkerVersion::StopWorkerIfIdle() { | 1510 void ServiceWorkerVersion::StopWorkerIfIdle() { |
1485 if (HasInflightRequests() && !ping_timed_out_) | 1511 if (HasInflightRequests() && ping_state_ != PING_TIMED_OUT) |
1486 return; | 1512 return; |
1487 if (running_status() == STOPPED || running_status() == STOPPING || | 1513 if (running_status() == STOPPED || running_status() == STOPPING || |
1488 !stop_callbacks_.empty()) { | 1514 !stop_callbacks_.empty()) { |
1489 return; | 1515 return; |
1490 } | 1516 } |
1491 | 1517 |
1492 // TODO(falken): We may need to handle StopIfIdle failure and | 1518 // TODO(falken): We may need to handle StopIfIdle failure and |
1493 // forcibly fail pending callbacks so no one is stuck waiting | 1519 // forcibly fail pending callbacks so no one is stuck waiting |
1494 // for the worker. | 1520 // for the worker. |
1495 embedded_worker_->StopIfIdle(); | 1521 embedded_worker_->StopIfIdle(); |
1496 } | 1522 } |
1497 | 1523 |
1498 bool ServiceWorkerVersion::HasInflightRequests() const { | 1524 bool ServiceWorkerVersion::HasInflightRequests() const { |
1499 return | 1525 return |
1500 !activate_callbacks_.IsEmpty() || | 1526 !activate_callbacks_.IsEmpty() || |
1501 !install_callbacks_.IsEmpty() || | 1527 !install_callbacks_.IsEmpty() || |
1502 !fetch_callbacks_.IsEmpty() || | 1528 !fetch_callbacks_.IsEmpty() || |
1503 !sync_callbacks_.IsEmpty() || | 1529 !sync_callbacks_.IsEmpty() || |
1504 !notification_click_callbacks_.IsEmpty() || | 1530 !notification_click_callbacks_.IsEmpty() || |
1505 !push_callbacks_.IsEmpty() || | 1531 !push_callbacks_.IsEmpty() || |
1506 !geofencing_callbacks_.IsEmpty() || | 1532 !geofencing_callbacks_.IsEmpty() || |
1507 !cross_origin_connect_callbacks_.IsEmpty() || | 1533 !cross_origin_connect_callbacks_.IsEmpty() || |
1508 !streaming_url_request_jobs_.empty(); | 1534 !streaming_url_request_jobs_.empty(); |
1509 } | 1535 } |
1510 | 1536 |
1511 void ServiceWorkerVersion::ScheduleStartWorkerTimeout() { | |
1512 DCHECK(!start_worker_timeout_timer_.IsRunning()); | |
1513 start_timing_ = embedded_worker_->devtools_attached() | |
1514 ? base::TimeTicks() | |
1515 : base::TimeTicks::Now(); | |
1516 start_callbacks_.push_back( | |
1517 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, | |
1518 weak_factory_.GetWeakPtr())); | |
1519 start_worker_timeout_timer_.Start( | |
1520 FROM_HERE, base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes), | |
1521 base::Bind(&ServiceWorkerVersion::OnStartWorkerTimeout, | |
1522 weak_factory_.GetWeakPtr())); | |
1523 } | |
1524 | |
1525 void ServiceWorkerVersion::OnStartWorkerTimeout() { | |
1526 DCHECK(running_status() == STARTING || running_status() == STOPPING) | |
1527 << running_status(); | |
1528 | |
1529 if (embedded_worker_->devtools_attached()) { | |
1530 start_worker_timeout_timer_.Stop(); | |
1531 return; | |
1532 } | |
1533 | |
1534 scoped_refptr<ServiceWorkerVersion> protect(this); | |
1535 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); | |
1536 if (running_status() == STARTING) | |
1537 embedded_worker_->Stop(); | |
1538 } | |
1539 | |
1540 void ServiceWorkerVersion::RecordStartWorkerResult( | 1537 void ServiceWorkerVersion::RecordStartWorkerResult( |
1541 ServiceWorkerStatusCode status) { | 1538 ServiceWorkerStatusCode status) { |
1542 start_worker_timeout_timer_.Stop(); | |
1543 | |
1544 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status, | 1539 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status, |
1545 SERVICE_WORKER_ERROR_MAX_VALUE); | 1540 SERVICE_WORKER_ERROR_MAX_VALUE); |
1546 if (status == SERVICE_WORKER_OK && !start_timing_.is_null()) { | 1541 if (status == SERVICE_WORKER_OK && !start_time_.is_null()) { |
1547 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", | 1542 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", |
1548 GetTickDuration(start_timing_)); | 1543 GetTickDuration(start_time_)); |
1549 } | 1544 } |
1550 | 1545 |
1546 ClearTick(&start_time_); | |
1551 if (status != SERVICE_WORKER_ERROR_TIMEOUT) | 1547 if (status != SERVICE_WORKER_ERROR_TIMEOUT) |
1552 return; | 1548 return; |
1553 EmbeddedWorkerInstance::StartingPhase phase = | 1549 EmbeddedWorkerInstance::StartingPhase phase = |
1554 EmbeddedWorkerInstance::NOT_STARTING; | 1550 EmbeddedWorkerInstance::NOT_STARTING; |
1555 EmbeddedWorkerInstance::Status running_status = embedded_worker_->status(); | 1551 EmbeddedWorkerInstance::Status running_status = embedded_worker_->status(); |
1556 // Build an artifical JavaScript exception to show in the ServiceWorker | 1552 // Build an artifical JavaScript exception to show in the ServiceWorker |
1557 // log for developers; it's not user-facing so it's not a localized resource. | 1553 // log for developers; it's not user-facing so it's not a localized resource. |
1558 std::string message = "ServiceWorker startup timed out. "; | 1554 std::string message = "ServiceWorker startup timed out. "; |
1559 if (running_status != EmbeddedWorkerInstance::STARTING) { | 1555 if (running_status != EmbeddedWorkerInstance::STARTING) { |
1560 message.append("The worker had unexpected status: "); | 1556 message.append("The worker had unexpected status: "); |
(...skipping 29 matching lines...) Expand all Loading... | |
1590 int request_id) { | 1586 int request_id) { |
1591 callbacks->Remove(request_id); | 1587 callbacks->Remove(request_id); |
1592 if (is_doomed_) { | 1588 if (is_doomed_) { |
1593 // The stop should be already scheduled, but try to stop immediately, in | 1589 // The stop should be already scheduled, but try to stop immediately, in |
1594 // order to release worker resources soon. | 1590 // order to release worker resources soon. |
1595 StopWorkerIfIdle(); | 1591 StopWorkerIfIdle(); |
1596 } | 1592 } |
1597 } | 1593 } |
1598 | 1594 |
1599 } // namespace content | 1595 } // namespace content |
OLD | NEW |