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