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" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "content/browser/message_port_message_filter.h" | 12 #include "content/browser/message_port_message_filter.h" |
13 #include "content/browser/message_port_service.h" | 13 #include "content/browser/message_port_service.h" |
14 #include "content/browser/service_worker/embedded_worker_instance.h" | 14 #include "content/browser/service_worker/embedded_worker_instance.h" |
15 #include "content/browser/service_worker/embedded_worker_registry.h" | 15 #include "content/browser/service_worker/embedded_worker_registry.h" |
16 #include "content/browser/service_worker/service_worker_context_core.h" | 16 #include "content/browser/service_worker/service_worker_context_core.h" |
| 17 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
17 #include "content/browser/service_worker/service_worker_registration.h" | 18 #include "content/browser/service_worker/service_worker_registration.h" |
18 #include "content/browser/service_worker/service_worker_utils.h" | 19 #include "content/browser/service_worker/service_worker_utils.h" |
| 20 #include "content/browser/storage_partition_impl.h" |
19 #include "content/common/service_worker/service_worker_messages.h" | 21 #include "content/common/service_worker/service_worker_messages.h" |
20 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 23 #include "content/public/browser/content_browser_client.h" |
| 24 #include "content/public/browser/page_navigator.h" |
| 25 #include "content/public/browser/render_frame_host.h" |
| 26 #include "content/public/browser/render_process_host.h" |
| 27 #include "content/public/browser/web_contents.h" |
| 28 #include "content/public/browser/web_contents_observer.h" |
| 29 #include "content/public/common/child_process_host.h" |
| 30 #include "content/public/common/content_client.h" |
21 #include "content/public/common/content_switches.h" | 31 #include "content/public/common/content_switches.h" |
| 32 #include "content/public/common/result_codes.h" |
22 #include "net/http/http_response_info.h" | 33 #include "net/http/http_response_info.h" |
23 | 34 |
24 namespace content { | 35 namespace content { |
25 | 36 |
26 typedef ServiceWorkerVersion::StatusCallback StatusCallback; | 37 typedef ServiceWorkerVersion::StatusCallback StatusCallback; |
27 typedef ServiceWorkerVersion::MessageCallback MessageCallback; | 38 typedef ServiceWorkerVersion::MessageCallback MessageCallback; |
28 | 39 |
29 class ServiceWorkerVersion::GetClientDocumentsCallback | 40 class ServiceWorkerVersion::GetClientDocumentsCallback |
30 : public base::RefCounted<GetClientDocumentsCallback> { | 41 : public base::RefCounted<GetClientDocumentsCallback> { |
31 public: | 42 public: |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 } | 155 } |
145 callback.Run(status); | 156 callback.Run(status); |
146 } | 157 } |
147 | 158 |
148 void RunErrorCrossOriginConnectCallback( | 159 void RunErrorCrossOriginConnectCallback( |
149 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, | 160 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, |
150 ServiceWorkerStatusCode status) { | 161 ServiceWorkerStatusCode status) { |
151 callback.Run(status, false); | 162 callback.Run(status, false); |
152 } | 163 } |
153 | 164 |
| 165 using WindowOpenedCallback = base::Callback<void(int, int)>; |
| 166 |
| 167 // The WindowOpenedObserver class is a WebContentsObserver that will wait for a |
| 168 // new Window's WebContents to be initialized, run the |callback| passed to its |
| 169 // constructor then self destroy. |
| 170 // The callback will receive the process and frame ids. If something went wrong |
| 171 // those will be (kInvalidUniqueID, MSG_ROUTING_NONE). |
| 172 // The callback will be called in the IO thread. |
| 173 class WindowOpenedObserver : public WebContentsObserver { |
| 174 public: |
| 175 WindowOpenedObserver(WebContents* web_contents, |
| 176 const WindowOpenedCallback& callback) |
| 177 : WebContentsObserver(web_contents), |
| 178 callback_(callback) |
| 179 {} |
| 180 |
| 181 void DidCommitProvisionalLoadForFrame( |
| 182 RenderFrameHost* render_frame_host, |
| 183 const GURL& validated_url, |
| 184 ui::PageTransition transition_type) override { |
| 185 DCHECK(web_contents()); |
| 186 |
| 187 if (render_frame_host != web_contents()->GetMainFrame()) |
| 188 return; |
| 189 |
| 190 RunCallback(render_frame_host->GetProcess()->GetID(), |
| 191 render_frame_host->GetRoutingID()); |
| 192 } |
| 193 |
| 194 void RenderProcessGone(base::TerminationStatus status) override { |
| 195 RunCallback(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE); |
| 196 } |
| 197 |
| 198 void WebContentsDestroyed() override { |
| 199 RunCallback(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE); |
| 200 } |
| 201 |
| 202 private: |
| 203 void RunCallback(int render_process_id, int render_frame_id) { |
| 204 // After running the callback, |this| will stop observing, thus |
| 205 // web_contents() should return nullptr and |RunCallback| should no longer |
| 206 // be called. Then, |this| will self destroy. |
| 207 DCHECK(web_contents()); |
| 208 |
| 209 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 210 base::Bind(callback_, |
| 211 render_process_id, |
| 212 render_frame_id)); |
| 213 Observe(nullptr); |
| 214 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 215 } |
| 216 |
| 217 const WindowOpenedCallback callback_; |
| 218 |
| 219 DISALLOW_COPY_AND_ASSIGN(WindowOpenedObserver); |
| 220 }; |
| 221 |
| 222 void OpenWindowOnUI( |
| 223 const GURL& url, |
| 224 const GURL& script_url, |
| 225 int process_id, |
| 226 const scoped_refptr<ServiceWorkerContextWrapper>& context_wrapper, |
| 227 const WindowOpenedCallback& callback) { |
| 228 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 229 |
| 230 BrowserContext* browser_context = context_wrapper->storage_partition() |
| 231 ? context_wrapper->storage_partition()->browser_context() |
| 232 : nullptr; |
| 233 // We are shutting down. |
| 234 if (!browser_context) |
| 235 return; |
| 236 |
| 237 RenderProcessHost* render_process_host = |
| 238 RenderProcessHost::FromID(process_id); |
| 239 if (render_process_host->IsIsolatedGuest()) { |
| 240 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 241 base::Bind(callback, |
| 242 ChildProcessHost::kInvalidUniqueID, |
| 243 MSG_ROUTING_NONE)); |
| 244 return; |
| 245 } |
| 246 |
| 247 OpenURLParams params(url, |
| 248 Referrer(script_url, blink::WebReferrerPolicyDefault), |
| 249 NEW_FOREGROUND_TAB, |
| 250 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 251 true /* is_renderer_initiated */); |
| 252 |
| 253 WebContents* web_contents = |
| 254 GetContentClient()->browser()->OpenURL(browser_context, params); |
| 255 DCHECK(web_contents); |
| 256 |
| 257 new WindowOpenedObserver(web_contents, callback); |
| 258 } |
| 259 |
| 260 void KillEmbeddedWorkerProcess(int process_id, ResultCode code) { |
| 261 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 262 |
| 263 RenderProcessHost* render_process_host = |
| 264 RenderProcessHost::FromID(process_id); |
| 265 if (render_process_host->GetHandle() != base::kNullProcessHandle) |
| 266 render_process_host->ReceivedBadMessage(); |
| 267 } |
| 268 |
154 } // namespace | 269 } // namespace |
155 | 270 |
156 ServiceWorkerVersion::ServiceWorkerVersion( | 271 ServiceWorkerVersion::ServiceWorkerVersion( |
157 ServiceWorkerRegistration* registration, | 272 ServiceWorkerRegistration* registration, |
158 const GURL& script_url, | 273 const GURL& script_url, |
159 int64 version_id, | 274 int64 version_id, |
160 base::WeakPtr<ServiceWorkerContextCore> context) | 275 base::WeakPtr<ServiceWorkerContextCore> context) |
161 : version_id_(version_id), | 276 : version_id_(version_id), |
162 registration_id_(kInvalidServiceWorkerVersionId), | 277 registration_id_(kInvalidServiceWorkerVersionId), |
163 script_url_(script_url), | 278 script_url_(script_url), |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished, | 915 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished, |
801 OnSyncEventFinished) | 916 OnSyncEventFinished) |
802 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished, | 917 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished, |
803 OnNotificationClickEventFinished) | 918 OnNotificationClickEventFinished) |
804 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, | 919 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, |
805 OnPushEventFinished) | 920 OnPushEventFinished) |
806 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, | 921 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, |
807 OnGeofencingEventFinished) | 922 OnGeofencingEventFinished) |
808 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, | 923 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, |
809 OnCrossOriginConnectEventFinished) | 924 OnCrossOriginConnectEventFinished) |
| 925 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, |
| 926 OnOpenWindow) |
810 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, | 927 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, |
811 OnPostMessageToDocument) | 928 OnPostMessageToDocument) |
812 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, | 929 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, |
813 OnFocusClient) | 930 OnFocusClient) |
814 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, | 931 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, |
815 OnSkipWaiting) | 932 OnSkipWaiting) |
816 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, | 933 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, |
817 OnClaimClients) | 934 OnClaimClients) |
818 IPC_MESSAGE_UNHANDLED(handled = false) | 935 IPC_MESSAGE_UNHANDLED(handled = false) |
819 IPC_END_MESSAGE_MAP() | 936 IPC_END_MESSAGE_MAP() |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 if (!callback) { | 1139 if (!callback) { |
1023 NOTREACHED() << "Got unexpected message: " << request_id; | 1140 NOTREACHED() << "Got unexpected message: " << request_id; |
1024 return; | 1141 return; |
1025 } | 1142 } |
1026 | 1143 |
1027 scoped_refptr<ServiceWorkerVersion> protect(this); | 1144 scoped_refptr<ServiceWorkerVersion> protect(this); |
1028 callback->Run(SERVICE_WORKER_OK, accept_connection); | 1145 callback->Run(SERVICE_WORKER_OK, accept_connection); |
1029 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id); | 1146 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id); |
1030 } | 1147 } |
1031 | 1148 |
| 1149 void ServiceWorkerVersion::OnOpenWindow(int request_id, const GURL& url) { |
| 1150 // Just abort if we are shutting down. |
| 1151 if (!context_) |
| 1152 return; |
| 1153 |
| 1154 if (url.GetOrigin() != script_url_.GetOrigin()) { |
| 1155 // There should be a same origin check by Blink, if the request is still not |
| 1156 // same origin, the process might be compromised and should be eliminated. |
| 1157 DVLOG(1) << "Received a cross origin openWindow() request from a service " |
| 1158 "worker. Killing associated process."; |
| 1159 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 1160 base::Bind(&KillEmbeddedWorkerProcess, |
| 1161 embedded_worker_->process_id(), |
| 1162 RESULT_CODE_KILLED_BAD_MESSAGE)); |
| 1163 return; |
| 1164 } |
| 1165 |
| 1166 BrowserThread::PostTask( |
| 1167 BrowserThread::UI, FROM_HERE, |
| 1168 base::Bind(&OpenWindowOnUI, |
| 1169 url, |
| 1170 script_url_, |
| 1171 embedded_worker_->process_id(), |
| 1172 make_scoped_refptr(context_->wrapper()), |
| 1173 base::Bind(&ServiceWorkerVersion::DidOpenWindow, |
| 1174 weak_factory_.GetWeakPtr(), |
| 1175 request_id))); |
| 1176 } |
| 1177 |
| 1178 void ServiceWorkerVersion::DidOpenWindow(int request_id, |
| 1179 int render_process_id, |
| 1180 int render_frame_id) { |
| 1181 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1182 |
| 1183 if (running_status() != RUNNING) |
| 1184 return; |
| 1185 |
| 1186 if (render_process_id == ChildProcessHost::kInvalidUniqueID && |
| 1187 render_frame_id == MSG_ROUTING_NONE) { |
| 1188 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowError(request_id)); |
| 1189 return; |
| 1190 } |
| 1191 |
| 1192 for (const auto& it : controllee_map_) { |
| 1193 const ServiceWorkerProviderHost* provider_host = it.first; |
| 1194 if (provider_host->process_id() != render_process_id || |
| 1195 provider_host->frame_id() != render_frame_id) { |
| 1196 continue; |
| 1197 } |
| 1198 |
| 1199 // it.second is the client_id associated with the provider_host. |
| 1200 provider_host->GetClientInfo( |
| 1201 base::Bind(&ServiceWorkerVersion::OnOpenWindowFinished, |
| 1202 weak_factory_.GetWeakPtr(), request_id, it.second)); |
| 1203 return; |
| 1204 } |
| 1205 |
| 1206 // If here, it means that no provider_host was found, in which case, the |
| 1207 // renderer should still be informed that the window was opened. |
| 1208 OnOpenWindowFinished(request_id, 0, ServiceWorkerClientInfo()); |
| 1209 } |
| 1210 |
| 1211 void ServiceWorkerVersion::OnOpenWindowFinished( |
| 1212 int request_id, |
| 1213 int client_id, |
| 1214 const ServiceWorkerClientInfo& client_info) { |
| 1215 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1216 |
| 1217 if (running_status() != RUNNING) |
| 1218 return; |
| 1219 |
| 1220 ServiceWorkerClientInfo client(client_info); |
| 1221 |
| 1222 // If the |client_info| is empty, it means that the opened window wasn't |
| 1223 // controlled but the action still succeeded. The renderer process is |
| 1224 // expecting an empty client in such case. |
| 1225 if (!client.IsEmpty()) |
| 1226 client.client_id = client_id; |
| 1227 |
| 1228 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowResponse( |
| 1229 request_id, client)); |
| 1230 } |
| 1231 |
1032 void ServiceWorkerVersion::OnPostMessageToDocument( | 1232 void ServiceWorkerVersion::OnPostMessageToDocument( |
1033 int client_id, | 1233 int client_id, |
1034 const base::string16& message, | 1234 const base::string16& message, |
1035 const std::vector<int>& sent_message_port_ids) { | 1235 const std::vector<int>& sent_message_port_ids) { |
1036 TRACE_EVENT1("ServiceWorker", | 1236 TRACE_EVENT1("ServiceWorker", |
1037 "ServiceWorkerVersion::OnPostMessageToDocument", | 1237 "ServiceWorkerVersion::OnPostMessageToDocument", |
1038 "Client id", client_id); | 1238 "Client id", client_id); |
1039 ServiceWorkerProviderHost* provider_host = | 1239 ServiceWorkerProviderHost* provider_host = |
1040 controllee_by_id_.Lookup(client_id); | 1240 controllee_by_id_.Lookup(client_id); |
1041 if (!provider_host) { | 1241 if (!provider_host) { |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 int request_id) { | 1410 int request_id) { |
1211 callbacks->Remove(request_id); | 1411 callbacks->Remove(request_id); |
1212 if (is_doomed_) { | 1412 if (is_doomed_) { |
1213 // The stop should be already scheduled, but try to stop immediately, in | 1413 // The stop should be already scheduled, but try to stop immediately, in |
1214 // order to release worker resources soon. | 1414 // order to release worker resources soon. |
1215 StopWorkerIfIdle(); | 1415 StopWorkerIfIdle(); |
1216 } | 1416 } |
1217 } | 1417 } |
1218 | 1418 |
1219 } // namespace content | 1419 } // namespace content |
OLD | NEW |