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