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

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

Issue 1525743002: Allow ServiceWorker events to have custom durations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use std::move instead of .Pass Created 5 years 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 <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 10
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 322 }
323 323
324 void ClearTick(base::TimeTicks* time) { 324 void ClearTick(base::TimeTicks* time) {
325 *time = base::TimeTicks(); 325 *time = base::TimeTicks();
326 } 326 }
327 327
328 void RestartTick(base::TimeTicks* time) { 328 void RestartTick(base::TimeTicks* time) {
329 *time = base::TimeTicks().Now(); 329 *time = base::TimeTicks().Now();
330 } 330 }
331 331
332 bool RequestExpired(const base::TimeTicks& expiration) {
333 if (expiration.is_null())
334 return false;
335 return base::TimeTicks().Now() >= expiration;
336 }
337
332 base::TimeDelta GetTickDuration(const base::TimeTicks& time) { 338 base::TimeDelta GetTickDuration(const base::TimeTicks& time) {
333 if (time.is_null()) 339 if (time.is_null())
334 return base::TimeDelta(); 340 return base::TimeDelta();
335 return base::TimeTicks().Now() - time; 341 return base::TimeTicks().Now() - time;
336 } 342 }
337 343
338 void OnGetWindowClientsFromUI( 344 void OnGetWindowClientsFromUI(
339 // The tuple contains process_id, frame_id, client_uuid. 345 // The tuple contains process_id, frame_id, client_uuid.
340 const std::vector<base::Tuple<int, int, std::string>>& clients_info, 346 const std::vector<base::Tuple<int, int, std::string>>& clients_info,
341 const GURL& script_url, 347 const GURL& script_url,
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 fetch_requests_.Remove(request_id); 802 fetch_requests_.Remove(request_id);
797 RunSoon(base::Bind(&RunErrorFetchCallback, 803 RunSoon(base::Bind(&RunErrorFetchCallback,
798 fetch_callback, 804 fetch_callback,
799 SERVICE_WORKER_ERROR_FAILED)); 805 SERVICE_WORKER_ERROR_FAILED));
800 } 806 }
801 } 807 }
802 808
803 void ServiceWorkerVersion::DispatchSyncEvent( 809 void ServiceWorkerVersion::DispatchSyncEvent(
804 BackgroundSyncRegistrationHandle::HandleId handle_id, 810 BackgroundSyncRegistrationHandle::HandleId handle_id,
805 BackgroundSyncEventLastChance last_chance, 811 BackgroundSyncEventLastChance last_chance,
812 base::TimeDelta max_duration,
806 const StatusCallback& callback) { 813 const StatusCallback& callback) {
807 OnBeginEvent(); 814 OnBeginEvent();
808 DCHECK_EQ(ACTIVATED, status()) << status(); 815 DCHECK_EQ(ACTIVATED, status()) << status();
809 if (running_status() != RUNNING) { 816 if (running_status() != RUNNING) {
810 // Schedule calling this method after starting the worker. 817 // Schedule calling this method after starting the worker.
811 StartWorker(base::Bind( 818 StartWorker(base::Bind(
812 &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), callback, 819 &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), callback,
813 base::Bind(&self::DispatchSyncEvent, weak_factory_.GetWeakPtr(), 820 base::Bind(&self::DispatchSyncEvent, weak_factory_.GetWeakPtr(),
814 handle_id, last_chance, callback))); 821 handle_id, last_chance, max_duration, callback)));
815 return; 822 return;
816 } 823 }
817 824
818 int request_id = AddRequest(callback, &sync_requests_, REQUEST_SYNC); 825 int request_id =
826 AddRequestWithExpiration(callback, &sync_requests_, REQUEST_SYNC,
827 base::TimeTicks::Now() + max_duration);
819 if (!background_sync_dispatcher_) { 828 if (!background_sync_dispatcher_) {
820 embedded_worker_->GetServiceRegistry()->ConnectToRemoteService( 829 embedded_worker_->GetServiceRegistry()->ConnectToRemoteService(
821 mojo::GetProxy(&background_sync_dispatcher_)); 830 mojo::GetProxy(&background_sync_dispatcher_));
822 background_sync_dispatcher_.set_connection_error_handler(base::Bind( 831 background_sync_dispatcher_.set_connection_error_handler(base::Bind(
823 &ServiceWorkerVersion::OnBackgroundSyncDispatcherConnectionError, 832 &ServiceWorkerVersion::OnBackgroundSyncDispatcherConnectionError,
824 weak_factory_.GetWeakPtr())); 833 weak_factory_.GetWeakPtr()));
825 } 834 }
826 835
827 background_sync_dispatcher_->Sync( 836 background_sync_dispatcher_->Sync(
828 handle_id, last_chance, 837 handle_id, last_chance,
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 if (attached) { 1081 if (attached) {
1073 // TODO(falken): Canceling the timeouts when debugging could cause 1082 // TODO(falken): Canceling the timeouts when debugging could cause
1074 // heisenbugs; we should instead run them as normal show an educational 1083 // heisenbugs; we should instead run them as normal show an educational
1075 // message in DevTools when they occur. crbug.com/470419 1084 // message in DevTools when they occur. crbug.com/470419
1076 1085
1077 // Don't record the startup time metric once DevTools is attached. 1086 // Don't record the startup time metric once DevTools is attached.
1078 ClearTick(&start_time_); 1087 ClearTick(&start_time_);
1079 skip_recording_startup_time_ = true; 1088 skip_recording_startup_time_ = true;
1080 1089
1081 // Cancel request timeouts. 1090 // Cancel request timeouts.
1082 SetAllRequestTimes(base::TimeTicks()); 1091 SetAllRequestExpirations(base::TimeTicks());
1083 return; 1092 return;
1084 } 1093 }
1085 if (!start_callbacks_.empty()) { 1094 if (!start_callbacks_.empty()) {
1086 // Reactivate the timer for start timeout. 1095 // Reactivate the timer for start timeout.
1087 DCHECK(timeout_timer_.IsRunning()); 1096 DCHECK(timeout_timer_.IsRunning());
1088 DCHECK(running_status() == STARTING || running_status() == STOPPING) 1097 DCHECK(running_status() == STARTING || running_status() == STOPPING)
1089 << running_status(); 1098 << running_status();
1090 RestartTick(&start_time_); 1099 RestartTick(&start_time_);
1091 } 1100 }
1092 1101
1093 // Reactivate request timeouts. 1102 // Reactivate request timeouts, setting them all to the same expiration time.
1094 SetAllRequestTimes(base::TimeTicks::Now()); 1103 SetAllRequestExpirations(
1104 base::TimeTicks::Now() +
1105 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes));
1095 } 1106 }
1096 1107
1097 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( 1108 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
1098 const net::HttpResponseInfo& http_info) { 1109 const net::HttpResponseInfo& http_info) {
1099 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); 1110 main_script_http_info_.reset(new net::HttpResponseInfo(http_info));
1100 FOR_EACH_OBSERVER(Listener, listeners_, 1111 FOR_EACH_OBSERVER(Listener, listeners_,
1101 OnMainScriptHttpResponseInfoSet(this)); 1112 OnMainScriptHttpResponseInfoSet(this));
1102 } 1113 }
1103 1114
1104 void ServiceWorkerVersion::SimulatePingTimeoutForTesting() { 1115 void ServiceWorkerVersion::SimulatePingTimeoutForTesting() {
1105 ping_controller_->SimulateTimeoutForTesting(); 1116 ping_controller_->SimulateTimeoutForTesting();
1106 } 1117 }
1107 1118
1108 const net::HttpResponseInfo* 1119 const net::HttpResponseInfo*
1109 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { 1120 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
1110 return main_script_http_info_.get(); 1121 return main_script_http_info_.get();
1111 } 1122 }
1112 1123
1113 ServiceWorkerVersion::RequestInfo::RequestInfo(int id, 1124 ServiceWorkerVersion::RequestInfo::RequestInfo(
1114 RequestType type, 1125 int id,
1115 const base::TimeTicks& now) 1126 RequestType type,
1116 : id(id), type(type), time(now) { 1127 const base::TimeTicks& expiration)
1128 : id(id), type(type), expiration(expiration) {}
1129
1130 ServiceWorkerVersion::RequestInfo::~RequestInfo() {
1117 } 1131 }
1118 1132
1119 ServiceWorkerVersion::RequestInfo::~RequestInfo() { 1133 bool ServiceWorkerVersion::RequestInfo::operator>(
1134 const RequestInfo& other) const {
1135 return expiration > other.expiration;
1120 } 1136 }
1121 1137
1122 template <typename CallbackType> 1138 template <typename CallbackType>
1123 ServiceWorkerVersion::PendingRequest<CallbackType>::PendingRequest( 1139 ServiceWorkerVersion::PendingRequest<CallbackType>::PendingRequest(
1124 const CallbackType& callback, 1140 const CallbackType& callback,
1125 const base::TimeTicks& time) 1141 const base::TimeTicks& time)
1126 : callback(callback), start_time(time) { 1142 : callback(callback), start_time(time) {
1127 } 1143 }
1128 1144
1129 template <typename CallbackType> 1145 template <typename CallbackType>
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1426 } 1442 }
1427 1443
1428 void ServiceWorkerVersion::OnSyncEventFinished( 1444 void ServiceWorkerVersion::OnSyncEventFinished(
1429 int request_id, 1445 int request_id,
1430 ServiceWorkerEventStatus status) { 1446 ServiceWorkerEventStatus status) {
1431 TRACE_EVENT1("ServiceWorker", 1447 TRACE_EVENT1("ServiceWorker",
1432 "ServiceWorkerVersion::OnSyncEventFinished", 1448 "ServiceWorkerVersion::OnSyncEventFinished",
1433 "Request id", request_id); 1449 "Request id", request_id);
1434 PendingRequest<StatusCallback>* request = sync_requests_.Lookup(request_id); 1450 PendingRequest<StatusCallback>* request = sync_requests_.Lookup(request_id);
1435 if (!request) { 1451 if (!request) {
1436 NOTREACHED() << "Got unexpected message: " << request_id; 1452 // Assume the request timed out.
1437 return; 1453 return;
1438 } 1454 }
1439 1455
1456 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.BackgroundSyncEvent.Time",
1457 base::TimeTicks::Now() - request->start_time);
1458
1440 scoped_refptr<ServiceWorkerVersion> protect(this); 1459 scoped_refptr<ServiceWorkerVersion> protect(this);
1441 request->callback.Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status)); 1460 request->callback.Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status));
1442 RemoveCallbackAndStopIfRedundant(&sync_requests_, request_id); 1461 RemoveCallbackAndStopIfRedundant(&sync_requests_, request_id);
1443 } 1462 }
1444 1463
1445 void ServiceWorkerVersion::OnNotificationClickEventFinished( 1464 void ServiceWorkerVersion::OnNotificationClickEventFinished(
1446 int request_id) { 1465 int request_id) {
1447 TRACE_EVENT1("ServiceWorker", 1466 TRACE_EVENT1("ServiceWorker",
1448 "ServiceWorkerVersion::OnNotificationClickEventFinished", 1467 "ServiceWorkerVersion::OnNotificationClickEventFinished",
1449 "Request id", request_id); 1468 "Request id", request_id);
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
2112 if (GetTickDuration(start_time_) > start_limit) { 2131 if (GetTickDuration(start_time_) > start_limit) {
2113 DCHECK(running_status() == STARTING || running_status() == STOPPING) 2132 DCHECK(running_status() == STARTING || running_status() == STOPPING)
2114 << running_status(); 2133 << running_status();
2115 scoped_refptr<ServiceWorkerVersion> protect(this); 2134 scoped_refptr<ServiceWorkerVersion> protect(this);
2116 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); 2135 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
2117 if (running_status() == STARTING) 2136 if (running_status() == STARTING)
2118 embedded_worker_->Stop(); 2137 embedded_worker_->Stop();
2119 return; 2138 return;
2120 } 2139 }
2121 2140
2122 // Requests have not finished within a certain period. 2141 // Requests have not finished before their expiration.
2123 bool request_timed_out = false; 2142 bool stop_for_timeout = false;
2124 while (!requests_.empty()) { 2143 while (!requests_.empty()) {
2125 RequestInfo info = requests_.front(); 2144 RequestInfo info = requests_.top();
2126 if (GetTickDuration(info.time) < 2145 if (!RequestExpired(info.expiration))
2127 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes))
2128 break; 2146 break;
2129 if (MaybeTimeOutRequest(info)) { 2147 if (MaybeTimeOutRequest(info)) {
2130 request_timed_out = true; 2148 stop_for_timeout = stop_for_timeout || ShouldStopIfRequestTimesOut(info);
2131 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.RequestTimeouts.Count", 2149 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.RequestTimeouts.Count",
2132 info.type, NUM_REQUEST_TYPES); 2150 info.type, NUM_REQUEST_TYPES);
2133 } 2151 }
2134 requests_.pop(); 2152 requests_.pop();
2135 } 2153 }
2136 if (request_timed_out && running_status() != STOPPING) 2154 if (stop_for_timeout && running_status() != STOPPING)
2137 embedded_worker_->Stop(); 2155 embedded_worker_->Stop();
2138 2156
2139 // For the timeouts below, there are no callbacks to timeout so there is 2157 // For the timeouts below, there are no callbacks to timeout so there is
2140 // nothing more to do if the worker is already stopping. 2158 // nothing more to do if the worker is already stopping.
2141 if (running_status() == STOPPING) 2159 if (running_status() == STOPPING)
2142 return; 2160 return;
2143 2161
2144 // The worker has been idle for longer than a certain period. 2162 // The worker has been idle for longer than a certain period.
2145 if (GetTickDuration(idle_time_) > 2163 if (GetTickDuration(idle_time_) >
2146 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { 2164 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 // order to release worker resources soon. 2251 // order to release worker resources soon.
2234 StopWorkerIfIdle(); 2252 StopWorkerIfIdle();
2235 } 2253 }
2236 } 2254 }
2237 2255
2238 template <typename CallbackType> 2256 template <typename CallbackType>
2239 int ServiceWorkerVersion::AddRequest( 2257 int ServiceWorkerVersion::AddRequest(
2240 const CallbackType& callback, 2258 const CallbackType& callback,
2241 IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map, 2259 IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
2242 RequestType request_type) { 2260 RequestType request_type) {
2243 base::TimeTicks now = base::TimeTicks::Now(); 2261 base::TimeTicks expiration_time =
2244 int request_id = 2262 base::TimeTicks::Now() +
2245 callback_map->Add(new PendingRequest<CallbackType>(callback, now)); 2263 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes);
2246 requests_.push(RequestInfo(request_id, request_type, now)); 2264 return AddRequestWithExpiration(callback, callback_map, request_type,
2265 expiration_time);
2266 }
2267
2268 template <typename CallbackType>
2269 int ServiceWorkerVersion::AddRequestWithExpiration(
2270 const CallbackType& callback,
2271 IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
2272 RequestType request_type,
2273 base::TimeTicks expiration) {
2274 int request_id = callback_map->Add(
2275 new PendingRequest<CallbackType>(callback, base::TimeTicks::Now()));
2276 requests_.push(RequestInfo(request_id, request_type, expiration));
2247 return request_id; 2277 return request_id;
2248 } 2278 }
2249 2279
2250 bool ServiceWorkerVersion::MaybeTimeOutRequest(const RequestInfo& info) { 2280 bool ServiceWorkerVersion::MaybeTimeOutRequest(const RequestInfo& info) {
2251 switch (info.type) { 2281 switch (info.type) {
2252 case REQUEST_ACTIVATE: 2282 case REQUEST_ACTIVATE:
2253 return RunIDMapCallback(&activate_requests_, info.id, 2283 return RunIDMapCallback(&activate_requests_, info.id,
2254 SERVICE_WORKER_ERROR_TIMEOUT); 2284 SERVICE_WORKER_ERROR_TIMEOUT);
2255 case REQUEST_INSTALL: 2285 case REQUEST_INSTALL:
2256 return RunIDMapCallback(&install_requests_, info.id, 2286 return RunIDMapCallback(&install_requests_, info.id,
(...skipping 20 matching lines...) Expand all
2277 SERVICE_WORKER_ERROR_TIMEOUT, 2307 SERVICE_WORKER_ERROR_TIMEOUT,
2278 false /* accept_connection */, base::string16(), 2308 false /* accept_connection */, base::string16(),
2279 base::string16()); 2309 base::string16());
2280 case NUM_REQUEST_TYPES: 2310 case NUM_REQUEST_TYPES:
2281 break; 2311 break;
2282 } 2312 }
2283 NOTREACHED() << "Got unexpected request type: " << info.type; 2313 NOTREACHED() << "Got unexpected request type: " << info.type;
2284 return false; 2314 return false;
2285 } 2315 }
2286 2316
2287 void ServiceWorkerVersion::SetAllRequestTimes(const base::TimeTicks& ticks) { 2317 bool ServiceWorkerVersion::ShouldStopIfRequestTimesOut(
2288 std::queue<RequestInfo> new_requests; 2318 const RequestInfo& info) {
2319 // Note, returning false for a type means that the On*EventFinished should not
2320 // call NOTREACHED if it can't find the matching request, it may have simply
2321 // timed out.
2322 switch (info.type) {
2323 case REQUEST_SYNC:
2324 return false;
2325 case REQUEST_ACTIVATE:
2326 case REQUEST_INSTALL:
2327 case REQUEST_FETCH:
2328 case REQUEST_NOTIFICATION_CLICK:
2329 case REQUEST_PUSH:
2330 case REQUEST_GEOFENCING:
2331 case REQUEST_SERVICE_PORT_CONNECT:
2332 return true;
2333 case NUM_REQUEST_TYPES:
2334 NOTREACHED() << "Got unexpected request type: " << info.type;
2335 }
2336 NOTREACHED() << "Got unexpected request type: " << info.type;
2337 return false;
2338 }
2339
2340 void ServiceWorkerVersion::SetAllRequestExpirations(
2341 const base::TimeTicks& expiration) {
2342 RequestInfoPriorityQueue new_requests;
2289 while (!requests_.empty()) { 2343 while (!requests_.empty()) {
2290 RequestInfo info = requests_.front(); 2344 RequestInfo info = requests_.top();
2291 info.time = ticks; 2345 info.expiration = expiration;
2292 new_requests.push(info); 2346 new_requests.push(info);
2293 requests_.pop(); 2347 requests_.pop();
2294 } 2348 }
2295 requests_ = new_requests; 2349 requests_ = new_requests;
2296 } 2350 }
2297 2351
2298 ServiceWorkerStatusCode ServiceWorkerVersion::DeduceStartWorkerFailureReason( 2352 ServiceWorkerStatusCode ServiceWorkerVersion::DeduceStartWorkerFailureReason(
2299 ServiceWorkerStatusCode default_code) { 2353 ServiceWorkerStatusCode default_code) {
2300 if (ping_controller_->IsTimedOut()) 2354 if (ping_controller_->IsTimedOut())
2301 return SERVICE_WORKER_ERROR_TIMEOUT; 2355 return SERVICE_WORKER_ERROR_TIMEOUT;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 void ServiceWorkerVersion::OnBeginEvent() { 2480 void ServiceWorkerVersion::OnBeginEvent() {
2427 if (should_exclude_from_uma_ || running_status() != RUNNING || 2481 if (should_exclude_from_uma_ || running_status() != RUNNING ||
2428 idle_time_.is_null()) { 2482 idle_time_.is_null()) {
2429 return; 2483 return;
2430 } 2484 }
2431 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() - 2485 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() -
2432 idle_time_); 2486 idle_time_);
2433 } 2487 }
2434 2488
2435 } // namespace content 2489 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698