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

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

Issue 2000063005: [WIP] Speculatively launch Service Workers on mouse/touch events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/service_worker/service_worker_version.h ('k') | content/child/runtime_features.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698