Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |