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/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 |