Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(963)

Side by Side Diff: content/browser/service_worker/service_worker_version.cc

Issue 843583005: [ServiceWorker] Implement WebServiceWorkerContextClient::openWindow(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@content_browser_client_openurl
Patch Set: review comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/service_worker/service_worker_version.h ('k') | content/common/service_worker/service_worker_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698