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