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/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 void AddClientInfo(int client_id, const ServiceWorkerClientInfo& info) { | 37 void AddClientInfo(int client_id, const ServiceWorkerClientInfo& info) { |
38 clients_.push_back(info); | 38 clients_.push_back(info); |
39 clients_.back().client_id = client_id; | 39 clients_.back().client_id = client_id; |
40 } | 40 } |
41 | 41 |
42 private: | 42 private: |
43 friend class base::RefCounted<GetClientDocumentsCallback>; | 43 friend class base::RefCounted<GetClientDocumentsCallback>; |
44 | 44 |
45 virtual ~GetClientDocumentsCallback() { | 45 virtual ~GetClientDocumentsCallback() { |
46 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
47 | |
48 if (version_->running_status() == RUNNING) { | 46 if (version_->running_status() == RUNNING) { |
49 version_->embedded_worker_->SendMessage( | 47 version_->embedded_worker_->SendMessage( |
50 ServiceWorkerMsg_DidGetClientDocuments(request_id_, clients_)); | 48 ServiceWorkerMsg_DidGetClientDocuments(request_id_, clients_)); |
51 } | 49 } |
52 } | 50 } |
53 | 51 |
54 std::vector<ServiceWorkerClientInfo> clients_; | 52 std::vector<ServiceWorkerClientInfo> clients_; |
55 int request_id_; | 53 int request_id_; |
56 scoped_refptr<ServiceWorkerVersion> version_; | 54 |
| 55 // |version_| must outlive this callback. |
| 56 ServiceWorkerVersion* version_; |
57 | 57 |
58 DISALLOW_COPY_AND_ASSIGN(GetClientDocumentsCallback); | 58 DISALLOW_COPY_AND_ASSIGN(GetClientDocumentsCallback); |
59 }; | 59 }; |
60 | 60 |
61 namespace { | 61 namespace { |
62 | 62 |
63 // Default delay for scheduled stop. | 63 // Default delay for scheduled stop. |
64 // (Note that if all references to the version is dropped the worker | 64 // (Note that if all references to the version is dropped the worker |
65 // is also stopped without delay) | 65 // is also stopped without delay) |
66 const int64 kStopWorkerDelay = 30; // 30 secs. | 66 const int64 kStopWorkerDelay = 30; // 30 secs. |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 &new_routing_ids); | 599 &new_routing_ids); |
600 ServiceWorkerStatusCode status = | 600 ServiceWorkerStatusCode status = |
601 embedded_worker_->SendMessage(ServiceWorkerMsg_CrossOriginMessageToWorker( | 601 embedded_worker_->SendMessage(ServiceWorkerMsg_CrossOriginMessageToWorker( |
602 client, message, sent_message_port_ids, new_routing_ids)); | 602 client, message, sent_message_port_ids, new_routing_ids)); |
603 RunSoon(base::Bind(callback, status)); | 603 RunSoon(base::Bind(callback, status)); |
604 } | 604 } |
605 void ServiceWorkerVersion::AddControllee( | 605 void ServiceWorkerVersion::AddControllee( |
606 ServiceWorkerProviderHost* provider_host) { | 606 ServiceWorkerProviderHost* provider_host) { |
607 DCHECK(!ContainsKey(controllee_map_, provider_host)); | 607 DCHECK(!ContainsKey(controllee_map_, provider_host)); |
608 int controllee_id = controllee_by_id_.Add(provider_host); | 608 int controllee_id = controllee_by_id_.Add(provider_host); |
609 // IDMap<>'s last index is kInvalidServiceWorkerClientId. | |
610 CHECK(controllee_id != kInvalidServiceWorkerClientId); | |
611 controllee_map_[provider_host] = controllee_id; | 609 controllee_map_[provider_host] = controllee_id; |
612 // Reset the timer if it's running (so that it's kept alive a bit longer | 610 // Reset the timer if it's running (so that it's kept alive a bit longer |
613 // right after a new controllee is added). | 611 // right after a new controllee is added). |
614 ScheduleStopWorker(); | 612 ScheduleStopWorker(); |
615 } | 613 } |
616 | 614 |
617 void ServiceWorkerVersion::RemoveControllee( | 615 void ServiceWorkerVersion::RemoveControllee( |
618 ServiceWorkerProviderHost* provider_host) { | 616 ServiceWorkerProviderHost* provider_host) { |
619 ControlleeMap::iterator found = controllee_map_.find(provider_host); | 617 ControlleeMap::iterator found = controllee_map_.find(provider_host); |
620 DCHECK(found != controllee_map_.end()); | 618 DCHECK(found != controllee_map_.end()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, | 709 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, |
712 ServiceWorkerResponse()); | 710 ServiceWorkerResponse()); |
713 RunIDMapCallbacks(&sync_callbacks_, | 711 RunIDMapCallbacks(&sync_callbacks_, |
714 SERVICE_WORKER_ERROR_FAILED); | 712 SERVICE_WORKER_ERROR_FAILED); |
715 RunIDMapCallbacks(¬ification_click_callbacks_, | 713 RunIDMapCallbacks(¬ification_click_callbacks_, |
716 SERVICE_WORKER_ERROR_FAILED); | 714 SERVICE_WORKER_ERROR_FAILED); |
717 RunIDMapCallbacks(&push_callbacks_, | 715 RunIDMapCallbacks(&push_callbacks_, |
718 SERVICE_WORKER_ERROR_FAILED); | 716 SERVICE_WORKER_ERROR_FAILED); |
719 RunIDMapCallbacks(&geofencing_callbacks_, | 717 RunIDMapCallbacks(&geofencing_callbacks_, |
720 SERVICE_WORKER_ERROR_FAILED); | 718 SERVICE_WORKER_ERROR_FAILED); |
| 719 RunIDMapCallbacks(&get_client_info_callbacks_, |
| 720 SERVICE_WORKER_ERROR_FAILED, |
| 721 ServiceWorkerClientInfo()); |
721 RunIDMapCallbacks(&cross_origin_connect_callbacks_, | 722 RunIDMapCallbacks(&cross_origin_connect_callbacks_, |
722 SERVICE_WORKER_ERROR_FAILED, | 723 SERVICE_WORKER_ERROR_FAILED, |
723 false); | 724 false); |
724 | 725 |
725 streaming_url_request_jobs_.clear(); | 726 streaming_url_request_jobs_.clear(); |
726 | 727 |
727 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this)); | 728 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this)); |
728 | 729 |
729 // There should be no more communication from/to a stopped worker. Deleting | 730 // There should be no more communication from/to a stopped worker. Deleting |
730 // the listener prevents any pending completion callbacks from causing | 731 // the listener prevents any pending completion callbacks from causing |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, | 787 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, |
787 OnPushEventFinished) | 788 OnPushEventFinished) |
788 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, | 789 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, |
789 OnGeofencingEventFinished) | 790 OnGeofencingEventFinished) |
790 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, | 791 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, |
791 OnCrossOriginConnectEventFinished) | 792 OnCrossOriginConnectEventFinished) |
792 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, | 793 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, |
793 OnPostMessageToDocument) | 794 OnPostMessageToDocument) |
794 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, | 795 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, |
795 OnFocusClient) | 796 OnFocusClient) |
| 797 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClientInfoSuccess, |
| 798 OnGetClientInfoSuccess) |
| 799 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClientInfoError, |
| 800 OnGetClientInfoError) |
796 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, | 801 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, |
797 OnSkipWaiting) | 802 OnSkipWaiting) |
798 IPC_MESSAGE_UNHANDLED(handled = false) | 803 IPC_MESSAGE_UNHANDLED(handled = false) |
799 IPC_END_MESSAGE_MAP() | 804 IPC_END_MESSAGE_MAP() |
800 return handled; | 805 return handled; |
801 } | 806 } |
802 | 807 |
803 void ServiceWorkerVersion::OnStartMessageSent( | 808 void ServiceWorkerVersion::OnStartMessageSent( |
804 ServiceWorkerStatusCode status) { | 809 ServiceWorkerStatusCode status) { |
805 if (status != SERVICE_WORKER_OK) | 810 if (status != SERVICE_WORKER_OK) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 std::vector<ServiceWorkerClientInfo>())); | 848 std::vector<ServiceWorkerClientInfo>())); |
844 } | 849 } |
845 return; | 850 return; |
846 } | 851 } |
847 scoped_refptr<GetClientDocumentsCallback> callback( | 852 scoped_refptr<GetClientDocumentsCallback> callback( |
848 new GetClientDocumentsCallback(request_id, this)); | 853 new GetClientDocumentsCallback(request_id, this)); |
849 ControlleeByIDMap::iterator it(&controllee_by_id_); | 854 ControlleeByIDMap::iterator it(&controllee_by_id_); |
850 TRACE_EVENT0("ServiceWorker", | 855 TRACE_EVENT0("ServiceWorker", |
851 "ServiceWorkerVersion::OnGetClientDocuments"); | 856 "ServiceWorkerVersion::OnGetClientDocuments"); |
852 while (!it.IsAtEnd()) { | 857 while (!it.IsAtEnd()) { |
853 // TODO(mlamouri): we could coalesce those requests into one. | 858 int client_request_id = get_client_info_callbacks_.Add( |
854 it.GetCurrentValue()->GetClientInfo( | 859 new GetClientInfoCallback(base::Bind( |
855 base::Bind(&ServiceWorkerVersion::DidGetClientInfo, | 860 &ServiceWorkerVersion::DidGetClientInfo, |
856 weak_factory_.GetWeakPtr(), it.GetCurrentKey(), callback)); | 861 weak_factory_.GetWeakPtr(), it.GetCurrentKey(), callback))); |
| 862 it.GetCurrentValue()->GetClientInfo(embedded_worker_->embedded_worker_id(), |
| 863 client_request_id); |
857 it.Advance(); | 864 it.Advance(); |
858 } | 865 } |
859 } | 866 } |
860 | 867 |
| 868 void ServiceWorkerVersion::OnGetClientInfoSuccess( |
| 869 int request_id, |
| 870 const ServiceWorkerClientInfo& info) { |
| 871 GetClientInfoCallback* callback = |
| 872 get_client_info_callbacks_.Lookup(request_id); |
| 873 if (!callback) { |
| 874 // The callback may already have been cleared by OnStopped, just ignore. |
| 875 return; |
| 876 } |
| 877 callback->Run(SERVICE_WORKER_OK, info); |
| 878 RemoveCallbackAndStopIfDoomed(&get_client_info_callbacks_, request_id); |
| 879 } |
| 880 |
| 881 void ServiceWorkerVersion::OnGetClientInfoError(int request_id) { |
| 882 GetClientInfoCallback* callback = |
| 883 get_client_info_callbacks_.Lookup(request_id); |
| 884 if (!callback) { |
| 885 // The callback may already have been cleared by OnStopped, just ignore. |
| 886 return; |
| 887 } |
| 888 callback->Run(SERVICE_WORKER_ERROR_FAILED, ServiceWorkerClientInfo()); |
| 889 RemoveCallbackAndStopIfDoomed(&get_client_info_callbacks_, request_id); |
| 890 } |
| 891 |
861 void ServiceWorkerVersion::OnActivateEventFinished( | 892 void ServiceWorkerVersion::OnActivateEventFinished( |
862 int request_id, | 893 int request_id, |
863 blink::WebServiceWorkerEventResult result) { | 894 blink::WebServiceWorkerEventResult result) { |
864 DCHECK(ACTIVATING == status() || | 895 DCHECK(ACTIVATING == status() || |
865 REDUNDANT == status()) << status(); | 896 REDUNDANT == status()) << status(); |
866 TRACE_EVENT0("ServiceWorker", | 897 TRACE_EVENT0("ServiceWorker", |
867 "ServiceWorkerVersion::OnActivateEventFinished"); | 898 "ServiceWorkerVersion::OnActivateEventFinished"); |
868 | 899 |
869 StatusCallback* callback = activate_callbacks_.Lookup(request_id); | 900 StatusCallback* callback = activate_callbacks_.Lookup(request_id); |
870 if (!callback) { | 901 if (!callback) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 } | 1101 } |
1071 | 1102 |
1072 void ServiceWorkerVersion::DidSkipWaiting(int request_id) { | 1103 void ServiceWorkerVersion::DidSkipWaiting(int request_id) { |
1073 if (running_status() == STARTING || running_status() == RUNNING) | 1104 if (running_status() == STARTING || running_status() == RUNNING) |
1074 embedded_worker_->SendMessage(ServiceWorkerMsg_DidSkipWaiting(request_id)); | 1105 embedded_worker_->SendMessage(ServiceWorkerMsg_DidSkipWaiting(request_id)); |
1075 } | 1106 } |
1076 | 1107 |
1077 void ServiceWorkerVersion::DidGetClientInfo( | 1108 void ServiceWorkerVersion::DidGetClientInfo( |
1078 int client_id, | 1109 int client_id, |
1079 scoped_refptr<GetClientDocumentsCallback> callback, | 1110 scoped_refptr<GetClientDocumentsCallback> callback, |
| 1111 ServiceWorkerStatusCode status, |
1080 const ServiceWorkerClientInfo& info) { | 1112 const ServiceWorkerClientInfo& info) { |
1081 // If the request to the provider_host returned an empty | 1113 if (status == SERVICE_WORKER_OK) |
1082 // ServiceWorkerClientInfo, that means that it wasn't possible to associate | 1114 callback->AddClientInfo(client_id, info); |
1083 // it with a valid RenderFrameHost. It might be because the frame was killed | |
1084 // or navigated in between. | |
1085 if (info.IsEmpty()) | |
1086 return; | |
1087 | |
1088 // We can get info for a frame that was navigating end ended up with a | |
1089 // different URL than expected. In such case, we should make sure to not | |
1090 // expose cross-origin WindowClient. | |
1091 if (info.url.GetOrigin() != script_url_.GetOrigin()) | |
1092 return; | |
1093 | |
1094 callback->AddClientInfo(client_id, info); | |
1095 } | 1115 } |
1096 | 1116 |
1097 void ServiceWorkerVersion::ScheduleStopWorker() { | 1117 void ServiceWorkerVersion::ScheduleStopWorker() { |
1098 if (running_status() != RUNNING) | 1118 if (running_status() != RUNNING) |
1099 return; | 1119 return; |
1100 stop_worker_timer_.Stop(); | 1120 stop_worker_timer_.Stop(); |
1101 stop_worker_timer_.Start( | 1121 stop_worker_timer_.Start( |
1102 FROM_HERE, base::TimeDelta::FromSeconds( | 1122 FROM_HERE, base::TimeDelta::FromSeconds( |
1103 is_doomed_ ? kStopDoomedWorkerDelay : kStopWorkerDelay), | 1123 is_doomed_ ? kStopDoomedWorkerDelay : kStopWorkerDelay), |
1104 base::Bind(&ServiceWorkerVersion::StopWorkerIfIdle, | 1124 base::Bind(&ServiceWorkerVersion::StopWorkerIfIdle, |
(...skipping 17 matching lines...) Expand all Loading... |
1122 | 1142 |
1123 bool ServiceWorkerVersion::HasInflightRequests() const { | 1143 bool ServiceWorkerVersion::HasInflightRequests() const { |
1124 return | 1144 return |
1125 !activate_callbacks_.IsEmpty() || | 1145 !activate_callbacks_.IsEmpty() || |
1126 !install_callbacks_.IsEmpty() || | 1146 !install_callbacks_.IsEmpty() || |
1127 !fetch_callbacks_.IsEmpty() || | 1147 !fetch_callbacks_.IsEmpty() || |
1128 !sync_callbacks_.IsEmpty() || | 1148 !sync_callbacks_.IsEmpty() || |
1129 !notification_click_callbacks_.IsEmpty() || | 1149 !notification_click_callbacks_.IsEmpty() || |
1130 !push_callbacks_.IsEmpty() || | 1150 !push_callbacks_.IsEmpty() || |
1131 !geofencing_callbacks_.IsEmpty() || | 1151 !geofencing_callbacks_.IsEmpty() || |
| 1152 !get_client_info_callbacks_.IsEmpty() || |
1132 !cross_origin_connect_callbacks_.IsEmpty() || | 1153 !cross_origin_connect_callbacks_.IsEmpty() || |
1133 !streaming_url_request_jobs_.empty(); | 1154 !streaming_url_request_jobs_.empty(); |
1134 } | 1155 } |
1135 | 1156 |
1136 void ServiceWorkerVersion::DoomInternal() { | 1157 void ServiceWorkerVersion::DoomInternal() { |
1137 DCHECK(is_doomed_); | 1158 DCHECK(is_doomed_); |
1138 DCHECK(!HasControllee()); | 1159 DCHECK(!HasControllee()); |
1139 SetStatus(REDUNDANT); | 1160 SetStatus(REDUNDANT); |
1140 StopWorkerIfIdle(); | 1161 StopWorkerIfIdle(); |
1141 if (!context_) | 1162 if (!context_) |
1142 return; | 1163 return; |
1143 std::vector<ServiceWorkerDatabase::ResourceRecord> resources; | 1164 std::vector<ServiceWorkerDatabase::ResourceRecord> resources; |
1144 script_cache_map_.GetResources(&resources); | 1165 script_cache_map_.GetResources(&resources); |
1145 context_->storage()->PurgeResources(resources); | 1166 context_->storage()->PurgeResources(resources); |
1146 } | 1167 } |
1147 | 1168 |
1148 template <typename IDMAP> | 1169 template <typename IDMAP> |
1149 void ServiceWorkerVersion::RemoveCallbackAndStopIfDoomed( | 1170 void ServiceWorkerVersion::RemoveCallbackAndStopIfDoomed( |
1150 IDMAP* callbacks, | 1171 IDMAP* callbacks, |
1151 int request_id) { | 1172 int request_id) { |
1152 callbacks->Remove(request_id); | 1173 callbacks->Remove(request_id); |
1153 if (is_doomed_) { | 1174 if (is_doomed_) { |
1154 // The stop should be already scheduled, but try to stop immediately, in | 1175 // The stop should be already scheduled, but try to stop immediately, in |
1155 // order to release worker resources soon. | 1176 // order to release worker resources soon. |
1156 StopWorkerIfIdle(); | 1177 StopWorkerIfIdle(); |
1157 } | 1178 } |
1158 } | 1179 } |
1159 | 1180 |
1160 } // namespace content | 1181 } // namespace content |
OLD | NEW |