| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 | 195 |
| 196 const int ServiceWorkerVersion::kTimeoutTimerDelaySeconds = 30; | 196 const int ServiceWorkerVersion::kTimeoutTimerDelaySeconds = 30; |
| 197 const int ServiceWorkerVersion::kStartInstalledWorkerTimeoutSeconds = 60; | 197 const int ServiceWorkerVersion::kStartInstalledWorkerTimeoutSeconds = 60; |
| 198 const int ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes = 5; | 198 const int ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes = 5; |
| 199 const int ServiceWorkerVersion::kRequestTimeoutMinutes = 5; | 199 const int ServiceWorkerVersion::kRequestTimeoutMinutes = 5; |
| 200 const int ServiceWorkerVersion::kStopWorkerTimeoutSeconds = 5; | 200 const int ServiceWorkerVersion::kStopWorkerTimeoutSeconds = 5; |
| 201 | 201 |
| 202 class ServiceWorkerVersion::Metrics { | 202 class ServiceWorkerVersion::Metrics { |
| 203 public: | 203 public: |
| 204 using EventType = ServiceWorkerMetrics::EventType; | 204 using EventType = ServiceWorkerMetrics::EventType; |
| 205 explicit Metrics(ServiceWorkerVersion* owner) : owner_(owner) {} | 205 explicit Metrics(ServiceWorkerVersion* owner, EventType start_worker_purpose) |
| 206 : owner_(owner), start_worker_purpose_(start_worker_purpose) {} |
| 206 ~Metrics() { | 207 ~Metrics() { |
| 207 if (owner_->should_exclude_from_uma_) | 208 if (owner_->should_exclude_from_uma_) |
| 208 return; | 209 return; |
| 209 for (const auto& ev : event_stats_) { | 210 for (const auto& ev : event_stats_) { |
| 210 ServiceWorkerMetrics::RecordEventHandledRatio( | 211 ServiceWorkerMetrics::RecordEventHandledRatio( |
| 211 ev.first, ev.second.handled_events, ev.second.fired_events); | 212 ev.first, ev.second.handled_events, ev.second.fired_events); |
| 212 } | 213 } |
| 214 if (ServiceWorkerMetrics::IsNavigationHintEvent(start_worker_purpose_)) { |
| 215 ServiceWorkerMetrics::RecordNavigationHintPrecision( |
| 216 start_worker_purpose_, !event_stats_.empty()); |
| 217 } |
| 213 } | 218 } |
| 214 | 219 |
| 215 void RecordEventHandledStatus(EventType event, bool handled) { | 220 void RecordEventHandledStatus(EventType event, bool handled) { |
| 216 event_stats_[event].fired_events++; | 221 event_stats_[event].fired_events++; |
| 217 if (handled) | 222 if (handled) |
| 218 event_stats_[event].handled_events++; | 223 event_stats_[event].handled_events++; |
| 219 } | 224 } |
| 220 | 225 |
| 221 private: | 226 private: |
| 222 struct EventStat { | 227 struct EventStat { |
| 223 size_t fired_events = 0; | 228 size_t fired_events = 0; |
| 224 size_t handled_events = 0; | 229 size_t handled_events = 0; |
| 225 }; | 230 }; |
| 226 | 231 |
| 227 ServiceWorkerVersion* owner_; | 232 ServiceWorkerVersion* owner_; |
| 228 std::map<EventType, EventStat> event_stats_; | 233 std::map<EventType, EventStat> event_stats_; |
| 234 const EventType start_worker_purpose_; |
| 229 | 235 |
| 230 DISALLOW_COPY_AND_ASSIGN(Metrics); | 236 DISALLOW_COPY_AND_ASSIGN(Metrics); |
| 231 }; | 237 }; |
| 232 | 238 |
| 233 // A controller for periodically sending a ping to the worker to see | 239 // A controller for periodically sending a ping to the worker to see |
| 234 // if the worker is not stalling. | 240 // if the worker is not stalling. |
| 235 class ServiceWorkerVersion::PingController { | 241 class ServiceWorkerVersion::PingController { |
| 236 public: | 242 public: |
| 237 explicit PingController(ServiceWorkerVersion* version) : version_(version) {} | 243 explicit PingController(ServiceWorkerVersion* version) : version_(version) {} |
| 238 ~PingController() {} | 244 ~PingController() {} |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 void ServiceWorkerVersion::OnStarting() { | 754 void ServiceWorkerVersion::OnStarting() { |
| 749 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); | 755 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); |
| 750 } | 756 } |
| 751 | 757 |
| 752 void ServiceWorkerVersion::OnStarted() { | 758 void ServiceWorkerVersion::OnStarted() { |
| 753 DCHECK_EQ(RUNNING, running_status()); | 759 DCHECK_EQ(RUNNING, running_status()); |
| 754 RestartTick(&idle_time_); | 760 RestartTick(&idle_time_); |
| 755 | 761 |
| 756 // Fire all start callbacks. | 762 // Fire all start callbacks. |
| 757 scoped_refptr<ServiceWorkerVersion> protect(this); | 763 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 758 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); | 764 RunStartCallbacks(SERVICE_WORKER_OK); |
| 759 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); | 765 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); |
| 760 } | 766 } |
| 761 | 767 |
| 762 void ServiceWorkerVersion::OnStopping() { | 768 void ServiceWorkerVersion::OnStopping() { |
| 763 DCHECK(stop_time_.is_null()); | 769 DCHECK(stop_time_.is_null()); |
| 764 RestartTick(&stop_time_); | 770 RestartTick(&stop_time_); |
| 765 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::StopWorker", | 771 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::StopWorker", |
| 766 stop_time_.ToInternalValue(), "Script", | 772 stop_time_.ToInternalValue(), "Script", |
| 767 script_url_.spec(), "Version Status", | 773 script_url_.spec(), "Version Status", |
| 768 VersionStatusToString(status_)); | 774 VersionStatusToString(status_)); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 OnRegisterForeignFetchScopes) | 865 OnRegisterForeignFetchScopes) |
| 860 IPC_MESSAGE_UNHANDLED(handled = false) | 866 IPC_MESSAGE_UNHANDLED(handled = false) |
| 861 IPC_END_MESSAGE_MAP() | 867 IPC_END_MESSAGE_MAP() |
| 862 return handled; | 868 return handled; |
| 863 } | 869 } |
| 864 | 870 |
| 865 void ServiceWorkerVersion::OnStartSentAndScriptEvaluated( | 871 void ServiceWorkerVersion::OnStartSentAndScriptEvaluated( |
| 866 ServiceWorkerStatusCode status) { | 872 ServiceWorkerStatusCode status) { |
| 867 if (status != SERVICE_WORKER_OK) { | 873 if (status != SERVICE_WORKER_OK) { |
| 868 scoped_refptr<ServiceWorkerVersion> protect(this); | 874 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 869 RunCallbacks(this, &start_callbacks_, | 875 RunStartCallbacks(DeduceStartWorkerFailureReason(status)); |
| 870 DeduceStartWorkerFailureReason(status)); | |
| 871 } | 876 } |
| 872 } | 877 } |
| 873 | 878 |
| 874 void ServiceWorkerVersion::OnGetClient(int request_id, | 879 void ServiceWorkerVersion::OnGetClient(int request_id, |
| 875 const std::string& client_uuid) { | 880 const std::string& client_uuid) { |
| 876 if (!context_) | 881 if (!context_) |
| 877 return; | 882 return; |
| 878 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerVersion::OnGetClient", | 883 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerVersion::OnGetClient", |
| 879 request_id, "client_uuid", client_uuid); | 884 request_id, "client_uuid", client_uuid); |
| 880 ServiceWorkerProviderHost* provider_host = | 885 ServiceWorkerProviderHost* provider_host = |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 DCHECK(!start_callbacks_.empty()); | 1299 DCHECK(!start_callbacks_.empty()); |
| 1295 break; | 1300 break; |
| 1296 case STOPPING: | 1301 case STOPPING: |
| 1297 case STOPPED: | 1302 case STOPPED: |
| 1298 if (start_callbacks_.empty()) { | 1303 if (start_callbacks_.empty()) { |
| 1299 int trace_id = NextTraceId(); | 1304 int trace_id = NextTraceId(); |
| 1300 TRACE_EVENT_ASYNC_BEGIN2( | 1305 TRACE_EVENT_ASYNC_BEGIN2( |
| 1301 "ServiceWorker", "ServiceWorkerVersion::StartWorker", trace_id, | 1306 "ServiceWorker", "ServiceWorkerVersion::StartWorker", trace_id, |
| 1302 "Script", script_url_.spec(), "Purpose", | 1307 "Script", script_url_.spec(), "Purpose", |
| 1303 ServiceWorkerMetrics::EventTypeToString(purpose)); | 1308 ServiceWorkerMetrics::EventTypeToString(purpose)); |
| 1309 DCHECK(!start_worker_first_purpose_); |
| 1310 start_worker_first_purpose_.reset( |
| 1311 new ServiceWorkerMetrics::EventType(purpose)); |
| 1304 start_callbacks_.push_back( | 1312 start_callbacks_.push_back( |
| 1305 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, | 1313 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, |
| 1306 weak_factory_.GetWeakPtr(), purpose, prestart_status, | 1314 weak_factory_.GetWeakPtr(), purpose, prestart_status, |
| 1307 trace_id, is_browser_startup_complete)); | 1315 trace_id, is_browser_startup_complete)); |
| 1308 } | 1316 } |
| 1309 break; | 1317 break; |
| 1310 } | 1318 } |
| 1311 | 1319 |
| 1312 // Keep the live registration while starting the worker. | 1320 // Keep the live registration while starting the worker. |
| 1313 start_callbacks_.push_back( | 1321 start_callbacks_.push_back( |
| 1314 base::Bind(&RunStartWorkerCallback, callback, protect)); | 1322 base::Bind(&RunStartWorkerCallback, callback, protect)); |
| 1315 | 1323 |
| 1316 if (running_status() == STOPPED) | 1324 if (running_status() == STOPPED) |
| 1317 StartWorkerInternal(); | 1325 StartWorkerInternal(); |
| 1318 DCHECK(timeout_timer_.IsRunning()); | 1326 DCHECK(timeout_timer_.IsRunning()); |
| 1319 } | 1327 } |
| 1320 | 1328 |
| 1321 void ServiceWorkerVersion::StartWorkerInternal() { | 1329 void ServiceWorkerVersion::StartWorkerInternal() { |
| 1322 DCHECK_EQ(STOPPED, running_status()); | 1330 DCHECK_EQ(STOPPED, running_status()); |
| 1323 | 1331 |
| 1324 DCHECK(!metrics_); | 1332 DCHECK(!metrics_); |
| 1325 metrics_.reset(new Metrics(this)); | 1333 DCHECK(start_worker_first_purpose_); |
| 1334 metrics_.reset(new Metrics(this, *start_worker_first_purpose_)); |
| 1326 | 1335 |
| 1327 StartTimeoutTimer(); | 1336 StartTimeoutTimer(); |
| 1328 | 1337 |
| 1329 std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( | 1338 std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
| 1330 new EmbeddedWorkerMsg_StartWorker_Params()); | 1339 new EmbeddedWorkerMsg_StartWorker_Params()); |
| 1331 params->service_worker_version_id = version_id_; | 1340 params->service_worker_version_id = version_id_; |
| 1332 params->scope = scope_; | 1341 params->scope = scope_; |
| 1333 params->script_url = script_url_; | 1342 params->script_url = script_url_; |
| 1334 params->is_installed = IsInstalled(status_); | 1343 params->is_installed = IsInstalled(status_); |
| 1335 params->pause_after_download = pause_after_download_; | 1344 params->pause_after_download = pause_after_download_; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 | 1437 |
| 1429 // Starting a worker hasn't finished within a certain period. | 1438 // Starting a worker hasn't finished within a certain period. |
| 1430 const base::TimeDelta start_limit = | 1439 const base::TimeDelta start_limit = |
| 1431 IsInstalled(status()) | 1440 IsInstalled(status()) |
| 1432 ? base::TimeDelta::FromSeconds(kStartInstalledWorkerTimeoutSeconds) | 1441 ? base::TimeDelta::FromSeconds(kStartInstalledWorkerTimeoutSeconds) |
| 1433 : base::TimeDelta::FromMinutes(kStartNewWorkerTimeoutMinutes); | 1442 : base::TimeDelta::FromMinutes(kStartNewWorkerTimeoutMinutes); |
| 1434 if (GetTickDuration(start_time_) > start_limit) { | 1443 if (GetTickDuration(start_time_) > start_limit) { |
| 1435 DCHECK(running_status() == STARTING || running_status() == STOPPING) | 1444 DCHECK(running_status() == STARTING || running_status() == STOPPING) |
| 1436 << running_status(); | 1445 << running_status(); |
| 1437 scoped_refptr<ServiceWorkerVersion> protect(this); | 1446 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 1438 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); | 1447 RunStartCallbacks(SERVICE_WORKER_ERROR_TIMEOUT); |
| 1439 if (running_status() == STARTING) | 1448 if (running_status() == STARTING) |
| 1440 embedded_worker_->Stop(); | 1449 embedded_worker_->Stop(); |
| 1441 return; | 1450 return; |
| 1442 } | 1451 } |
| 1443 | 1452 |
| 1444 // Requests have not finished before their expiration. | 1453 // Requests have not finished before their expiration. |
| 1445 bool stop_for_timeout = false; | 1454 bool stop_for_timeout = false; |
| 1446 while (!requests_.empty()) { | 1455 while (!requests_.empty()) { |
| 1447 RequestInfo info = requests_.top(); | 1456 RequestInfo info = requests_.top(); |
| 1448 if (!RequestExpired(info.expiration)) | 1457 if (!RequestExpired(info.expiration)) |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 should_restart); | 1666 should_restart); |
| 1658 ClearTick(&stop_time_); | 1667 ClearTick(&stop_time_); |
| 1659 } | 1668 } |
| 1660 StopTimeoutTimer(); | 1669 StopTimeoutTimer(); |
| 1661 | 1670 |
| 1662 // Fire all stop callbacks. | 1671 // Fire all stop callbacks. |
| 1663 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); | 1672 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); |
| 1664 | 1673 |
| 1665 if (!should_restart) { | 1674 if (!should_restart) { |
| 1666 // Let all start callbacks fail. | 1675 // Let all start callbacks fail. |
| 1667 RunCallbacks(this, &start_callbacks_, | 1676 RunStartCallbacks(DeduceStartWorkerFailureReason( |
| 1668 DeduceStartWorkerFailureReason( | 1677 SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
| 1669 SERVICE_WORKER_ERROR_START_WORKER_FAILED)); | |
| 1670 } | 1678 } |
| 1671 | 1679 |
| 1672 // Let all message callbacks fail (this will also fire and clear all | 1680 // Let all message callbacks fail (this will also fire and clear all |
| 1673 // callbacks for events). | 1681 // callbacks for events). |
| 1674 // TODO(kinuko): Consider if we want to add queue+resend mechanism here. | 1682 // TODO(kinuko): Consider if we want to add queue+resend mechanism here. |
| 1675 IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer>::iterator iter( | 1683 IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer>::iterator iter( |
| 1676 &custom_requests_); | 1684 &custom_requests_); |
| 1677 while (!iter.IsAtEnd()) { | 1685 while (!iter.IsAtEnd()) { |
| 1678 TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request", | 1686 TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request", |
| 1679 iter.GetCurrentValue(), "Error", "Worker Stopped"); | 1687 iter.GetCurrentValue(), "Error", "Worker Stopped"); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1703 | 1711 |
| 1704 void ServiceWorkerVersion::OnBeginEvent() { | 1712 void ServiceWorkerVersion::OnBeginEvent() { |
| 1705 if (should_exclude_from_uma_ || running_status() != RUNNING || | 1713 if (should_exclude_from_uma_ || running_status() != RUNNING || |
| 1706 idle_time_.is_null()) { | 1714 idle_time_.is_null()) { |
| 1707 return; | 1715 return; |
| 1708 } | 1716 } |
| 1709 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() - | 1717 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() - |
| 1710 idle_time_); | 1718 idle_time_); |
| 1711 } | 1719 } |
| 1712 | 1720 |
| 1721 void ServiceWorkerVersion::RunStartCallbacks(ServiceWorkerStatusCode status) { |
| 1722 start_worker_first_purpose_.reset(); |
| 1723 RunCallbacks(this, &start_callbacks_, status); |
| 1724 } |
| 1725 |
| 1713 } // namespace content | 1726 } // namespace content |
| OLD | NEW |