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

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: jochen 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 "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)>;
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
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
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
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
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