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

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: rebase and review comments Created 5 years, 11 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 "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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 } 149 }
139 callback.Run(status); 150 callback.Run(status);
140 } 151 }
141 152
142 void RunErrorCrossOriginConnectCallback( 153 void RunErrorCrossOriginConnectCallback(
143 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, 154 const ServiceWorkerVersion::CrossOriginConnectCallback& callback,
144 ServiceWorkerStatusCode status) { 155 ServiceWorkerStatusCode status) {
145 callback.Run(status, false); 156 callback.Run(status, false);
146 } 157 }
147 158
159 using WindowOpenedCallback = base::Callback<void(int,int)>;
160
161 // The WindowOpenedObserver class is a WebContentsObserver that will wait for a
162 // new Window's WebContents to be initialized, run the |callback| passed to its
163 // constructor then self destroy.
164 // The callback will receive the process and frame ids. If something went wrong
165 // those will be (kInvalidUniqueID,MSG_ROUTING_NONE).
166 class WindowOpenedObserver : public WebContentsObserver {
167 public:
168 WindowOpenedObserver(WebContents* web_contents,
169 const WindowOpenedCallback& callback)
170 : WebContentsObserver(web_contents)
171 , callback_(callback)
172 {}
173
174 void DidCommitProvisionalLoadForFrame(
175 RenderFrameHost* render_frame_host,
176 const GURL& validated_url,
177 ui::PageTransition transition_type) override {
178 DCHECK(web_contents());
179
180 if (render_frame_host != web_contents()->GetMainFrame())
181 return;
182
183 RunCallback(render_frame_host->GetProcess()->GetID(),
184 render_frame_host->GetRoutingID());
185 }
186
187 void RenderProcessGone(base::TerminationStatus status) override {
188 RunCallback(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE);
189 }
190
191 void WebContentsDestroyed() override {
192 RunCallback(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE);
193 }
194
195 private:
196 void RunCallback(int render_process_id, int render_frame_id) {
197 // After running the callback, |this| will stop observing, thus
198 // web_contents() should return nullptr and |RunCallback| should no longer
199 // be called. Then, |this| will self destroy.
200 DCHECK(web_contents());
201
202 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
203 base::Bind(callback_,
204 render_process_id,
205 render_frame_id));
206 Observe(nullptr);
207 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
208 }
209
210 const WindowOpenedCallback callback_;
211
212 DISALLOW_COPY_AND_ASSIGN(WindowOpenedObserver);
213 };
214
215 void OpenWindowOnUI(
216 const GURL& url,
217 const GURL& script_url,
218 int process_id,
219 const scoped_refptr<ServiceWorkerContextWrapper>& context_wrapper,
220 const WindowOpenedCallback& callback) {
Michael van Ouwerkerk 2015/01/30 16:21:02 Please document that this callback will be called
mlamouri (slow - plz ping) 2015/02/04 23:23:22 Done.
221 DCHECK_CURRENTLY_ON(BrowserThread::UI);
222
223 BrowserContext* browser_context = context_wrapper->storage_partition()
224 ? context_wrapper->storage_partition()->browser_context()
225 : nullptr;
226 // We are shutting down.
227 if (!browser_context)
228 return;
229
230 RenderProcessHost* render_process_host =
231 RenderProcessHost::FromID(process_id);
232 if (render_process_host->IsIsolatedGuest()) {
233 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
234 base::Bind(callback,
235 ChildProcessHost::kInvalidUniqueID,
236 MSG_ROUTING_NONE));
237 return;
238 }
239
240 OpenURLParams params(url,
241 Referrer(script_url, blink::WebReferrerPolicyDefault),
242 NEW_FOREGROUND_TAB,
243 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
244 false);
Michael van Ouwerkerk 2015/01/30 16:21:01 nit: please comment what false is for here. It is
mlamouri (slow - plz ping) 2015/02/04 23:23:22 Right. Changed to true and added the comment.
245
246 WebContents* web_contents =
247 GetContentClient()->browser()->OpenURL(browser_context, params);
248 DCHECK(web_contents);
249
250 new WindowOpenedObserver(web_contents, callback);
251 }
252
253 void KillEmbeddedWorkerProcess(int process_id, ResultCode code) {
254 DCHECK_CURRENTLY_ON(BrowserThread::UI);
255
256 RenderProcessHost* render_process_host =
257 RenderProcessHost::FromID(process_id);
258 if (render_process_host->GetHandle() != base::kNullProcessHandle)
259 render_process_host->ReceivedBadMessage();
260 }
261
148 } // namespace 262 } // namespace
149 263
150 ServiceWorkerVersion::ServiceWorkerVersion( 264 ServiceWorkerVersion::ServiceWorkerVersion(
151 ServiceWorkerRegistration* registration, 265 ServiceWorkerRegistration* registration,
152 const GURL& script_url, 266 const GURL& script_url,
153 int64 version_id, 267 int64 version_id,
154 base::WeakPtr<ServiceWorkerContextCore> context) 268 base::WeakPtr<ServiceWorkerContextCore> context)
155 : version_id_(version_id), 269 : version_id_(version_id),
156 registration_id_(kInvalidServiceWorkerVersionId), 270 registration_id_(kInvalidServiceWorkerVersionId),
157 script_url_(script_url), 271 script_url_(script_url),
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished, 898 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished,
785 OnSyncEventFinished) 899 OnSyncEventFinished)
786 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished, 900 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished,
787 OnNotificationClickEventFinished) 901 OnNotificationClickEventFinished)
788 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, 902 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished,
789 OnPushEventFinished) 903 OnPushEventFinished)
790 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, 904 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished,
791 OnGeofencingEventFinished) 905 OnGeofencingEventFinished)
792 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, 906 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished,
793 OnCrossOriginConnectEventFinished) 907 OnCrossOriginConnectEventFinished)
908 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow,
909 OnOpenWindow)
794 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, 910 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument,
795 OnPostMessageToDocument) 911 OnPostMessageToDocument)
796 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, 912 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient,
797 OnFocusClient) 913 OnFocusClient)
798 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, 914 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting,
799 OnSkipWaiting) 915 OnSkipWaiting)
800 IPC_MESSAGE_UNHANDLED(handled = false) 916 IPC_MESSAGE_UNHANDLED(handled = false)
801 IPC_END_MESSAGE_MAP() 917 IPC_END_MESSAGE_MAP()
802 return handled; 918 return handled;
803 } 919 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 if (!callback) { 1119 if (!callback) {
1004 NOTREACHED() << "Got unexpected message: " << request_id; 1120 NOTREACHED() << "Got unexpected message: " << request_id;
1005 return; 1121 return;
1006 } 1122 }
1007 1123
1008 scoped_refptr<ServiceWorkerVersion> protect(this); 1124 scoped_refptr<ServiceWorkerVersion> protect(this);
1009 callback->Run(SERVICE_WORKER_OK, accept_connection); 1125 callback->Run(SERVICE_WORKER_OK, accept_connection);
1010 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id); 1126 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id);
1011 } 1127 }
1012 1128
1129 void ServiceWorkerVersion::OnOpenWindow(int request_id, const GURL& url) {
1130 // Just abort if we are shutting down.
1131 if (!context_)
1132 return;
1133
1134 if (url.GetOrigin() != script_url_.GetOrigin()) {
1135 // There should be a same origin check by Blink, if the request is still not
1136 // same origin, the process might be compromised and should be eliminated.
1137 DVLOG(1) << "Received a cross origin openWindow() request from a service "
1138 "worker. Killing associated process.";
1139 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1140 base::Bind(&KillEmbeddedWorkerProcess,
1141 embedded_worker_->process_id(),
1142 RESULT_CODE_KILLED_BAD_MESSAGE));
1143 return;
1144 }
1145
1146 BrowserThread::PostTask(
1147 BrowserThread::UI, FROM_HERE,
1148 base::Bind(&OpenWindowOnUI,
1149 url,
1150 script_url_,
1151 embedded_worker_->process_id(),
1152 make_scoped_refptr(context_->wrapper()),
1153 base::Bind(&ServiceWorkerVersion::DidOpenWindow,
1154 weak_factory_.GetWeakPtr(),
1155 request_id)));
1156 }
1157
1158 void ServiceWorkerVersion::DidOpenWindow(int request_id,
1159 int render_process_id,
1160 int render_frame_id) {
1161 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1162
1163 if (running_status() != RUNNING)
1164 return;
1165
1166 if (render_process_id == ChildProcessHost::kInvalidUniqueID &&
1167 render_frame_id == MSG_ROUTING_NONE) {
1168 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowError(request_id));
1169 return;
1170 }
1171
1172 for (const auto& it : controllee_map_) {
1173 const ServiceWorkerProviderHost* provider_host = it.first;
1174 if (provider_host->process_id() != render_process_id ||
1175 provider_host->frame_id() != render_frame_id) {
1176 continue;
1177 }
1178
1179 // it.second is the client_id associated with the provider_host.
1180 provider_host->GetClientInfo(
1181 base::Bind(&ServiceWorkerVersion::OnOpenWindowFinished,
1182 weak_factory_.GetWeakPtr(), request_id, it.second));
1183 return;
1184 }
1185
1186 // If here, it means that no provider_host was found, in which case, the
1187 // renderer should still be informed that the window was opened.
1188 OnOpenWindowFinished(request_id, 0, ServiceWorkerClientInfo());
1189 }
1190
1191 void ServiceWorkerVersion::OnOpenWindowFinished(
1192 int request_id,
1193 int client_id,
1194 const ServiceWorkerClientInfo& client_info) {
1195 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1196
1197 if (running_status() != RUNNING)
1198 return;
1199
1200 ServiceWorkerClientInfo client(client_info);
1201
1202 // If the |client_info| is empty, it means that the opened window wasn't
1203 // controlled but the action still succeeded. The renderer process is
1204 // expecting an empty client in such case.
1205 if (!client.IsEmpty())
1206 client.client_id = client_id;
1207
1208 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowResponse(
1209 request_id, client));
1210 }
1211
1013 void ServiceWorkerVersion::OnPostMessageToDocument( 1212 void ServiceWorkerVersion::OnPostMessageToDocument(
1014 int client_id, 1213 int client_id,
1015 const base::string16& message, 1214 const base::string16& message,
1016 const std::vector<int>& sent_message_port_ids) { 1215 const std::vector<int>& sent_message_port_ids) {
1017 TRACE_EVENT1("ServiceWorker", 1216 TRACE_EVENT1("ServiceWorker",
1018 "ServiceWorkerVersion::OnPostMessageToDocument", 1217 "ServiceWorkerVersion::OnPostMessageToDocument",
1019 "Client id", client_id); 1218 "Client id", client_id);
1020 ServiceWorkerProviderHost* provider_host = 1219 ServiceWorkerProviderHost* provider_host =
1021 controllee_by_id_.Lookup(client_id); 1220 controllee_by_id_.Lookup(client_id);
1022 if (!provider_host) { 1221 if (!provider_host) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 int request_id) { 1344 int request_id) {
1146 callbacks->Remove(request_id); 1345 callbacks->Remove(request_id);
1147 if (is_doomed_) { 1346 if (is_doomed_) {
1148 // The stop should be already scheduled, but try to stop immediately, in 1347 // The stop should be already scheduled, but try to stop immediately, in
1149 // order to release worker resources soon. 1348 // order to release worker resources soon.
1150 StopWorkerIfIdle(); 1349 StopWorkerIfIdle();
1151 } 1350 }
1152 } 1351 }
1153 1352
1154 } // namespace content 1353 } // 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