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 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 const GURL& script_url, | 307 const GURL& script_url, |
308 int64 version_id, | 308 int64 version_id, |
309 base::WeakPtr<ServiceWorkerContextCore> context) | 309 base::WeakPtr<ServiceWorkerContextCore> context) |
310 : version_id_(version_id), | 310 : version_id_(version_id), |
311 registration_id_(kInvalidServiceWorkerVersionId), | 311 registration_id_(kInvalidServiceWorkerVersionId), |
312 script_url_(script_url), | 312 script_url_(script_url), |
313 status_(NEW), | 313 status_(NEW), |
314 context_(context), | 314 context_(context), |
315 script_cache_map_(this, context), | 315 script_cache_map_(this, context), |
316 ping_state_(NOT_PINGING), | 316 ping_state_(NOT_PINGING), |
317 is_doomed_(false), | |
318 skip_waiting_(false), | |
319 weak_factory_(this) { | 317 weak_factory_(this) { |
320 DCHECK(context_); | 318 DCHECK(context_); |
321 DCHECK(registration); | 319 DCHECK(registration); |
322 if (registration) { | 320 if (registration) { |
323 registration_id_ = registration->id(); | 321 registration_id_ = registration->id(); |
324 scope_ = registration->pattern(); | 322 scope_ = registration->pattern(); |
325 } | 323 } |
326 context_->AddLiveVersion(this); | 324 context_->AddLiveVersion(this); |
327 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); | 325 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); |
328 embedded_worker_->AddListener(this); | 326 embedded_worker_->AddListener(this); |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
772 if (is_doomed_) | 770 if (is_doomed_) |
773 return; | 771 return; |
774 is_doomed_ = true; | 772 is_doomed_ = true; |
775 if (!HasControllee()) | 773 if (!HasControllee()) |
776 DoomInternal(); | 774 DoomInternal(); |
777 } | 775 } |
778 | 776 |
779 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { | 777 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { |
780 embedded_worker()->set_devtools_attached(attached); | 778 embedded_worker()->set_devtools_attached(attached); |
781 if (attached) { | 779 if (attached) { |
782 // Set to null time so we don't record the startup time metric. | 780 // Don't record the startup time metric once DevTools is attached. |
783 ClearTick(&start_time_); | 781 ClearTick(&start_time_); |
782 skip_recording_startup_time_ = true; | |
784 return; | 783 return; |
785 } | 784 } |
786 if (!timeout_timer_.IsRunning()) | 785 if (running_status() == STARTING || running_status() == STOPPING) { |
falken
2015/03/23 00:14:25
This is kind of a non-obvious condition. Would it
nhiroki
2015/03/23 00:43:17
Done.
nhiroki
2015/03/23 00:43:17
Done.
| |
787 StartTimeoutTimer(); | 786 // Reactivate the timer for start timeout. |
787 DCHECK(timeout_timer_.IsRunning()) << running_status(); | |
788 RestartTick(&start_time_); | |
789 } | |
788 } | 790 } |
789 | 791 |
790 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( | 792 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( |
791 const net::HttpResponseInfo& http_info) { | 793 const net::HttpResponseInfo& http_info) { |
792 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); | 794 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); |
793 } | 795 } |
794 | 796 |
795 const net::HttpResponseInfo* | 797 const net::HttpResponseInfo* |
796 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { | 798 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { |
797 return main_script_http_info_.get(); | 799 return main_script_http_info_.get(); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
869 streaming_url_request_jobs_.clear(); | 871 streaming_url_request_jobs_.clear(); |
870 | 872 |
871 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); | 873 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); |
872 | 874 |
873 // There should be no more communication from/to a stopped worker. Deleting | 875 // There should be no more communication from/to a stopped worker. Deleting |
874 // the listener prevents any pending completion callbacks from causing | 876 // the listener prevents any pending completion callbacks from causing |
875 // messages to be sent to the stopped worker. | 877 // messages to be sent to the stopped worker. |
876 cache_listener_.reset(); | 878 cache_listener_.reset(); |
877 | 879 |
878 // Restart worker if we have any start callbacks and the worker isn't doomed. | 880 // Restart worker if we have any start callbacks and the worker isn't doomed. |
879 if (should_restart) { | 881 if (should_restart) |
880 if (embedded_worker_->devtools_attached()) | 882 StartWorkerInternal(false /* pause_after_download */); |
falken
2015/03/23 00:14:25
Thanks for this helper function.
| |
881 ClearTick(&start_time_); | |
882 else | |
883 RestartTick(&start_time_); | |
nhiroki
2015/03/16 01:58:02
FYI: We may have to call StartTimeoutTimer() here.
| |
884 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); | |
885 embedded_worker_->Start( | |
886 version_id_, scope_, script_url_, false /* pause_after_download */, | |
887 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, | |
888 weak_factory_.GetWeakPtr())); | |
889 } | |
890 } | 883 } |
891 | 884 |
892 void ServiceWorkerVersion::OnReportException( | 885 void ServiceWorkerVersion::OnReportException( |
893 const base::string16& error_message, | 886 const base::string16& error_message, |
894 int line_number, | 887 int line_number, |
895 int column_number, | 888 int column_number, |
896 const GURL& source_url) { | 889 const GURL& source_url) { |
897 FOR_EACH_OBSERVER( | 890 FOR_EACH_OBSERVER( |
898 Listener, | 891 Listener, |
899 listeners_, | 892 listeners_, |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1414 | 1407 |
1415 void ServiceWorkerVersion::OnPongFromWorker() { | 1408 void ServiceWorkerVersion::OnPongFromWorker() { |
1416 ClearTick(&ping_time_); | 1409 ClearTick(&ping_time_); |
1417 } | 1410 } |
1418 | 1411 |
1419 void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker( | 1412 void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker( |
1420 bool pause_after_download, | 1413 bool pause_after_download, |
1421 const StatusCallback& callback, | 1414 const StatusCallback& callback, |
1422 ServiceWorkerStatusCode status, | 1415 ServiceWorkerStatusCode status, |
1423 const scoped_refptr<ServiceWorkerRegistration>& protect) { | 1416 const scoped_refptr<ServiceWorkerRegistration>& protect) { |
1424 if (status != SERVICE_WORKER_OK || is_doomed()) { | 1417 if (status != SERVICE_WORKER_OK || is_doomed()) { |
falken
2015/03/23 00:14:25
I feel like non-OK status here is unexpected and w
nhiroki
2015/03/23 00:43:17
Sounds reasonable. Added the function call (is_doo
| |
1425 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); | 1418 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
1426 return; | 1419 return; |
1427 } | 1420 } |
1428 | 1421 |
1429 switch (running_status()) { | 1422 switch (running_status()) { |
1430 case RUNNING: | 1423 case RUNNING: |
1431 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); | 1424 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
1432 return; | 1425 return; |
1433 case STOPPING: | 1426 case STOPPING: |
1434 case STOPPED: | 1427 case STOPPED: |
1435 case STARTING: | 1428 case STARTING: |
1436 if (!timeout_timer_.IsRunning()) | 1429 if (start_callbacks_.empty()) { |
1437 StartTimeoutTimer(); | 1430 start_callbacks_.push_back( |
1438 // Start callbacks keep the live registration. | 1431 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, |
1432 weak_factory_.GetWeakPtr())); | |
1433 } | |
1434 // Keep the live registration while staring the worker. | |
falken
2015/03/23 00:14:25
nit: starting
nhiroki
2015/03/23 00:43:17
Done.
| |
1439 start_callbacks_.push_back( | 1435 start_callbacks_.push_back( |
1440 base::Bind(&RunStartWorkerCallback, callback, protect)); | 1436 base::Bind(&RunStartWorkerCallback, callback, protect)); |
1441 if (running_status() == STOPPED) { | 1437 StartWorkerInternal(pause_after_download); |
1442 DCHECK(!cache_listener_.get()); | |
1443 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); | |
1444 embedded_worker_->Start( | |
1445 version_id_, scope_, script_url_, pause_after_download, | |
1446 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, | |
1447 weak_factory_.GetWeakPtr())); | |
1448 } | |
1449 return; | 1438 return; |
1450 } | 1439 } |
1451 } | 1440 } |
1452 | 1441 |
1442 void ServiceWorkerVersion::StartWorkerInternal(bool pause_after_download) { | |
1443 if (!timeout_timer_.IsRunning()) | |
1444 StartTimeoutTimer(); | |
1445 if (running_status() == STOPPED) { | |
1446 DCHECK(!cache_listener_.get()); | |
1447 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); | |
1448 embedded_worker_->Start( | |
1449 version_id_, scope_, script_url_, pause_after_download, | |
1450 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, | |
1451 weak_factory_.GetWeakPtr())); | |
1452 } | |
1453 } | |
1454 | |
1453 void ServiceWorkerVersion::DidClaimClients( | 1455 void ServiceWorkerVersion::DidClaimClients( |
1454 int request_id, ServiceWorkerStatusCode status) { | 1456 int request_id, ServiceWorkerStatusCode status) { |
1455 if (status == SERVICE_WORKER_ERROR_STATE) { | 1457 if (status == SERVICE_WORKER_ERROR_STATE) { |
1456 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( | 1458 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( |
1457 request_id, blink::WebServiceWorkerError::ErrorTypeState, | 1459 request_id, blink::WebServiceWorkerError::ErrorTypeState, |
1458 base::ASCIIToUTF16(kClaimClientsStateErrorMesage))); | 1460 base::ASCIIToUTF16(kClaimClientsStateErrorMesage))); |
1459 return; | 1461 return; |
1460 } | 1462 } |
1461 if (status == SERVICE_WORKER_ERROR_ABORT) { | 1463 if (status == SERVICE_WORKER_ERROR_ABORT) { |
1462 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( | 1464 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( |
(...skipping 12 matching lines...) Expand all Loading... | |
1475 if (running_status() != RUNNING) | 1477 if (running_status() != RUNNING) |
1476 return; | 1478 return; |
1477 | 1479 |
1478 embedded_worker_->SendMessage( | 1480 embedded_worker_->SendMessage( |
1479 ServiceWorkerMsg_DidGetClients(request_id, clients)); | 1481 ServiceWorkerMsg_DidGetClients(request_id, clients)); |
1480 } | 1482 } |
1481 | 1483 |
1482 void ServiceWorkerVersion::StartTimeoutTimer() { | 1484 void ServiceWorkerVersion::StartTimeoutTimer() { |
1483 DCHECK(!timeout_timer_.IsRunning()); | 1485 DCHECK(!timeout_timer_.IsRunning()); |
1484 | 1486 |
1485 if (embedded_worker_->devtools_attached()) | 1487 if (embedded_worker_->devtools_attached()) { |
1488 // Don't record the startup time metric once DevTools is attached. | |
1486 ClearTick(&start_time_); | 1489 ClearTick(&start_time_); |
1487 else | 1490 skip_recording_startup_time_ = true; |
1491 } else { | |
1488 RestartTick(&start_time_); | 1492 RestartTick(&start_time_); |
1489 start_callbacks_.push_back( | 1493 skip_recording_startup_time_ = false; |
1490 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, | 1494 } |
1491 weak_factory_.GetWeakPtr())); | |
1492 | 1495 |
1493 ClearTick(&idle_time_); | 1496 ClearTick(&idle_time_); |
1494 ClearTick(&ping_time_); | 1497 ClearTick(&ping_time_); |
1495 ping_state_ = NOT_PINGING; | 1498 ping_state_ = NOT_PINGING; |
1496 | 1499 |
1497 timeout_timer_.Start(FROM_HERE, | 1500 timeout_timer_.Start(FROM_HERE, |
1498 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), | 1501 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), |
1499 this, &ServiceWorkerVersion::OnTimeoutTimer); | 1502 this, &ServiceWorkerVersion::OnTimeoutTimer); |
1500 } | 1503 } |
1501 | 1504 |
1502 void ServiceWorkerVersion::StopTimeoutTimer() { | 1505 void ServiceWorkerVersion::StopTimeoutTimer() { |
1503 timeout_timer_.Stop(); | 1506 timeout_timer_.Stop(); |
1504 } | 1507 } |
1505 | 1508 |
1506 void ServiceWorkerVersion::OnTimeoutTimer() { | 1509 void ServiceWorkerVersion::OnTimeoutTimer() { |
1507 DCHECK(running_status() == STARTING || running_status() == RUNNING || | 1510 DCHECK(running_status() == STARTING || running_status() == RUNNING || |
1508 running_status() == STOPPING) | 1511 running_status() == STOPPING) |
1509 << running_status(); | 1512 << running_status(); |
1510 | 1513 |
1511 // Starting a worker hasn't finished within a certain period. | 1514 // Starting a worker hasn't finished within a certain period. |
1512 if (GetTickDuration(start_time_) > | 1515 if (GetTickDuration(start_time_) > |
1513 base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) { | 1516 base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) { |
1514 DCHECK_NE(RUNNING, running_status()); | 1517 DCHECK(running_status() == STARTING || running_status() == STOPPING) |
1518 << running_status(); | |
1515 scoped_refptr<ServiceWorkerVersion> protect(this); | 1519 scoped_refptr<ServiceWorkerVersion> protect(this); |
1516 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); | 1520 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); |
1517 if (running_status() == STARTING) | 1521 if (running_status() == STARTING) |
1518 embedded_worker_->Stop(); | 1522 embedded_worker_->Stop(); |
1519 return; | 1523 return; |
1520 } | 1524 } |
1521 | 1525 |
1522 // This check occurs after the start_time_ timeout check, since in that case | 1526 // This check occurs after the start_time_ timeout check, since in that case |
1523 // the start callbacks should fail with ERROR_TIMEOUT. In the other timeout | 1527 // the start callbacks should fail with ERROR_TIMEOUT. In the other timeout |
1524 // checks, there's nothing more to do as the worker is already stopping. | 1528 // checks, there's nothing more to do as the worker is already stopping. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1598 base::TimeTicks start_time = start_time_; | 1602 base::TimeTicks start_time = start_time_; |
1599 ClearTick(&start_time_); | 1603 ClearTick(&start_time_); |
1600 | 1604 |
1601 // Failing to start a doomed worker isn't interesting and very common when | 1605 // Failing to start a doomed worker isn't interesting and very common when |
1602 // update dooms because the script is byte-to-byte identical. | 1606 // update dooms because the script is byte-to-byte identical. |
1603 if (is_doomed_) | 1607 if (is_doomed_) |
1604 return; | 1608 return; |
1605 | 1609 |
1606 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status, | 1610 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status, |
1607 SERVICE_WORKER_ERROR_MAX_VALUE); | 1611 SERVICE_WORKER_ERROR_MAX_VALUE); |
1608 if (status == SERVICE_WORKER_OK && !start_time.is_null()) { | 1612 if (status == SERVICE_WORKER_OK && !start_time.is_null() && |
1613 !skip_recording_startup_time_) { | |
1609 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", | 1614 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", |
1610 GetTickDuration(start_time)); | 1615 GetTickDuration(start_time)); |
1611 } | 1616 } |
1612 | 1617 |
1613 if (status != SERVICE_WORKER_ERROR_TIMEOUT) | 1618 if (status != SERVICE_WORKER_ERROR_TIMEOUT) |
1614 return; | 1619 return; |
1615 EmbeddedWorkerInstance::StartingPhase phase = | 1620 EmbeddedWorkerInstance::StartingPhase phase = |
1616 EmbeddedWorkerInstance::NOT_STARTING; | 1621 EmbeddedWorkerInstance::NOT_STARTING; |
1617 EmbeddedWorkerInstance::Status running_status = embedded_worker_->status(); | 1622 EmbeddedWorkerInstance::Status running_status = embedded_worker_->status(); |
1618 // Build an artifical JavaScript exception to show in the ServiceWorker | 1623 // Build an artifical JavaScript exception to show in the ServiceWorker |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1652 int request_id) { | 1657 int request_id) { |
1653 callbacks->Remove(request_id); | 1658 callbacks->Remove(request_id); |
1654 if (is_doomed_) { | 1659 if (is_doomed_) { |
1655 // The stop should be already scheduled, but try to stop immediately, in | 1660 // The stop should be already scheduled, but try to stop immediately, in |
1656 // order to release worker resources soon. | 1661 // order to release worker resources soon. |
1657 StopWorkerIfIdle(); | 1662 StopWorkerIfIdle(); |
1658 } | 1663 } |
1659 } | 1664 } |
1660 | 1665 |
1661 } // namespace content | 1666 } // namespace content |
OLD | NEW |