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 "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
31 #include "content/public/browser/web_contents_observer.h" | 31 #include "content/public/browser/web_contents_observer.h" |
32 #include "content/public/common/child_process_host.h" | 32 #include "content/public/common/child_process_host.h" |
33 #include "content/public/common/content_client.h" | 33 #include "content/public/common/content_client.h" |
34 #include "content/public/common/content_switches.h" | 34 #include "content/public/common/content_switches.h" |
35 #include "content/public/common/result_codes.h" | 35 #include "content/public/common/result_codes.h" |
36 #include "net/http/http_response_info.h" | 36 #include "net/http/http_response_info.h" |
37 | 37 |
38 namespace content { | 38 namespace content { |
39 | 39 |
40 typedef ServiceWorkerVersion::StatusCallback StatusCallback; | 40 using StatusCallback = ServiceWorkerVersion::StatusCallback; |
41 | 41 using GetClientDocumentsCallback = |
42 class ServiceWorkerVersion::GetClientDocumentsCallback | 42 base::Callback<void(const std::vector<ServiceWorkerClientInfo>&)>; |
43 : public base::RefCounted<GetClientDocumentsCallback> { | |
44 public: | |
45 GetClientDocumentsCallback(int request_id, | |
46 ServiceWorkerVersion* version) | |
47 : request_id_(request_id), | |
48 version_(version) { | |
49 DCHECK(version_); | |
50 } | |
51 | |
52 void AddClientInfo(int client_id, const ServiceWorkerClientInfo& info) { | |
53 clients_.push_back(info); | |
54 clients_.back().client_id = client_id; | |
55 } | |
56 | |
57 private: | |
58 friend class base::RefCounted<GetClientDocumentsCallback>; | |
59 | |
60 virtual ~GetClientDocumentsCallback() { | |
61 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
62 | |
63 if (version_->running_status() == RUNNING) { | |
64 version_->embedded_worker_->SendMessage( | |
65 ServiceWorkerMsg_DidGetClientDocuments(request_id_, clients_)); | |
66 } | |
67 } | |
68 | |
69 std::vector<ServiceWorkerClientInfo> clients_; | |
70 int request_id_; | |
71 scoped_refptr<ServiceWorkerVersion> version_; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(GetClientDocumentsCallback); | |
74 }; | |
75 | 43 |
76 namespace { | 44 namespace { |
77 | 45 |
78 // Delay between the timeout timer firing. | 46 // Delay between the timeout timer firing. |
79 const int kTimeoutTimerDelaySeconds = 30; | 47 const int kTimeoutTimerDelaySeconds = 30; |
80 | 48 |
81 // Time to wait until stopping an idle worker. | 49 // Time to wait until stopping an idle worker. |
82 const int kIdleWorkerTimeoutSeconds = 30; | 50 const int kIdleWorkerTimeoutSeconds = 30; |
83 | 51 |
84 // Default delay for scheduled update. | 52 // Default delay for scheduled update. |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 void RestartTick(base::TimeTicks* time) { | 247 void RestartTick(base::TimeTicks* time) { |
280 *time = base::TimeTicks().Now(); | 248 *time = base::TimeTicks().Now(); |
281 } | 249 } |
282 | 250 |
283 base::TimeDelta GetTickDuration(const base::TimeTicks& time) { | 251 base::TimeDelta GetTickDuration(const base::TimeTicks& time) { |
284 if (time.is_null()) | 252 if (time.is_null()) |
285 return base::TimeDelta(); | 253 return base::TimeDelta(); |
286 return base::TimeTicks().Now() - time; | 254 return base::TimeTicks().Now() - time; |
287 } | 255 } |
288 | 256 |
257 void OnGetClientDocumentsFromUI( | |
258 // The tuple contains process_id, frame_id, client_id. | |
michaeln
2015/03/06 23:55:22
nice comment
| |
259 const std::vector<Tuple<int,int,int>>& clients_info, | |
260 const GURL& script_url, | |
261 const GetClientDocumentsCallback& callback) { | |
262 std::vector<ServiceWorkerClientInfo> clients; | |
263 | |
264 for (const auto& it : clients_info) { | |
265 ServiceWorkerClientInfo info = | |
266 ServiceWorkerProviderHost::GetClientInfoOnUI(get<0>(it), get<1>(it)); | |
267 | |
268 // If the request to the provider_host returned an empty | |
269 // ServiceWorkerClientInfo, that means that it wasn't possible to associate | |
270 // it with a valid RenderFrameHost. It might be because the frame was killed | |
271 // or navigated in between. | |
272 if (info.IsEmpty()) | |
273 continue; | |
274 | |
275 // We can get info for a frame that was navigating end ended up with a | |
276 // different URL than expected. In such case, we should make sure to not | |
277 // expose cross-origin WindowClient. | |
278 if (info.url.GetOrigin() != script_url.GetOrigin()) | |
279 return; | |
280 | |
281 info.client_id = get<2>(it); | |
282 clients.push_back(info); | |
283 } | |
284 | |
285 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
286 base::Bind(callback, clients)); | |
287 } | |
288 | |
289 } // namespace | 289 } // namespace |
290 | 290 |
291 ServiceWorkerVersion::ServiceWorkerVersion( | 291 ServiceWorkerVersion::ServiceWorkerVersion( |
292 ServiceWorkerRegistration* registration, | 292 ServiceWorkerRegistration* registration, |
293 const GURL& script_url, | 293 const GURL& script_url, |
294 int64 version_id, | 294 int64 version_id, |
295 base::WeakPtr<ServiceWorkerContextCore> context) | 295 base::WeakPtr<ServiceWorkerContextCore> context) |
296 : version_id_(version_id), | 296 : version_id_(version_id), |
297 registration_id_(kInvalidServiceWorkerVersionId), | 297 registration_id_(kInvalidServiceWorkerVersionId), |
298 script_url_(script_url), | 298 script_url_(script_url), |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
986 | 986 |
987 void ServiceWorkerVersion::OnGetClientDocuments(int request_id) { | 987 void ServiceWorkerVersion::OnGetClientDocuments(int request_id) { |
988 if (controllee_by_id_.IsEmpty()) { | 988 if (controllee_by_id_.IsEmpty()) { |
989 if (running_status() == RUNNING) { | 989 if (running_status() == RUNNING) { |
990 embedded_worker_->SendMessage( | 990 embedded_worker_->SendMessage( |
991 ServiceWorkerMsg_DidGetClientDocuments(request_id, | 991 ServiceWorkerMsg_DidGetClientDocuments(request_id, |
992 std::vector<ServiceWorkerClientInfo>())); | 992 std::vector<ServiceWorkerClientInfo>())); |
993 } | 993 } |
994 return; | 994 return; |
995 } | 995 } |
996 scoped_refptr<GetClientDocumentsCallback> callback( | 996 |
997 new GetClientDocumentsCallback(request_id, this)); | |
998 ControlleeByIDMap::iterator it(&controllee_by_id_); | |
999 TRACE_EVENT0("ServiceWorker", | 997 TRACE_EVENT0("ServiceWorker", |
1000 "ServiceWorkerVersion::OnGetClientDocuments"); | 998 "ServiceWorkerVersion::OnGetClientDocuments"); |
1001 while (!it.IsAtEnd()) { | 999 |
1002 // TODO(mlamouri): we could coalesce those requests into one. | 1000 std::vector<Tuple<int,int,int>> clients_info; |
1003 it.GetCurrentValue()->GetClientInfo( | 1001 for (ControlleeByIDMap::iterator it(&controllee_by_id_); !it.IsAtEnd(); |
1004 base::Bind(&ServiceWorkerVersion::DidGetClientInfo, | 1002 it.Advance()) { |
1005 weak_factory_.GetWeakPtr(), it.GetCurrentKey(), callback)); | 1003 int process_id = it.GetCurrentValue()->process_id(); |
1006 it.Advance(); | 1004 int frame_id = it.GetCurrentValue()->frame_id(); |
1005 int client_id = it.GetCurrentKey(); | |
1006 | |
1007 clients_info.push_back(MakeTuple(process_id, frame_id, client_id)); | |
1007 } | 1008 } |
1009 | |
1010 BrowserThread::PostTask( | |
1011 BrowserThread::UI, FROM_HERE, | |
1012 base::Bind(&OnGetClientDocumentsFromUI, clients_info, script_url_, | |
1013 base::Bind(&ServiceWorkerVersion::DidGetClientDocuments, | |
1014 weak_factory_.GetWeakPtr(), | |
1015 request_id))); | |
1016 | |
1008 } | 1017 } |
1009 | 1018 |
1010 void ServiceWorkerVersion::OnActivateEventFinished( | 1019 void ServiceWorkerVersion::OnActivateEventFinished( |
1011 int request_id, | 1020 int request_id, |
1012 blink::WebServiceWorkerEventResult result) { | 1021 blink::WebServiceWorkerEventResult result) { |
1013 DCHECK(ACTIVATING == status() || | 1022 DCHECK(ACTIVATING == status() || |
1014 REDUNDANT == status()) << status(); | 1023 REDUNDANT == status()) << status(); |
1015 TRACE_EVENT0("ServiceWorker", | 1024 TRACE_EVENT0("ServiceWorker", |
1016 "ServiceWorkerVersion::OnActivateEventFinished"); | 1025 "ServiceWorkerVersion::OnActivateEventFinished"); |
1017 | 1026 |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1390 if (status == SERVICE_WORKER_ERROR_ABORT) { | 1399 if (status == SERVICE_WORKER_ERROR_ABORT) { |
1391 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( | 1400 embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError( |
1392 request_id, blink::WebServiceWorkerError::ErrorTypeAbort, | 1401 request_id, blink::WebServiceWorkerError::ErrorTypeAbort, |
1393 base::ASCIIToUTF16(kClaimClientsShutdownErrorMesage))); | 1402 base::ASCIIToUTF16(kClaimClientsShutdownErrorMesage))); |
1394 return; | 1403 return; |
1395 } | 1404 } |
1396 DCHECK(status == SERVICE_WORKER_OK); | 1405 DCHECK(status == SERVICE_WORKER_OK); |
1397 embedded_worker_->SendMessage(ServiceWorkerMsg_DidClaimClients(request_id)); | 1406 embedded_worker_->SendMessage(ServiceWorkerMsg_DidClaimClients(request_id)); |
1398 } | 1407 } |
1399 | 1408 |
1400 void ServiceWorkerVersion::DidGetClientInfo( | 1409 void ServiceWorkerVersion::DidGetClientDocuments( |
1401 int client_id, | 1410 int request_id, |
1402 scoped_refptr<GetClientDocumentsCallback> callback, | 1411 const std::vector<ServiceWorkerClientInfo>& clients) { |
1403 const ServiceWorkerClientInfo& info) { | 1412 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1404 // If the request to the provider_host returned an empty | 1413 if (running_status() != RUNNING) |
1405 // ServiceWorkerClientInfo, that means that it wasn't possible to associate | |
1406 // it with a valid RenderFrameHost. It might be because the frame was killed | |
1407 // or navigated in between. | |
1408 if (info.IsEmpty()) | |
1409 return; | 1414 return; |
1410 | 1415 |
1411 // We can get info for a frame that was navigating end ended up with a | 1416 embedded_worker_->SendMessage( |
1412 // different URL than expected. In such case, we should make sure to not | 1417 ServiceWorkerMsg_DidGetClientDocuments(request_id, clients)); |
1413 // expose cross-origin WindowClient. | |
1414 if (info.url.GetOrigin() != script_url_.GetOrigin()) | |
1415 return; | |
1416 | |
1417 callback->AddClientInfo(client_id, info); | |
1418 } | 1418 } |
1419 | 1419 |
1420 void ServiceWorkerVersion::StartTimeoutTimer() { | 1420 void ServiceWorkerVersion::StartTimeoutTimer() { |
1421 DCHECK(!timeout_timer_.IsRunning()); | 1421 DCHECK(!timeout_timer_.IsRunning()); |
1422 ClearTick(&idle_time_); | 1422 ClearTick(&idle_time_); |
1423 ClearTick(&ping_time_); | 1423 ClearTick(&ping_time_); |
1424 ping_timed_out_ = false; | 1424 ping_timed_out_ = false; |
1425 timeout_timer_.Start(FROM_HERE, | 1425 timeout_timer_.Start(FROM_HERE, |
1426 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), | 1426 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), |
1427 this, &ServiceWorkerVersion::OnTimeoutTimer); | 1427 this, &ServiceWorkerVersion::OnTimeoutTimer); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1583 int request_id) { | 1583 int request_id) { |
1584 callbacks->Remove(request_id); | 1584 callbacks->Remove(request_id); |
1585 if (is_doomed_) { | 1585 if (is_doomed_) { |
1586 // The stop should be already scheduled, but try to stop immediately, in | 1586 // The stop should be already scheduled, but try to stop immediately, in |
1587 // order to release worker resources soon. | 1587 // order to release worker resources soon. |
1588 StopWorkerIfIdle(); | 1588 StopWorkerIfIdle(); |
1589 } | 1589 } |
1590 } | 1590 } |
1591 | 1591 |
1592 } // namespace content | 1592 } // namespace content |
OLD | NEW |