Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: content/browser/service_worker/service_worker_version.cc

Issue 2045153003: Speculatively launch Service Workers on mouse/touch events. [4/5] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add test Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698