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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 | 194 |
195 const int ServiceWorkerVersion::kTimeoutTimerDelaySeconds = 30; | 195 const int ServiceWorkerVersion::kTimeoutTimerDelaySeconds = 30; |
196 const int ServiceWorkerVersion::kStartInstalledWorkerTimeoutSeconds = 60; | 196 const int ServiceWorkerVersion::kStartInstalledWorkerTimeoutSeconds = 60; |
197 const int ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes = 5; | 197 const int ServiceWorkerVersion::kStartNewWorkerTimeoutMinutes = 5; |
198 const int ServiceWorkerVersion::kRequestTimeoutMinutes = 5; | 198 const int ServiceWorkerVersion::kRequestTimeoutMinutes = 5; |
199 const int ServiceWorkerVersion::kStopWorkerTimeoutSeconds = 5; | 199 const int ServiceWorkerVersion::kStopWorkerTimeoutSeconds = 5; |
200 | 200 |
201 class ServiceWorkerVersion::Metrics { | 201 class ServiceWorkerVersion::Metrics { |
202 public: | 202 public: |
203 using EventType = ServiceWorkerMetrics::EventType; | 203 using EventType = ServiceWorkerMetrics::EventType; |
204 explicit Metrics(ServiceWorkerVersion* owner) : owner_(owner) {} | 204 explicit Metrics(ServiceWorkerVersion* owner, EventType start_worker_purpose) |
| 205 : owner_(owner), start_worker_purpose_(start_worker_purpose) {} |
205 ~Metrics() { | 206 ~Metrics() { |
206 if (owner_->should_exclude_from_uma_) | 207 if (owner_->should_exclude_from_uma_) |
207 return; | 208 return; |
208 for (const auto& ev : event_stats_) { | 209 for (const auto& ev : event_stats_) { |
209 ServiceWorkerMetrics::RecordEventHandledRatio( | 210 ServiceWorkerMetrics::RecordEventHandledRatio( |
210 ev.first, ev.second.handled_events, ev.second.fired_events); | 211 ev.first, ev.second.handled_events, ev.second.fired_events); |
211 } | 212 } |
| 213 if (ServiceWorkerMetrics::IsNavigationHintEvent(start_worker_purpose_)) { |
| 214 ServiceWorkerMetrics::RecordNavigationHintPrecision( |
| 215 start_worker_purpose_, |
| 216 event_stats_[EventType::FETCH_MAIN_FRAME].fired_events != 0 || |
| 217 event_stats_[EventType::FETCH_SUB_FRAME].fired_events != 0); |
| 218 } |
212 } | 219 } |
213 | 220 |
214 void RecordEventHandledStatus(EventType event, bool handled) { | 221 void RecordEventHandledStatus(EventType event, bool handled) { |
215 event_stats_[event].fired_events++; | 222 event_stats_[event].fired_events++; |
216 if (handled) | 223 if (handled) |
217 event_stats_[event].handled_events++; | 224 event_stats_[event].handled_events++; |
218 } | 225 } |
219 | 226 |
220 private: | 227 private: |
221 struct EventStat { | 228 struct EventStat { |
222 size_t fired_events = 0; | 229 size_t fired_events = 0; |
223 size_t handled_events = 0; | 230 size_t handled_events = 0; |
224 }; | 231 }; |
225 | 232 |
226 ServiceWorkerVersion* owner_; | 233 ServiceWorkerVersion* owner_; |
227 std::map<EventType, EventStat> event_stats_; | 234 std::map<EventType, EventStat> event_stats_; |
| 235 const EventType start_worker_purpose_; |
228 | 236 |
229 DISALLOW_COPY_AND_ASSIGN(Metrics); | 237 DISALLOW_COPY_AND_ASSIGN(Metrics); |
230 }; | 238 }; |
231 | 239 |
232 // A controller for periodically sending a ping to the worker to see | 240 // A controller for periodically sending a ping to the worker to see |
233 // if the worker is not stalling. | 241 // if the worker is not stalling. |
234 class ServiceWorkerVersion::PingController { | 242 class ServiceWorkerVersion::PingController { |
235 public: | 243 public: |
236 explicit PingController(ServiceWorkerVersion* version) : version_(version) {} | 244 explicit PingController(ServiceWorkerVersion* version) : version_(version) {} |
237 ~PingController() {} | 245 ~PingController() {} |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 void ServiceWorkerVersion::OnStarting() { | 779 void ServiceWorkerVersion::OnStarting() { |
772 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); | 780 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); |
773 } | 781 } |
774 | 782 |
775 void ServiceWorkerVersion::OnStarted() { | 783 void ServiceWorkerVersion::OnStarted() { |
776 DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status()); | 784 DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status()); |
777 RestartTick(&idle_time_); | 785 RestartTick(&idle_time_); |
778 | 786 |
779 // Fire all start callbacks. | 787 // Fire all start callbacks. |
780 scoped_refptr<ServiceWorkerVersion> protect(this); | 788 scoped_refptr<ServiceWorkerVersion> protect(this); |
781 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); | 789 FinishStartWorker(SERVICE_WORKER_OK); |
782 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); | 790 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); |
783 } | 791 } |
784 | 792 |
785 void ServiceWorkerVersion::OnStopping() { | 793 void ServiceWorkerVersion::OnStopping() { |
786 DCHECK(stop_time_.is_null()); | 794 DCHECK(stop_time_.is_null()); |
787 RestartTick(&stop_time_); | 795 RestartTick(&stop_time_); |
788 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::StopWorker", | 796 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::StopWorker", |
789 stop_time_.ToInternalValue(), "Script", | 797 stop_time_.ToInternalValue(), "Script", |
790 script_url_.spec(), "Version Status", | 798 script_url_.spec(), "Version Status", |
791 VersionStatusToString(status_)); | 799 VersionStatusToString(status_)); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 OnRegisterForeignFetchScopes) | 888 OnRegisterForeignFetchScopes) |
881 IPC_MESSAGE_UNHANDLED(handled = false) | 889 IPC_MESSAGE_UNHANDLED(handled = false) |
882 IPC_END_MESSAGE_MAP() | 890 IPC_END_MESSAGE_MAP() |
883 return handled; | 891 return handled; |
884 } | 892 } |
885 | 893 |
886 void ServiceWorkerVersion::OnStartSentAndScriptEvaluated( | 894 void ServiceWorkerVersion::OnStartSentAndScriptEvaluated( |
887 ServiceWorkerStatusCode status) { | 895 ServiceWorkerStatusCode status) { |
888 if (status != SERVICE_WORKER_OK) { | 896 if (status != SERVICE_WORKER_OK) { |
889 scoped_refptr<ServiceWorkerVersion> protect(this); | 897 scoped_refptr<ServiceWorkerVersion> protect(this); |
890 RunCallbacks(this, &start_callbacks_, | 898 FinishStartWorker(DeduceStartWorkerFailureReason(status)); |
891 DeduceStartWorkerFailureReason(status)); | |
892 } | 899 } |
893 } | 900 } |
894 | 901 |
895 void ServiceWorkerVersion::OnGetClient(int request_id, | 902 void ServiceWorkerVersion::OnGetClient(int request_id, |
896 const std::string& client_uuid) { | 903 const std::string& client_uuid) { |
897 if (!context_) | 904 if (!context_) |
898 return; | 905 return; |
899 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerVersion::OnGetClient", | 906 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerVersion::OnGetClient", |
900 request_id, "client_uuid", client_uuid); | 907 request_id, "client_uuid", client_uuid); |
901 ServiceWorkerProviderHost* provider_host = | 908 ServiceWorkerProviderHost* provider_host = |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1321 DCHECK(!start_callbacks_.empty()); | 1328 DCHECK(!start_callbacks_.empty()); |
1322 break; | 1329 break; |
1323 case EmbeddedWorkerStatus::STOPPING: | 1330 case EmbeddedWorkerStatus::STOPPING: |
1324 case EmbeddedWorkerStatus::STOPPED: | 1331 case EmbeddedWorkerStatus::STOPPED: |
1325 if (start_callbacks_.empty()) { | 1332 if (start_callbacks_.empty()) { |
1326 int trace_id = NextTraceId(); | 1333 int trace_id = NextTraceId(); |
1327 TRACE_EVENT_ASYNC_BEGIN2( | 1334 TRACE_EVENT_ASYNC_BEGIN2( |
1328 "ServiceWorker", "ServiceWorkerVersion::StartWorker", trace_id, | 1335 "ServiceWorker", "ServiceWorkerVersion::StartWorker", trace_id, |
1329 "Script", script_url_.spec(), "Purpose", | 1336 "Script", script_url_.spec(), "Purpose", |
1330 ServiceWorkerMetrics::EventTypeToString(purpose)); | 1337 ServiceWorkerMetrics::EventTypeToString(purpose)); |
| 1338 DCHECK(!start_worker_first_purpose_); |
| 1339 start_worker_first_purpose_ = purpose; |
1331 start_callbacks_.push_back( | 1340 start_callbacks_.push_back( |
1332 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, | 1341 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, |
1333 weak_factory_.GetWeakPtr(), purpose, prestart_status, | 1342 weak_factory_.GetWeakPtr(), purpose, prestart_status, |
1334 trace_id, is_browser_startup_complete)); | 1343 trace_id, is_browser_startup_complete)); |
1335 } | 1344 } |
1336 break; | 1345 break; |
1337 } | 1346 } |
1338 | 1347 |
1339 // Keep the live registration while starting the worker. | 1348 // Keep the live registration while starting the worker. |
1340 start_callbacks_.push_back( | 1349 start_callbacks_.push_back( |
1341 base::Bind(&RunStartWorkerCallback, callback, protect)); | 1350 base::Bind(&RunStartWorkerCallback, callback, protect)); |
1342 | 1351 |
1343 if (running_status() == EmbeddedWorkerStatus::STOPPED) | 1352 if (running_status() == EmbeddedWorkerStatus::STOPPED) |
1344 StartWorkerInternal(); | 1353 StartWorkerInternal(); |
1345 DCHECK(timeout_timer_.IsRunning()); | 1354 DCHECK(timeout_timer_.IsRunning()); |
1346 } | 1355 } |
1347 | 1356 |
1348 void ServiceWorkerVersion::StartWorkerInternal() { | 1357 void ServiceWorkerVersion::StartWorkerInternal() { |
1349 DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status()); | 1358 DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status()); |
1350 | 1359 |
1351 DCHECK(!metrics_); | 1360 DCHECK(!metrics_); |
1352 metrics_.reset(new Metrics(this)); | 1361 DCHECK(start_worker_first_purpose_); |
| 1362 metrics_.reset(new Metrics(this, start_worker_first_purpose_.value())); |
| 1363 |
| 1364 // We don't clear |start_worker_first_purpose_| here but clear in |
| 1365 // FinishStartWorker. This is because StartWorkerInternal may be called |
| 1366 // again from OnStoppedInternal if StopWorker is called before OnStarted. |
1353 | 1367 |
1354 StartTimeoutTimer(); | 1368 StartTimeoutTimer(); |
1355 | 1369 |
1356 std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( | 1370 std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
1357 new EmbeddedWorkerMsg_StartWorker_Params()); | 1371 new EmbeddedWorkerMsg_StartWorker_Params()); |
1358 params->service_worker_version_id = version_id_; | 1372 params->service_worker_version_id = version_id_; |
1359 params->scope = scope_; | 1373 params->scope = scope_; |
1360 params->script_url = script_url_; | 1374 params->script_url = script_url_; |
1361 params->is_installed = IsInstalled(status_); | 1375 params->is_installed = IsInstalled(status_); |
1362 params->pause_after_download = pause_after_download_; | 1376 params->pause_after_download = pause_after_download_; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 // Starting a worker hasn't finished within a certain period. | 1471 // Starting a worker hasn't finished within a certain period. |
1458 const base::TimeDelta start_limit = | 1472 const base::TimeDelta start_limit = |
1459 IsInstalled(status()) | 1473 IsInstalled(status()) |
1460 ? base::TimeDelta::FromSeconds(kStartInstalledWorkerTimeoutSeconds) | 1474 ? base::TimeDelta::FromSeconds(kStartInstalledWorkerTimeoutSeconds) |
1461 : base::TimeDelta::FromMinutes(kStartNewWorkerTimeoutMinutes); | 1475 : base::TimeDelta::FromMinutes(kStartNewWorkerTimeoutMinutes); |
1462 if (GetTickDuration(start_time_) > start_limit) { | 1476 if (GetTickDuration(start_time_) > start_limit) { |
1463 DCHECK(running_status() == EmbeddedWorkerStatus::STARTING || | 1477 DCHECK(running_status() == EmbeddedWorkerStatus::STARTING || |
1464 running_status() == EmbeddedWorkerStatus::STOPPING) | 1478 running_status() == EmbeddedWorkerStatus::STOPPING) |
1465 << static_cast<int>(running_status()); | 1479 << static_cast<int>(running_status()); |
1466 scoped_refptr<ServiceWorkerVersion> protect(this); | 1480 scoped_refptr<ServiceWorkerVersion> protect(this); |
1467 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); | 1481 FinishStartWorker(SERVICE_WORKER_ERROR_TIMEOUT); |
1468 if (running_status() == EmbeddedWorkerStatus::STARTING) | 1482 if (running_status() == EmbeddedWorkerStatus::STARTING) |
1469 embedded_worker_->Stop(); | 1483 embedded_worker_->Stop(); |
1470 return; | 1484 return; |
1471 } | 1485 } |
1472 | 1486 |
1473 // Requests have not finished before their expiration. | 1487 // Requests have not finished before their expiration. |
1474 bool stop_for_timeout = false; | 1488 bool stop_for_timeout = false; |
1475 while (!timeout_queue_.empty()) { | 1489 while (!timeout_queue_.empty()) { |
1476 RequestInfo info = timeout_queue_.top(); | 1490 RequestInfo info = timeout_queue_.top(); |
1477 if (!RequestExpired(info.expiration)) | 1491 if (!RequestExpired(info.expiration)) |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1689 should_restart); | 1703 should_restart); |
1690 ClearTick(&stop_time_); | 1704 ClearTick(&stop_time_); |
1691 } | 1705 } |
1692 StopTimeoutTimer(); | 1706 StopTimeoutTimer(); |
1693 | 1707 |
1694 // Fire all stop callbacks. | 1708 // Fire all stop callbacks. |
1695 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); | 1709 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); |
1696 | 1710 |
1697 if (!should_restart) { | 1711 if (!should_restart) { |
1698 // Let all start callbacks fail. | 1712 // Let all start callbacks fail. |
1699 RunCallbacks(this, &start_callbacks_, | 1713 FinishStartWorker(DeduceStartWorkerFailureReason( |
1700 DeduceStartWorkerFailureReason( | 1714 SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
1701 SERVICE_WORKER_ERROR_START_WORKER_FAILED)); | |
1702 } | 1715 } |
1703 | 1716 |
1704 // Let all message callbacks fail (this will also fire and clear all | 1717 // Let all message callbacks fail (this will also fire and clear all |
1705 // callbacks for events). | 1718 // callbacks for events). |
1706 // TODO(kinuko): Consider if we want to add queue+resend mechanism here. | 1719 // TODO(kinuko): Consider if we want to add queue+resend mechanism here. |
1707 IDMap<PendingRequest, IDMapOwnPointer>::iterator iter(&pending_requests_); | 1720 IDMap<PendingRequest, IDMapOwnPointer>::iterator iter(&pending_requests_); |
1708 while (!iter.IsAtEnd()) { | 1721 while (!iter.IsAtEnd()) { |
1709 TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request", | 1722 TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request", |
1710 iter.GetCurrentValue(), "Error", "Worker Stopped"); | 1723 iter.GetCurrentValue(), "Error", "Worker Stopped"); |
1711 iter.GetCurrentValue()->error_callback.Run(SERVICE_WORKER_ERROR_FAILED); | 1724 iter.GetCurrentValue()->error_callback.Run(SERVICE_WORKER_ERROR_FAILED); |
(...skipping 24 matching lines...) Expand all Loading... |
1736 void ServiceWorkerVersion::OnBeginEvent() { | 1749 void ServiceWorkerVersion::OnBeginEvent() { |
1737 if (should_exclude_from_uma_ || | 1750 if (should_exclude_from_uma_ || |
1738 running_status() != EmbeddedWorkerStatus::RUNNING || | 1751 running_status() != EmbeddedWorkerStatus::RUNNING || |
1739 idle_time_.is_null()) { | 1752 idle_time_.is_null()) { |
1740 return; | 1753 return; |
1741 } | 1754 } |
1742 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() - | 1755 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() - |
1743 idle_time_); | 1756 idle_time_); |
1744 } | 1757 } |
1745 | 1758 |
| 1759 void ServiceWorkerVersion::FinishStartWorker(ServiceWorkerStatusCode status) { |
| 1760 start_worker_first_purpose_ = base::nullopt; |
| 1761 RunCallbacks(this, &start_callbacks_, status); |
| 1762 } |
| 1763 |
1746 } // namespace content | 1764 } // namespace content |
OLD | NEW |