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

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: incorporated nhiroki's comment 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_,
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698