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 <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/guid.h" |
11 #include "base/location.h" | 12 #include "base/location.h" |
12 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
13 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
14 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
16 #include "base/strings/string16.h" | 17 #include "base/strings/string16.h" |
17 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
18 #include "base/thread_task_runner_handle.h" | 19 #include "base/thread_task_runner_handle.h" |
19 #include "base/time/time.h" | 20 #include "base/time/time.h" |
20 #include "content/browser/bad_message.h" | 21 #include "content/browser/bad_message.h" |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 callback.Run(status); | 170 callback.Run(status); |
170 } | 171 } |
171 | 172 |
172 void RunErrorServicePortConnectCallback( | 173 void RunErrorServicePortConnectCallback( |
173 const ServiceWorkerVersion::ServicePortConnectCallback& callback, | 174 const ServiceWorkerVersion::ServicePortConnectCallback& callback, |
174 ServiceWorkerStatusCode status) { | 175 ServiceWorkerStatusCode status) { |
175 callback.Run(status, false /* accept_connection */, base::string16(), | 176 callback.Run(status, false /* accept_connection */, base::string16(), |
176 base::string16()); | 177 base::string16()); |
177 } | 178 } |
178 | 179 |
179 using WindowOpenedCallback = base::Callback<void(int, int)>; | 180 using OpenURLCallback = base::Callback<void(int, int)>; |
180 | 181 |
181 // The WindowOpenedObserver class is a WebContentsObserver that will wait for a | 182 // The OpenURLObserver class is a WebContentsObserver that will wait for a |
182 // new Window's WebContents to be initialized, run the |callback| passed to its | 183 // WebContents to be initialized, run the |callback| passed to its constructor |
183 // constructor then self destroy. | 184 // then self destroy. |
184 // The callback will receive the process and frame ids. If something went wrong | 185 // The callback will receive the process and frame ids. If something went wrong |
185 // those will be (kInvalidUniqueID, MSG_ROUTING_NONE). | 186 // those will be (kInvalidUniqueID, MSG_ROUTING_NONE). |
186 // The callback will be called in the IO thread. | 187 // The callback will be called in the IO thread. |
187 class WindowOpenedObserver : public WebContentsObserver { | 188 class OpenURLObserver : public WebContentsObserver { |
188 public: | 189 public: |
189 WindowOpenedObserver(WebContents* web_contents, | 190 OpenURLObserver(WebContents* web_contents, const OpenURLCallback& callback) |
190 const WindowOpenedCallback& callback) | 191 : WebContentsObserver(web_contents), callback_(callback) {} |
191 : WebContentsObserver(web_contents), | |
192 callback_(callback) | |
193 {} | |
194 | 192 |
195 void DidCommitProvisionalLoadForFrame( | 193 void DidCommitProvisionalLoadForFrame( |
196 RenderFrameHost* render_frame_host, | 194 RenderFrameHost* render_frame_host, |
197 const GURL& validated_url, | 195 const GURL& validated_url, |
198 ui::PageTransition transition_type) override { | 196 ui::PageTransition transition_type) override { |
199 DCHECK(web_contents()); | 197 DCHECK(web_contents()); |
200 | 198 |
201 if (render_frame_host != web_contents()->GetMainFrame()) | 199 if (render_frame_host != web_contents()->GetMainFrame()) |
202 return; | 200 return; |
203 | 201 |
(...skipping 17 matching lines...) Expand all Loading... |
221 DCHECK(web_contents()); | 219 DCHECK(web_contents()); |
222 | 220 |
223 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 221 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
224 base::Bind(callback_, | 222 base::Bind(callback_, |
225 render_process_id, | 223 render_process_id, |
226 render_frame_id)); | 224 render_frame_id)); |
227 Observe(nullptr); | 225 Observe(nullptr); |
228 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 226 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
229 } | 227 } |
230 | 228 |
231 const WindowOpenedCallback callback_; | 229 const OpenURLCallback callback_; |
232 | 230 |
233 DISALLOW_COPY_AND_ASSIGN(WindowOpenedObserver); | 231 DISALLOW_COPY_AND_ASSIGN(OpenURLObserver); |
234 }; | 232 }; |
235 | 233 |
236 void DidOpenURL(const WindowOpenedCallback& callback, | 234 void DidOpenURL(const OpenURLCallback& callback, WebContents* web_contents) { |
237 WebContents* web_contents) { | |
238 DCHECK(web_contents); | 235 DCHECK(web_contents); |
239 | 236 |
240 new WindowOpenedObserver(web_contents, callback); | 237 new OpenURLObserver(web_contents, callback); |
| 238 } |
| 239 |
| 240 void NavigateClientOnUI(const GURL& url, |
| 241 const GURL& script_url, |
| 242 int process_id, |
| 243 int frame_id, |
| 244 const OpenURLCallback& callback) { |
| 245 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 246 |
| 247 RenderFrameHost* render_frame_host = |
| 248 RenderFrameHost::FromID(process_id, frame_id); |
| 249 WebContents* web_contents = |
| 250 WebContents::FromRenderFrameHost(render_frame_host); |
| 251 |
| 252 if (!render_frame_host || !web_contents) { |
| 253 BrowserThread::PostTask( |
| 254 BrowserThread::IO, FROM_HERE, |
| 255 base::Bind(callback, ChildProcessHost::kInvalidUniqueID, |
| 256 MSG_ROUTING_NONE)); |
| 257 return; |
| 258 } |
| 259 |
| 260 OpenURLParams params( |
| 261 url, Referrer::SanitizeForRequest( |
| 262 url, Referrer(script_url, blink::WebReferrerPolicyDefault)), |
| 263 CURRENT_TAB, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 264 true /* is_renderer_initiated */); |
| 265 web_contents->OpenURL(params); |
| 266 DidOpenURL(callback, web_contents); |
241 } | 267 } |
242 | 268 |
243 void OpenWindowOnUI( | 269 void OpenWindowOnUI( |
244 const GURL& url, | 270 const GURL& url, |
245 const GURL& script_url, | 271 const GURL& script_url, |
246 int process_id, | 272 int process_id, |
247 const scoped_refptr<ServiceWorkerContextWrapper>& context_wrapper, | 273 const scoped_refptr<ServiceWorkerContextWrapper>& context_wrapper, |
248 const WindowOpenedCallback& callback) { | 274 const OpenURLCallback& callback) { |
249 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 275 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
250 | 276 |
251 BrowserContext* browser_context = context_wrapper->storage_partition() | 277 BrowserContext* browser_context = context_wrapper->storage_partition() |
252 ? context_wrapper->storage_partition()->browser_context() | 278 ? context_wrapper->storage_partition()->browser_context() |
253 : nullptr; | 279 : nullptr; |
254 // We are shutting down. | 280 // We are shutting down. |
255 if (!browser_context) | 281 if (!browser_context) |
256 return; | 282 return; |
257 | 283 |
258 RenderProcessHost* render_process_host = | 284 RenderProcessHost* render_process_host = |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1180 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, | 1206 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow, |
1181 OnOpenWindow) | 1207 OnOpenWindow) |
1182 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetCachedMetadata, | 1208 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetCachedMetadata, |
1183 OnSetCachedMetadata) | 1209 OnSetCachedMetadata) |
1184 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClearCachedMetadata, | 1210 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClearCachedMetadata, |
1185 OnClearCachedMetadata) | 1211 OnClearCachedMetadata) |
1186 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToClient, | 1212 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToClient, |
1187 OnPostMessageToClient) | 1213 OnPostMessageToClient) |
1188 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, | 1214 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, |
1189 OnFocusClient) | 1215 OnFocusClient) |
| 1216 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NavigateClient, OnNavigateClient) |
1190 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, | 1217 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SkipWaiting, |
1191 OnSkipWaiting) | 1218 OnSkipWaiting) |
1192 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, | 1219 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ClaimClients, |
1193 OnClaimClients) | 1220 OnClaimClients) |
1194 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_Pong, OnPongFromWorker) | 1221 IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_Pong, OnPongFromWorker) |
1195 IPC_MESSAGE_UNHANDLED(handled = false) | 1222 IPC_MESSAGE_UNHANDLED(handled = false) |
1196 IPC_END_MESSAGE_MAP() | 1223 IPC_END_MESSAGE_MAP() |
1197 return handled; | 1224 return handled; |
1198 } | 1225 } |
1199 | 1226 |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1639 if (running_status() != RUNNING) | 1666 if (running_status() != RUNNING) |
1640 return; | 1667 return; |
1641 | 1668 |
1642 ServiceWorkerClientInfo client_info(client); | 1669 ServiceWorkerClientInfo client_info(client); |
1643 client_info.client_uuid = client_uuid; | 1670 client_info.client_uuid = client_uuid; |
1644 | 1671 |
1645 embedded_worker_->SendMessage(ServiceWorkerMsg_FocusClientResponse( | 1672 embedded_worker_->SendMessage(ServiceWorkerMsg_FocusClientResponse( |
1646 request_id, client_info)); | 1673 request_id, client_info)); |
1647 } | 1674 } |
1648 | 1675 |
| 1676 void ServiceWorkerVersion::OnNavigateClient(int request_id, |
| 1677 const std::string& client_uuid, |
| 1678 const GURL& url) { |
| 1679 if (!context_) |
| 1680 return; |
| 1681 |
| 1682 TRACE_EVENT2("ServiceWorker", "ServiceWorkerVersion::OnNavigateClient", |
| 1683 "Request id", request_id, "Client id", client_uuid); |
| 1684 |
| 1685 if (!url.is_valid() || !base::IsValidGUID(client_uuid)) { |
| 1686 DVLOG(1) << "Received unexpected invalid URL/UUID from renderer process."; |
| 1687 BrowserThread::PostTask( |
| 1688 BrowserThread::UI, FROM_HERE, |
| 1689 base::Bind(&KillEmbeddedWorkerProcess, embedded_worker_->process_id(), |
| 1690 RESULT_CODE_KILLED_BAD_MESSAGE)); |
| 1691 return; |
| 1692 } |
| 1693 |
| 1694 // Reject requests for URLs that the process is not allowed to access. It's |
| 1695 // possible to receive such requests since the renderer-side checks are |
| 1696 // slightly different. For example, the view-source scheme will not be |
| 1697 // filtered out by Blink. |
| 1698 if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( |
| 1699 embedded_worker_->process_id(), url)) { |
| 1700 embedded_worker_->SendMessage( |
| 1701 ServiceWorkerMsg_NavigateClientError(request_id, url)); |
| 1702 return; |
| 1703 } |
| 1704 |
| 1705 ServiceWorkerProviderHost* provider_host = |
| 1706 context_->GetProviderHostByClientID(client_uuid); |
| 1707 if (!provider_host || provider_host->active_version() != this) { |
| 1708 embedded_worker_->SendMessage( |
| 1709 ServiceWorkerMsg_NavigateClientError(request_id, url)); |
| 1710 return; |
| 1711 } |
| 1712 |
| 1713 BrowserThread::PostTask( |
| 1714 BrowserThread::UI, FROM_HERE, |
| 1715 base::Bind(&NavigateClientOnUI, url, script_url_, |
| 1716 provider_host->process_id(), provider_host->frame_id(), |
| 1717 base::Bind(&ServiceWorkerVersion::DidNavigateClient, |
| 1718 weak_factory_.GetWeakPtr(), request_id))); |
| 1719 } |
| 1720 |
| 1721 void ServiceWorkerVersion::DidNavigateClient(int request_id, |
| 1722 int render_process_id, |
| 1723 int render_frame_id) { |
| 1724 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1725 |
| 1726 if (running_status() != RUNNING) |
| 1727 return; |
| 1728 |
| 1729 if (render_process_id == ChildProcessHost::kInvalidUniqueID && |
| 1730 render_frame_id == MSG_ROUTING_NONE) { |
| 1731 embedded_worker_->SendMessage( |
| 1732 ServiceWorkerMsg_NavigateClientError(request_id, GURL())); |
| 1733 return; |
| 1734 } |
| 1735 |
| 1736 for (auto it = |
| 1737 context_->GetClientProviderHostIterator(script_url_.GetOrigin()); |
| 1738 !it->IsAtEnd(); it->Advance()) { |
| 1739 ServiceWorkerProviderHost* provider_host = it->GetProviderHost(); |
| 1740 if (provider_host->process_id() != render_process_id || |
| 1741 provider_host->frame_id() != render_frame_id) { |
| 1742 continue; |
| 1743 } |
| 1744 provider_host->GetWindowClientInfo(base::Bind( |
| 1745 &ServiceWorkerVersion::OnNavigateClientFinished, |
| 1746 weak_factory_.GetWeakPtr(), request_id, provider_host->client_uuid())); |
| 1747 return; |
| 1748 } |
| 1749 |
| 1750 OnNavigateClientFinished(request_id, std::string(), |
| 1751 ServiceWorkerClientInfo()); |
| 1752 } |
| 1753 |
| 1754 void ServiceWorkerVersion::OnNavigateClientFinished( |
| 1755 int request_id, |
| 1756 const std::string& client_uuid, |
| 1757 const ServiceWorkerClientInfo& client_info) { |
| 1758 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1759 |
| 1760 if (running_status() != RUNNING) |
| 1761 return; |
| 1762 |
| 1763 ServiceWorkerClientInfo client(client_info); |
| 1764 |
| 1765 // If the |client_info| is empty, it means that the navigated client wasn't |
| 1766 // controlled but the action still succeeded. The renderer process is |
| 1767 // expecting an empty client in such case. |
| 1768 if (!client.IsEmpty()) |
| 1769 client.client_uuid = client_uuid; |
| 1770 |
| 1771 embedded_worker_->SendMessage( |
| 1772 ServiceWorkerMsg_NavigateClientResponse(request_id, client)); |
| 1773 } |
| 1774 |
1649 void ServiceWorkerVersion::OnSkipWaiting(int request_id) { | 1775 void ServiceWorkerVersion::OnSkipWaiting(int request_id) { |
1650 skip_waiting_ = true; | 1776 skip_waiting_ = true; |
1651 if (status_ != INSTALLED) | 1777 if (status_ != INSTALLED) |
1652 return DidSkipWaiting(request_id); | 1778 return DidSkipWaiting(request_id); |
1653 | 1779 |
1654 if (!context_) | 1780 if (!context_) |
1655 return; | 1781 return; |
1656 ServiceWorkerRegistration* registration = | 1782 ServiceWorkerRegistration* registration = |
1657 context_->GetLiveRegistration(registration_id_); | 1783 context_->GetLiveRegistration(registration_id_); |
1658 if (!registration) | 1784 if (!registration) |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2169 base::string16()); | 2295 base::string16()); |
2170 service_port_dispatcher_.reset(); | 2296 service_port_dispatcher_.reset(); |
2171 } | 2297 } |
2172 | 2298 |
2173 void ServiceWorkerVersion::OnBackgroundSyncDispatcherConnectionError() { | 2299 void ServiceWorkerVersion::OnBackgroundSyncDispatcherConnectionError() { |
2174 RunIDMapCallbacks(&sync_requests_, SERVICE_WORKER_ERROR_FAILED); | 2300 RunIDMapCallbacks(&sync_requests_, SERVICE_WORKER_ERROR_FAILED); |
2175 background_sync_dispatcher_.reset(); | 2301 background_sync_dispatcher_.reset(); |
2176 } | 2302 } |
2177 | 2303 |
2178 } // namespace content | 2304 } // namespace content |
OLD | NEW |