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

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: Logic bug 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::TimeTicks expiration,
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, expiration, callback)));
falken 2015/12/17 13:54:32 This means the expiration includes the time to sta
jkarlin 2015/12/17 15:01:54 Good idea. Done.
815 return; 822 return;
816 } 823 }
817 824
818 int request_id = AddRequest(callback, &sync_requests_, REQUEST_SYNC); 825 int request_id = AddRequestWithExpiration(callback, &sync_requests_,
826 REQUEST_SYNC, expiration);
819 if (!background_sync_dispatcher_) { 827 if (!background_sync_dispatcher_) {
820 embedded_worker_->GetServiceRegistry()->ConnectToRemoteService( 828 embedded_worker_->GetServiceRegistry()->ConnectToRemoteService(
821 mojo::GetProxy(&background_sync_dispatcher_)); 829 mojo::GetProxy(&background_sync_dispatcher_));
822 background_sync_dispatcher_.set_connection_error_handler(base::Bind( 830 background_sync_dispatcher_.set_connection_error_handler(base::Bind(
823 &ServiceWorkerVersion::OnBackgroundSyncDispatcherConnectionError, 831 &ServiceWorkerVersion::OnBackgroundSyncDispatcherConnectionError,
824 weak_factory_.GetWeakPtr())); 832 weak_factory_.GetWeakPtr()));
825 } 833 }
826 834
827 background_sync_dispatcher_->Sync( 835 background_sync_dispatcher_->Sync(
828 handle_id, last_chance, 836 handle_id, last_chance,
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 if (attached) { 1080 if (attached) {
1073 // TODO(falken): Canceling the timeouts when debugging could cause 1081 // TODO(falken): Canceling the timeouts when debugging could cause
1074 // heisenbugs; we should instead run them as normal show an educational 1082 // heisenbugs; we should instead run them as normal show an educational
1075 // message in DevTools when they occur. crbug.com/470419 1083 // message in DevTools when they occur. crbug.com/470419
1076 1084
1077 // Don't record the startup time metric once DevTools is attached. 1085 // Don't record the startup time metric once DevTools is attached.
1078 ClearTick(&start_time_); 1086 ClearTick(&start_time_);
1079 skip_recording_startup_time_ = true; 1087 skip_recording_startup_time_ = true;
1080 1088
1081 // Cancel request timeouts. 1089 // Cancel request timeouts.
1082 SetAllRequestTimes(base::TimeTicks()); 1090 SetAllRequestExpirations(base::TimeTicks());
1083 return; 1091 return;
1084 } 1092 }
1085 if (!start_callbacks_.empty()) { 1093 if (!start_callbacks_.empty()) {
1086 // Reactivate the timer for start timeout. 1094 // Reactivate the timer for start timeout.
1087 DCHECK(timeout_timer_.IsRunning()); 1095 DCHECK(timeout_timer_.IsRunning());
1088 DCHECK(running_status() == STARTING || running_status() == STOPPING) 1096 DCHECK(running_status() == STARTING || running_status() == STOPPING)
1089 << running_status(); 1097 << running_status();
1090 RestartTick(&start_time_); 1098 RestartTick(&start_time_);
1091 } 1099 }
1092 1100
1093 // Reactivate request timeouts. 1101 // Reactivate request timeouts, setting them all to the same expiration time.
1094 SetAllRequestTimes(base::TimeTicks::Now()); 1102 SetAllRequestExpirations(
falken 2015/12/17 13:54:32 So this means the sync event's expiration is not h
jkarlin 2015/12/17 15:01:54 Ack.
1103 base::TimeTicks::Now() +
1104 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes));
1095 } 1105 }
1096 1106
1097 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( 1107 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
1098 const net::HttpResponseInfo& http_info) { 1108 const net::HttpResponseInfo& http_info) {
1099 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); 1109 main_script_http_info_.reset(new net::HttpResponseInfo(http_info));
1100 FOR_EACH_OBSERVER(Listener, listeners_, 1110 FOR_EACH_OBSERVER(Listener, listeners_,
1101 OnMainScriptHttpResponseInfoSet(this)); 1111 OnMainScriptHttpResponseInfoSet(this));
1102 } 1112 }
1103 1113
1104 void ServiceWorkerVersion::SimulatePingTimeoutForTesting() { 1114 void ServiceWorkerVersion::SimulatePingTimeoutForTesting() {
1105 ping_controller_->SimulateTimeoutForTesting(); 1115 ping_controller_->SimulateTimeoutForTesting();
1106 } 1116 }
1107 1117
1108 const net::HttpResponseInfo* 1118 const net::HttpResponseInfo*
1109 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { 1119 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
1110 return main_script_http_info_.get(); 1120 return main_script_http_info_.get();
1111 } 1121 }
1112 1122
1113 ServiceWorkerVersion::RequestInfo::RequestInfo(int id, 1123 ServiceWorkerVersion::RequestInfo::RequestInfo(
1114 RequestType type, 1124 int id,
1115 const base::TimeTicks& now) 1125 RequestType type,
1116 : id(id), type(type), time(now) { 1126 const base::TimeTicks& expiration)
1127 : id(id), type(type), expiration(expiration) {}
1128
1129 ServiceWorkerVersion::RequestInfo::~RequestInfo() {
1117 } 1130 }
1118 1131
1119 ServiceWorkerVersion::RequestInfo::~RequestInfo() { 1132 bool ServiceWorkerVersion::RequestInfo::operator>(
1133 const RequestInfo& other) const {
1134 return expiration > other.expiration;
1120 } 1135 }
1121 1136
1122 template <typename CallbackType> 1137 template <typename CallbackType>
1123 ServiceWorkerVersion::PendingRequest<CallbackType>::PendingRequest( 1138 ServiceWorkerVersion::PendingRequest<CallbackType>::PendingRequest(
1124 const CallbackType& callback, 1139 const CallbackType& callback,
1125 const base::TimeTicks& time) 1140 const base::TimeTicks& time)
1126 : callback(callback), start_time(time) { 1141 : callback(callback), start_time(time) {
1127 } 1142 }
1128 1143
1129 template <typename CallbackType> 1144 template <typename CallbackType>
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1426 } 1441 }
1427 1442
1428 void ServiceWorkerVersion::OnSyncEventFinished( 1443 void ServiceWorkerVersion::OnSyncEventFinished(
1429 int request_id, 1444 int request_id,
1430 ServiceWorkerEventStatus status) { 1445 ServiceWorkerEventStatus status) {
1431 TRACE_EVENT1("ServiceWorker", 1446 TRACE_EVENT1("ServiceWorker",
1432 "ServiceWorkerVersion::OnSyncEventFinished", 1447 "ServiceWorkerVersion::OnSyncEventFinished",
1433 "Request id", request_id); 1448 "Request id", request_id);
1434 PendingRequest<StatusCallback>* request = sync_requests_.Lookup(request_id); 1449 PendingRequest<StatusCallback>* request = sync_requests_.Lookup(request_id);
1435 if (!request) { 1450 if (!request) {
1436 NOTREACHED() << "Got unexpected message: " << request_id; 1451 // Assume the request timed out.
1437 return; 1452 return;
1438 } 1453 }
1439 1454
1440 scoped_refptr<ServiceWorkerVersion> protect(this); 1455 scoped_refptr<ServiceWorkerVersion> protect(this);
1441 request->callback.Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status)); 1456 request->callback.Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status));
1442 RemoveCallbackAndStopIfRedundant(&sync_requests_, request_id); 1457 RemoveCallbackAndStopIfRedundant(&sync_requests_, request_id);
1443 } 1458 }
1444 1459
1445 void ServiceWorkerVersion::OnNotificationClickEventFinished( 1460 void ServiceWorkerVersion::OnNotificationClickEventFinished(
1446 int request_id) { 1461 int request_id) {
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
2112 if (GetTickDuration(start_time_) > start_limit) { 2127 if (GetTickDuration(start_time_) > start_limit) {
2113 DCHECK(running_status() == STARTING || running_status() == STOPPING) 2128 DCHECK(running_status() == STARTING || running_status() == STOPPING)
2114 << running_status(); 2129 << running_status();
2115 scoped_refptr<ServiceWorkerVersion> protect(this); 2130 scoped_refptr<ServiceWorkerVersion> protect(this);
2116 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); 2131 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
2117 if (running_status() == STARTING) 2132 if (running_status() == STARTING)
2118 embedded_worker_->Stop(); 2133 embedded_worker_->Stop();
2119 return; 2134 return;
2120 } 2135 }
2121 2136
2122 // Requests have not finished within a certain period. 2137 // Requests have not finished before their expiration.
2123 bool request_timed_out = false; 2138 bool stop_for_timeout = false;
2124 while (!requests_.empty()) { 2139 while (!requests_.empty()) {
2125 RequestInfo info = requests_.front(); 2140 RequestInfo info = requests_.top();
2126 if (GetTickDuration(info.time) < 2141 if (!RequestExpired(info.expiration))
2127 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes))
2128 break; 2142 break;
2129 if (MaybeTimeOutRequest(info)) { 2143 if (MaybeTimeOutRequest(info)) {
2130 request_timed_out = true; 2144 stop_for_timeout = stop_for_timeout || ShouldStopIfRequestTimesOut(info);
2131 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.RequestTimeouts.Count", 2145 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.RequestTimeouts.Count",
2132 info.type, NUM_REQUEST_TYPES); 2146 info.type, NUM_REQUEST_TYPES);
falken 2015/12/17 13:54:32 Do you have/want UMA to track how frequent the syn
jkarlin 2015/12/17 15:01:54 Added BackgroundSyncEvent.Time.
2133 } 2147 }
2134 requests_.pop(); 2148 requests_.pop();
2135 } 2149 }
2136 if (request_timed_out && running_status() != STOPPING) 2150 if (stop_for_timeout && running_status() != STOPPING)
2137 embedded_worker_->Stop(); 2151 embedded_worker_->Stop();
2138 2152
2139 // For the timeouts below, there are no callbacks to timeout so there is 2153 // For the timeouts below, there are no callbacks to timeout so there is
2140 // nothing more to do if the worker is already stopping. 2154 // nothing more to do if the worker is already stopping.
2141 if (running_status() == STOPPING) 2155 if (running_status() == STOPPING)
2142 return; 2156 return;
2143 2157
2144 // The worker has been idle for longer than a certain period. 2158 // The worker has been idle for longer than a certain period.
2145 if (GetTickDuration(idle_time_) > 2159 if (GetTickDuration(idle_time_) >
2146 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { 2160 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 // order to release worker resources soon. 2247 // order to release worker resources soon.
2234 StopWorkerIfIdle(); 2248 StopWorkerIfIdle();
2235 } 2249 }
2236 } 2250 }
2237 2251
2238 template <typename CallbackType> 2252 template <typename CallbackType>
2239 int ServiceWorkerVersion::AddRequest( 2253 int ServiceWorkerVersion::AddRequest(
2240 const CallbackType& callback, 2254 const CallbackType& callback,
2241 IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map, 2255 IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
2242 RequestType request_type) { 2256 RequestType request_type) {
2243 base::TimeTicks now = base::TimeTicks::Now(); 2257 base::TimeTicks expiration_time =
2244 int request_id = 2258 base::TimeTicks::Now() +
2245 callback_map->Add(new PendingRequest<CallbackType>(callback, now)); 2259 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes);
2246 requests_.push(RequestInfo(request_id, request_type, now)); 2260 return AddRequestWithExpiration(callback, callback_map, request_type,
2261 expiration_time);
2262 }
2263
2264 template <typename CallbackType>
2265 int ServiceWorkerVersion::AddRequestWithExpiration(
2266 const CallbackType& callback,
2267 IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
2268 RequestType request_type,
2269 base::TimeTicks expiration) {
2270 int request_id = callback_map->Add(
2271 new PendingRequest<CallbackType>(callback, base::TimeTicks::Now()));
2272 requests_.push(RequestInfo(request_id, request_type, expiration));
2247 return request_id; 2273 return request_id;
2248 } 2274 }
2249 2275
2250 bool ServiceWorkerVersion::MaybeTimeOutRequest(const RequestInfo& info) { 2276 bool ServiceWorkerVersion::MaybeTimeOutRequest(const RequestInfo& info) {
2251 switch (info.type) { 2277 switch (info.type) {
2252 case REQUEST_ACTIVATE: 2278 case REQUEST_ACTIVATE:
2253 return RunIDMapCallback(&activate_requests_, info.id, 2279 return RunIDMapCallback(&activate_requests_, info.id,
2254 SERVICE_WORKER_ERROR_TIMEOUT); 2280 SERVICE_WORKER_ERROR_TIMEOUT);
2255 case REQUEST_INSTALL: 2281 case REQUEST_INSTALL:
2256 return RunIDMapCallback(&install_requests_, info.id, 2282 return RunIDMapCallback(&install_requests_, info.id,
(...skipping 20 matching lines...) Expand all
2277 SERVICE_WORKER_ERROR_TIMEOUT, 2303 SERVICE_WORKER_ERROR_TIMEOUT,
2278 false /* accept_connection */, base::string16(), 2304 false /* accept_connection */, base::string16(),
2279 base::string16()); 2305 base::string16());
2280 case NUM_REQUEST_TYPES: 2306 case NUM_REQUEST_TYPES:
2281 break; 2307 break;
2282 } 2308 }
2283 NOTREACHED() << "Got unexpected request type: " << info.type; 2309 NOTREACHED() << "Got unexpected request type: " << info.type;
2284 return false; 2310 return false;
2285 } 2311 }
2286 2312
2287 void ServiceWorkerVersion::SetAllRequestTimes(const base::TimeTicks& ticks) { 2313 bool ServiceWorkerVersion::ShouldStopIfRequestTimesOut(
2288 std::queue<RequestInfo> new_requests; 2314 const RequestInfo& info) {
2315 // Note, returning true for a type means that the On*EventFinished should not
falken 2015/12/17 13:54:32 returning false?
jkarlin 2015/12/17 15:01:54 Thanks. Done.
2316 // call NOTREACHED if it can't find the matching request, it may have simply
2317 // timed out.
2318 switch (info.type) {
2319 case REQUEST_SYNC:
2320 return false;
2321 case REQUEST_ACTIVATE:
2322 case REQUEST_INSTALL:
2323 case REQUEST_FETCH:
2324 case REQUEST_NOTIFICATION_CLICK:
2325 case REQUEST_PUSH:
2326 case REQUEST_GEOFENCING:
2327 case REQUEST_SERVICE_PORT_CONNECT:
2328 case NUM_REQUEST_TYPES:
2329 return true;
2330 }
2331 NOTREACHED() << "Got unexpected request type: " << info.type;
2332 return false;
2333 }
2334
2335 void ServiceWorkerVersion::SetAllRequestExpirations(
2336 const base::TimeTicks& expiration) {
2337 RequestInfoPriorityQueue new_requests;
2289 while (!requests_.empty()) { 2338 while (!requests_.empty()) {
2290 RequestInfo info = requests_.front(); 2339 RequestInfo info = requests_.top();
2291 info.time = ticks; 2340 info.expiration = expiration;
2292 new_requests.push(info); 2341 new_requests.push(info);
2293 requests_.pop(); 2342 requests_.pop();
2294 } 2343 }
2295 requests_ = new_requests; 2344 requests_ = new_requests;
2296 } 2345 }
2297 2346
2298 ServiceWorkerStatusCode ServiceWorkerVersion::DeduceStartWorkerFailureReason( 2347 ServiceWorkerStatusCode ServiceWorkerVersion::DeduceStartWorkerFailureReason(
2299 ServiceWorkerStatusCode default_code) { 2348 ServiceWorkerStatusCode default_code) {
2300 if (ping_controller_->IsTimedOut()) 2349 if (ping_controller_->IsTimedOut())
2301 return SERVICE_WORKER_ERROR_TIMEOUT; 2350 return SERVICE_WORKER_ERROR_TIMEOUT;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 void ServiceWorkerVersion::OnBeginEvent() { 2475 void ServiceWorkerVersion::OnBeginEvent() {
2427 if (should_exclude_from_uma_ || running_status() != RUNNING || 2476 if (should_exclude_from_uma_ || running_status() != RUNNING ||
2428 idle_time_.is_null()) { 2477 idle_time_.is_null()) {
2429 return; 2478 return;
2430 } 2479 }
2431 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() - 2480 ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeTicks::Now() -
2432 idle_time_); 2481 idle_time_);
2433 } 2482 }
2434 2483
2435 } // namespace content 2484 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698