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

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: merge with ContentBrowserClient::openWindow 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/26 15:43:53 any reason you're waiting until the document is pa
mlamouri (slow - plz ping) 2015/01/26 16:01:41 The document needs to be controlled which will hap
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 };
jochen (gone - plz use gerrit) 2015/01/26 15:43:53 disallow copy/assign
jochen (gone - plz use gerrit) 2015/01/26 15:43:53 disallow copy/assign
mlamouri (slow - plz ping) 2015/01/26 16:01:41 Done.
207
208 void OpenWindowOnUI(
209 const GURL& url,
210 const GURL& script_url,
211 const scoped_refptr<ServiceWorkerContextWrapper>& context_wrapper,
212 const WindowOpenedCallback& callback) {
213 DCHECK_CURRENTLY_ON(BrowserThread::UI);
214
215 BrowserContext* browser_context = context_wrapper->storage_partition()
216 ? context_wrapper->storage_partition()->browser_context()
217 : nullptr;
jochen (gone - plz use gerrit) 2015/01/26 15:43:53 can you also bail out if the process is an isolate
mlamouri (slow - plz ping) 2015/01/26 16:01:41 Done. Though, the issue isn't really storage parti
218 // We are shutting down.
219 if (!browser_context)
220 return;
221
222 OpenURLParams params(url,
223 Referrer(script_url, blink::WebReferrerPolicyDefault),
224 NEW_FOREGROUND_TAB,
225 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
226 false);
227
228 WebContents* web_contents =
229 GetContentClient()->browser()->OpenURL(browser_context, params);
230 DCHECK(web_contents);
231
232 new WindowOpenedObserver(web_contents, callback);
233 }
234
235 void KillEmbeddedWorkerProcess(int process_id, ResultCode code) {
236 DCHECK_CURRENTLY_ON(BrowserThread::UI);
237
238 RenderProcessHost* render_process_host =
239 RenderProcessHost::FromID(process_id);
240 if (render_process_host->GetHandle() != base::kNullProcessHandle)
jochen (gone - plz use gerrit) 2015/01/26 15:43:53 should be render_process_host->ReceivedBadMessage(
mlamouri (slow - plz ping) 2015/01/26 16:01:41 Done.
241 render_process_host->Shutdown(code, false);
242 }
243
146 } // namespace 244 } // namespace
147 245
148 ServiceWorkerVersion::ServiceWorkerVersion( 246 ServiceWorkerVersion::ServiceWorkerVersion(
149 ServiceWorkerRegistration* registration, 247 ServiceWorkerRegistration* registration,
150 const GURL& script_url, 248 const GURL& script_url,
151 int64 version_id, 249 int64 version_id,
152 base::WeakPtr<ServiceWorkerContextCore> context) 250 base::WeakPtr<ServiceWorkerContextCore> context)
153 : version_id_(version_id), 251 : version_id_(version_id),
154 registration_id_(kInvalidServiceWorkerVersionId), 252 registration_id_(kInvalidServiceWorkerVersionId),
155 script_url_(script_url), 253 script_url_(script_url),
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished, 878 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SyncEventFinished,
781 OnSyncEventFinished) 879 OnSyncEventFinished)
782 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished, 880 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished,
783 OnNotificationClickEventFinished) 881 OnNotificationClickEventFinished)
784 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished, 882 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished,
785 OnPushEventFinished) 883 OnPushEventFinished)
786 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished, 884 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished,
787 OnGeofencingEventFinished) 885 OnGeofencingEventFinished)
788 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished, 886 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CrossOriginConnectEventFinished,
789 OnCrossOriginConnectEventFinished) 887 OnCrossOriginConnectEventFinished)
888 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow,
889 OnOpenWindow)
790 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument, 890 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument,
791 OnPostMessageToDocument) 891 OnPostMessageToDocument)
792 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, 892 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient,
793 OnFocusClient) 893 OnFocusClient)
794 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, 894 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting,
795 OnSkipWaiting) 895 OnSkipWaiting)
796 IPC_MESSAGE_UNHANDLED(handled = false) 896 IPC_MESSAGE_UNHANDLED(handled = false)
797 IPC_END_MESSAGE_MAP() 897 IPC_END_MESSAGE_MAP()
798 return handled; 898 return handled;
799 } 899 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 if (!callback) { 1099 if (!callback) {
1000 NOTREACHED() << "Got unexpected message: " << request_id; 1100 NOTREACHED() << "Got unexpected message: " << request_id;
1001 return; 1101 return;
1002 } 1102 }
1003 1103
1004 scoped_refptr<ServiceWorkerVersion> protect(this); 1104 scoped_refptr<ServiceWorkerVersion> protect(this);
1005 callback->Run(SERVICE_WORKER_OK, accept_connection); 1105 callback->Run(SERVICE_WORKER_OK, accept_connection);
1006 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id); 1106 RemoveCallbackAndStopIfDoomed(&cross_origin_connect_callbacks_, request_id);
1007 } 1107 }
1008 1108
1109 void ServiceWorkerVersion::OnOpenWindow(int request_id, const GURL& url) {
1110 // Just abort if we are shutting down.
1111 if (!context_)
1112 return;
1113
1114 if (url.GetOrigin() != script_url_.GetOrigin()) {
1115 // There should be a same origin check by Blink, if the request is still not
1116 // same origin, the process might be compromised and should be eliminated.
1117 DVLOG(1) << "Received a cross origin openWindow() request from a service "
1118 "worker. Killing associated process.";
1119 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1120 base::Bind(&KillEmbeddedWorkerProcess,
1121 embedded_worker_->process_id(),
1122 RESULT_CODE_KILLED_BAD_MESSAGE));
1123 return;
1124 }
1125
1126 BrowserThread::PostTask(
1127 BrowserThread::UI, FROM_HERE,
1128 base::Bind(&OpenWindowOnUI,
1129 url,
1130 script_url_,
1131 make_scoped_refptr(context_->wrapper()),
1132 base::Bind(&ServiceWorkerVersion::DidOpenWindow,
1133 weak_factory_.GetWeakPtr(),
1134 request_id)));
1135 }
1136
1137 void ServiceWorkerVersion::DidOpenWindow(int request_id,
1138 int render_process_id,
1139 int render_frame_id) {
1140 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1141
1142 if (running_status() != RUNNING)
1143 return;
1144
1145 if (render_process_id == ChildProcessHost::kInvalidUniqueID &&
1146 render_frame_id == MSG_ROUTING_NONE) {
1147 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowError(request_id));
1148 return;
1149 }
1150
1151 for (const auto& it : controllee_map_) {
1152 const ServiceWorkerProviderHost* provider_host = it.first;
1153 if (provider_host->process_id() != render_process_id ||
1154 provider_host->frame_id() != render_frame_id) {
1155 continue;
1156 }
1157
1158 // it.second is the client_id associated with the provider_host.
1159 provider_host->GetClientInfo(
1160 base::Bind(&ServiceWorkerVersion::OnOpenWindowFinished,
1161 weak_factory_.GetWeakPtr(), request_id, it.second));
1162 return;
1163 }
1164
1165 // If here, it means that no provider_host was found, in which case, the
1166 // renderer should still be informed that the window was opened.
1167 OnOpenWindowFinished(request_id, 0, ServiceWorkerClientInfo());
1168 }
1169
1170 void ServiceWorkerVersion::OnOpenWindowFinished(
1171 int request_id,
1172 int client_id,
1173 const ServiceWorkerClientInfo& client_info) {
1174 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1175
1176 if (running_status() != RUNNING)
1177 return;
1178
1179 ServiceWorkerClientInfo client(client_info);
1180
1181 // If the |client_info| is empty, it means that the opened window wasn't
1182 // controlled but the action still succeeded. The renderer process is
1183 // expecting an empty client in such case.
1184 if (!client.IsEmpty())
1185 client.SetClientID(client_id);
1186
1187 embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowResponse(
1188 request_id, client));
1189 }
1190
1009 void ServiceWorkerVersion::OnPostMessageToDocument( 1191 void ServiceWorkerVersion::OnPostMessageToDocument(
1010 int client_id, 1192 int client_id,
1011 const base::string16& message, 1193 const base::string16& message,
1012 const std::vector<int>& sent_message_port_ids) { 1194 const std::vector<int>& sent_message_port_ids) {
1013 TRACE_EVENT1("ServiceWorker", 1195 TRACE_EVENT1("ServiceWorker",
1014 "ServiceWorkerVersion::OnPostMessageToDocument", 1196 "ServiceWorkerVersion::OnPostMessageToDocument",
1015 "Client id", client_id); 1197 "Client id", client_id);
1016 ServiceWorkerProviderHost* provider_host = 1198 ServiceWorkerProviderHost* provider_host =
1017 controllee_by_id_.Lookup(client_id); 1199 controllee_by_id_.Lookup(client_id);
1018 if (!provider_host) { 1200 if (!provider_host) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 int request_id) { 1318 int request_id) {
1137 callbacks->Remove(request_id); 1319 callbacks->Remove(request_id);
1138 if (is_doomed_) { 1320 if (is_doomed_) {
1139 // The stop should be already scheduled, but try to stop immediately, in 1321 // The stop should be already scheduled, but try to stop immediately, in
1140 // order to release worker resources soon. 1322 // order to release worker resources soon.
1141 StopWorkerIfIdle(); 1323 StopWorkerIfIdle();
1142 } 1324 }
1143 } 1325 }
1144 1326
1145 } // namespace content 1327 } // 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