OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |