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

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