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 "content/browser/message_port_message_filter.h" | 11 #include "content/browser/message_port_message_filter.h" |
12 #include "content/browser/message_port_service.h" | 12 #include "content/browser/message_port_service.h" |
13 #include "content/browser/service_worker/embedded_worker_instance.h" | 13 #include "content/browser/service_worker/embedded_worker_instance.h" |
14 #include "content/browser/service_worker/embedded_worker_registry.h" | 14 #include "content/browser/service_worker/embedded_worker_registry.h" |
15 #include "content/browser/service_worker/service_worker_context_core.h" | 15 #include "content/browser/service_worker/service_worker_context_core.h" |
16 #include "content/browser/service_worker/service_worker_context_wrapper.h" | |
16 #include "content/browser/service_worker/service_worker_registration.h" | 17 #include "content/browser/service_worker/service_worker_registration.h" |
17 #include "content/browser/service_worker/service_worker_utils.h" | 18 #include "content/browser/service_worker/service_worker_utils.h" |
19 #include "content/browser/storage_partition_impl.h" | |
18 #include "content/common/service_worker/service_worker_messages.h" | 20 #include "content/common/service_worker/service_worker_messages.h" |
19 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
22 #include "content/public/browser/content_browser_client.h" | |
23 #include "content/public/browser/page_navigator.h" | |
24 #include "content/public/browser/render_frame_host.h" | |
25 #include "content/public/browser/render_process_host.h" | |
26 #include "content/public/browser/web_contents.h" | |
27 #include "content/public/browser/web_contents_observer.h" | |
28 #include "content/public/common/child_process_host.h" | |
29 #include "content/public/common/content_client.h" | |
20 #include "content/public/common/content_switches.h" | 30 #include "content/public/common/content_switches.h" |
31 #include "content/public/common/result_codes.h" | |
21 | 32 |
22 namespace content { | 33 namespace content { |
23 | 34 |
24 typedef ServiceWorkerVersion::StatusCallback StatusCallback; | 35 typedef ServiceWorkerVersion::StatusCallback StatusCallback; |
25 typedef ServiceWorkerVersion::MessageCallback MessageCallback; | 36 typedef ServiceWorkerVersion::MessageCallback MessageCallback; |
26 | 37 |
27 class ServiceWorkerVersion::GetClientDocumentsCallback | 38 class ServiceWorkerVersion::GetClientDocumentsCallback |
28 : public base::RefCounted<GetClientDocumentsCallback> { | 39 : public base::RefCounted<GetClientDocumentsCallback> { |
29 public: | 40 public: |
30 GetClientDocumentsCallback(int request_id, | 41 GetClientDocumentsCallback(int request_id, |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 } | 147 } |
137 callback.Run(status); | 148 callback.Run(status); |
138 } | 149 } |
139 | 150 |
140 void RunErrorCrossOriginConnectCallback( | 151 void RunErrorCrossOriginConnectCallback( |
141 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, | 152 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, |
142 ServiceWorkerStatusCode status) { | 153 ServiceWorkerStatusCode status) { |
143 callback.Run(status, false); | 154 callback.Run(status, false); |
144 } | 155 } |
145 | 156 |
157 using WindowOpenedCallback = base::Callback<void(int,int)>; | |
158 | |
159 // The WindowOpenedObserver class is a WebContentsObserver that will wait for a | |
160 // new Window's WebContents to be initialized, run the |callback| passed to its | |
161 // constructor then self destroy. | |
162 // The callback will receive the process and frame ids. If something went wrong | |
163 // those will be (kInvalidUniqueID,MSG_ROUTING_NONE). | |
164 class WindowOpenedObserver : public WebContentsObserver { | |
165 public: | |
166 WindowOpenedObserver(WebContents* web_contents, | |
167 const WindowOpenedCallback& callback) | |
168 : WebContentsObserver(web_contents) | |
169 , callback_(callback) | |
170 {} | |
171 | |
172 void DocumentAvailableInMainFrame() override { | |
jochen (gone - plz use gerrit)
2015/01/27 09:54:45
i guess you'll want the first signal after didCrea
mlamouri (slow - plz ping)
2015/01/27 15:42:08
My mistake, the controllee is added via a url requ
| |
173 DCHECK(web_contents()); | |
174 | |
175 RenderFrameHost* render_frame_host = web_contents()->GetMainFrame(); | |
176 DCHECK(render_frame_host); | |
177 | |
178 RunCallback(render_frame_host->GetProcess()->GetID(), | |
179 render_frame_host->GetRoutingID()); | |
180 } | |
181 | |
182 void RenderProcessGone(base::TerminationStatus status) override { | |
183 RunCallback(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE); | |
184 } | |
185 | |
186 void WebContentsDestroyed() override { | |
187 RunCallback(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE); | |
188 } | |
189 | |
190 private: | |
191 void RunCallback(int render_process_id, int render_frame_id) { | |
192 // After running the callback, |this| will stop observing, thus | |
193 // web_contents() should return nullptr and |RunCallback| should no longer | |
194 // be called. Then, |this| will self destroy. | |
195 DCHECK(web_contents()); | |
196 | |
197 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
198 base::Bind(callback_, | |
199 render_process_id, | |
200 render_frame_id)); | |
201 Observe(nullptr); | |
202 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
203 } | |
204 | |
205 const WindowOpenedCallback callback_; | |
206 | |
207 DISALLOW_COPY_AND_ASSIGN(WindowOpenedObserver); | |
208 }; | |
209 | |
210 void OpenWindowOnUI( | |
211 const GURL& url, | |
212 const GURL& script_url, | |
213 int process_id, | |
214 const scoped_refptr<ServiceWorkerContextWrapper>& context_wrapper, | |
215 const WindowOpenedCallback& callback) { | |
216 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
217 | |
218 BrowserContext* browser_context = context_wrapper->storage_partition() | |
219 ? context_wrapper->storage_partition()->browser_context() | |
220 : nullptr; | |
221 // We are shutting down. | |
222 if (!browser_context) | |
223 return; | |
224 | |
225 RenderProcessHost* render_process_host = | |
226 RenderProcessHost::FromID(process_id); | |
227 if (render_process_host->IsIsolatedGuest()) { | |
228 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
229 base::Bind(callback, | |
230 ChildProcessHost::kInvalidUniqueID, | |
231 MSG_ROUTING_NONE)); | |
232 return; | |
233 } | |
234 | |
235 OpenURLParams params(url, | |
236 Referrer(script_url, blink::WebReferrerPolicyDefault), | |
237 NEW_FOREGROUND_TAB, | |
238 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, | |
239 false); | |
240 | |
241 WebContents* web_contents = | |
242 GetContentClient()->browser()->OpenURL(browser_context, params); | |
243 DCHECK(web_contents); | |
jochen (gone - plz use gerrit)
2015/01/27 09:54:45
why not if (web_contents) new Window....
mlamouri (slow - plz ping)
2015/01/27 15:42:08
Because |web_contents| should not be nullptr here.
| |
244 | |
245 new WindowOpenedObserver(web_contents, callback); | |
246 } | |
247 | |
248 void KillEmbeddedWorkerProcess(int process_id, ResultCode code) { | |
249 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
250 | |
251 RenderProcessHost* render_process_host = | |
252 RenderProcessHost::FromID(process_id); | |
253 if (render_process_host->GetHandle() != base::kNullProcessHandle) | |
254 render_process_host->ReceivedBadMessage(); | |
255 } | |
256 | |
146 } // namespace | 257 } // namespace |
147 | 258 |
148 ServiceWorkerVersion::ServiceWorkerVersion( | 259 ServiceWorkerVersion::ServiceWorkerVersion( |
149 ServiceWorkerRegistration* registration, | 260 ServiceWorkerRegistration* registration, |
150 const GURL& script_url, | 261 const GURL& script_url, |
151 int64 version_id, | 262 int64 version_id, |
152 base::WeakPtr<ServiceWorkerContextCore> context) | 263 base::WeakPtr<ServiceWorkerContextCore> context) |
153 : version_id_(version_id), | 264 : version_id_(version_id), |
154 registration_id_(kInvalidServiceWorkerVersionId), | 265 registration_id_(kInvalidServiceWorkerVersionId), |
155 script_url_(script_url), | 266 script_url_(script_url), |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
780 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished, | 891 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished, |
781 OnSyncEventFinished) | 892 OnSyncEventFinished) |
782 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished, | 893 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished, |
783 OnNotificationClickEventFinished) | 894 OnNotificationClickEventFinished) |
784 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, | 895 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, |
785 OnPushEventFinished) | 896 OnPushEventFinished) |
786 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, | 897 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, |
787 OnGeofencingEventFinished) | 898 OnGeofencingEventFinished) |
788 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, | 899 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, |
789 OnCrossOriginConnectEventFinished) | 900 OnCrossOriginConnectEventFinished) |
901 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, | |
902 OnOpenWindow) | |
790 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, | 903 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, |
791 OnPostMessageToDocument) | 904 OnPostMessageToDocument) |
792 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, | 905 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, |
793 OnFocusClient) | 906 OnFocusClient) |
794 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, | 907 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, |
795 OnSkipWaiting) | 908 OnSkipWaiting) |
796 IPC_MESSAGE_UNHANDLED(handled = false) | 909 IPC_MESSAGE_UNHANDLED(handled = false) |
797 IPC_END_MESSAGE_MAP() | 910 IPC_END_MESSAGE_MAP() |
798 return handled; | 911 return handled; |
799 } | 912 } |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 if (!callback) { | 1112 if (!callback) { |
1000 NOTREACHED() << "Got unexpected message: " << request_id; | 1113 NOTREACHED() << "Got unexpected message: " << request_id; |
1001 return; | 1114 return; |
1002 } | 1115 } |
1003 | 1116 |
1004 scoped_refptr<ServiceWorkerVersion> protect(this); | 1117 scoped_refptr<ServiceWorkerVersion> protect(this); |
1005 callback->Run(SERVICE_WORKER_OK, accept_connection); | 1118 callback->Run(SERVICE_WORKER_OK, accept_connection); |
1006 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id); | 1119 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id); |
1007 } | 1120 } |
1008 | 1121 |
1122 void ServiceWorkerVersion::OnOpenWindow(int request_id, const GURL& url) { | |
1123 // Just abort if we are shutting down. | |
1124 if (!context_) | |
1125 return; | |
1126 | |
1127 if (url.GetOrigin() != script_url_.GetOrigin()) { | |
1128 // There should be a same origin check by Blink, if the request is still not | |
1129 // same origin, the process might be compromised and should be eliminated. | |
1130 DVLOG(1) << "Received a cross origin openWindow() request from a service " | |
1131 "worker. Killing associated process."; | |
1132 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
1133 base::Bind(&KillEmbeddedWorkerProcess, | |
1134 embedded_worker_->process_id(), | |
1135 RESULT_CODE_KILLED_BAD_MESSAGE)); | |
1136 return; | |
1137 } | |
1138 | |
1139 BrowserThread::PostTask( | |
1140 BrowserThread::UI, FROM_HERE, | |
1141 base::Bind(&OpenWindowOnUI, | |
1142 url, | |
1143 script_url_, | |
1144 embedded_worker_->process_id(), | |
1145 make_scoped_refptr(context_->wrapper()), | |
1146 base::Bind(&ServiceWorkerVersion::DidOpenWindow, | |
1147 weak_factory_.GetWeakPtr(), | |
1148 request_id))); | |
1149 } | |
1150 | |
1151 void ServiceWorkerVersion::DidOpenWindow(int request_id, | |
1152 int render_process_id, | |
1153 int render_frame_id) { | |
1154 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
1155 | |
1156 if (running_status() != RUNNING) | |
1157 return; | |
1158 | |
1159 if (render_process_id == ChildProcessHost::kInvalidUniqueID && | |
1160 render_frame_id == MSG_ROUTING_NONE) { | |
1161 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowError(request_id)); | |
1162 return; | |
1163 } | |
1164 | |
1165 for (const auto& it : controllee_map_) { | |
1166 const ServiceWorkerProviderHost* provider_host = it.first; | |
1167 if (provider_host->process_id() != render_process_id || | |
1168 provider_host->frame_id() != render_frame_id) { | |
1169 continue; | |
1170 } | |
1171 | |
1172 // it.second is the client_id associated with the provider_host. | |
1173 provider_host->GetClientInfo( | |
1174 base::Bind(&ServiceWorkerVersion::OnOpenWindowFinished, | |
1175 weak_factory_.GetWeakPtr(), request_id, it.second)); | |
1176 return; | |
1177 } | |
1178 | |
1179 // If here, it means that no provider_host was found, in which case, the | |
1180 // renderer should still be informed that the window was opened. | |
1181 OnOpenWindowFinished(request_id, 0, ServiceWorkerClientInfo()); | |
1182 } | |
1183 | |
1184 void ServiceWorkerVersion::OnOpenWindowFinished( | |
1185 int request_id, | |
1186 int client_id, | |
1187 const ServiceWorkerClientInfo& client_info) { | |
1188 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
1189 | |
1190 if (running_status() != RUNNING) | |
1191 return; | |
1192 | |
1193 ServiceWorkerClientInfo client(client_info); | |
1194 | |
1195 // If the |client_info| is empty, it means that the opened window wasn't | |
1196 // controlled but the action still succeeded. The renderer process is | |
1197 // expecting an empty client in such case. | |
1198 if (!client.IsEmpty()) | |
1199 client.SetClientID(client_id); | |
1200 | |
1201 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowResponse( | |
1202 request_id, client)); | |
1203 } | |
1204 | |
1009 void ServiceWorkerVersion::OnPostMessageToDocument( | 1205 void ServiceWorkerVersion::OnPostMessageToDocument( |
1010 int client_id, | 1206 int client_id, |
1011 const base::string16& message, | 1207 const base::string16& message, |
1012 const std::vector<int>& sent_message_port_ids) { | 1208 const std::vector<int>& sent_message_port_ids) { |
1013 TRACE_EVENT1("ServiceWorker", | 1209 TRACE_EVENT1("ServiceWorker", |
1014 "ServiceWorkerVersion::OnPostMessageToDocument", | 1210 "ServiceWorkerVersion::OnPostMessageToDocument", |
1015 "Client id", client_id); | 1211 "Client id", client_id); |
1016 ServiceWorkerProviderHost* provider_host = | 1212 ServiceWorkerProviderHost* provider_host = |
1017 controllee_by_id_.Lookup(client_id); | 1213 controllee_by_id_.Lookup(client_id); |
1018 if (!provider_host) { | 1214 if (!provider_host) { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1136 int request_id) { | 1332 int request_id) { |
1137 callbacks->Remove(request_id); | 1333 callbacks->Remove(request_id); |
1138 if (is_doomed_) { | 1334 if (is_doomed_) { |
1139 // The stop should be already scheduled, but try to stop immediately, in | 1335 // The stop should be already scheduled, but try to stop immediately, in |
1140 // order to release worker resources soon. | 1336 // order to release worker resources soon. |
1141 StopWorkerIfIdle(); | 1337 StopWorkerIfIdle(); |
1142 } | 1338 } |
1143 } | 1339 } |
1144 | 1340 |
1145 } // namespace content | 1341 } // namespace content |
OLD | NEW |