Commit c6f4fbae authored by dominicc@chromium.org's avatar dominicc@chromium.org

Use the Navigator's frame in navigator.serviceWorker and associated container.

NavigatorServiceWorker's use of CallWith=ExecutionContext meant the
container was configured depending on how it was accessed: for
example, navigator.serviceWorker would associate it with the frame's
execution context; but iframe.contentWindow.navigator.serviceWorker,
window.opener.navigator.serviceWorker,
window.parent.navigator.serviceWorker, etc. would associate it with a
different execution context. This change always retrieves the
execution context from the frame associated with the Navigator object.

Separately, the ServiceWorkerContainerClient was a supplement to the
page, which meant a main frame and an iframe could end up sharing a
ServiceWorkerContainerClient, violating the assumption of a 1:1
relationship between provider and client. This change associates it
with the document.

BUG=358979

Review URL: https://codereview.chromium.org/213223005

git-svn-id: svn://svn.chromium.org/blink/trunk@170641 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 46779daf
Test accessing navigator.serviceWorker of iframe doesn't crash
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<script src="../../resources/js-test.js"></script>
<body>
<script>
description('Test accessing navigator.serviceWorker of iframe doesn\'t crash');
navigator.serviceWorker;
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.contentWindow.navigator.serviceWorker;
var successfullyParsed = true;
</script>
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "config.h" #include "config.h"
#include "modules/serviceworkers/NavigatorServiceWorker.h" #include "modules/serviceworkers/NavigatorServiceWorker.h"
#include "core/frame/DOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Navigator.h" #include "core/frame/Navigator.h"
#include "modules/serviceworkers/ServiceWorkerContainer.h" #include "modules/serviceworkers/ServiceWorkerContainer.h"
...@@ -39,15 +41,17 @@ const char* NavigatorServiceWorker::supplementName() ...@@ -39,15 +41,17 @@ const char* NavigatorServiceWorker::supplementName()
return "NavigatorServiceWorker"; return "NavigatorServiceWorker";
} }
ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(ExecutionContext* executionContext, Navigator& navigator) ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(Navigator& navigator)
{ {
return NavigatorServiceWorker::from(navigator).serviceWorker(executionContext); return NavigatorServiceWorker::from(navigator).serviceWorker();
} }
ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(ExecutionContext* executionContext) ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker()
{ {
if (!m_serviceWorker && frame()) if (!m_serviceWorker && frame()) {
m_serviceWorker = ServiceWorkerContainer::create(executionContext); ASSERT(frame()->domWindow());
m_serviceWorker = ServiceWorkerContainer::create(frame()->domWindow()->executionContext());
}
return m_serviceWorker.get(); return m_serviceWorker.get();
} }
......
...@@ -23,13 +23,13 @@ public: ...@@ -23,13 +23,13 @@ public:
static NavigatorServiceWorker* toNavigatorServiceWorker(Navigator&); static NavigatorServiceWorker* toNavigatorServiceWorker(Navigator&);
static const char* supplementName(); static const char* supplementName();
static ServiceWorkerContainer* serviceWorker(ExecutionContext*, Navigator&); static ServiceWorkerContainer* serviceWorker(Navigator&);
void trace(Visitor*) { } void trace(Visitor*) { }
private: private:
explicit NavigatorServiceWorker(Navigator&); explicit NavigatorServiceWorker(Navigator&);
ServiceWorkerContainer* serviceWorker(ExecutionContext*); ServiceWorkerContainer* serviceWorker();
// DOMWindowProperty override. // DOMWindowProperty override.
virtual void willDetachGlobalObjectFromFrame() OVERRIDE; virtual void willDetachGlobalObjectFromFrame() OVERRIDE;
......
...@@ -5,5 +5,5 @@ ...@@ -5,5 +5,5 @@
[ [
RuntimeEnabled=ServiceWorker, RuntimeEnabled=ServiceWorker,
] partial interface Navigator { ] partial interface Navigator {
[CallWith=ExecutionContext] readonly attribute ServiceWorkerContainer serviceWorker; readonly attribute ServiceWorkerContainer serviceWorker;
}; };
...@@ -119,6 +119,9 @@ ServiceWorkerContainer::ServiceWorkerContainer(ExecutionContext* executionContex ...@@ -119,6 +119,9 @@ ServiceWorkerContainer::ServiceWorkerContainer(ExecutionContext* executionContex
{ {
ScriptWrappable::init(this); ScriptWrappable::init(this);
if (!executionContext)
return;
if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext)) { if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext)) {
m_provider = client->provider(); m_provider = client->provider();
if (m_provider) if (m_provider)
......
...@@ -35,13 +35,13 @@ ServiceWorkerContainerClient* ServiceWorkerContainerClient::from(ExecutionContex ...@@ -35,13 +35,13 @@ ServiceWorkerContainerClient* ServiceWorkerContainerClient::from(ExecutionContex
if (!document->frame()) if (!document->frame())
return 0; return 0;
ServiceWorkerContainerClient* client = static_cast<ServiceWorkerContainerClient*>(Supplement<Page>::from(document->page(), supplementName())); ServiceWorkerContainerClient* client = static_cast<ServiceWorkerContainerClient*>(DocumentSupplement::from(document, supplementName()));
if (client) if (client)
return client; return client;
// If it's not provided yet, create it lazily. // If it's not provided yet, create it lazily.
document->page()->provideSupplement(ServiceWorkerContainerClient::supplementName(), ServiceWorkerContainerClient::create(document->frame()->loader().client()->createServiceWorkerProvider())); document->provideSupplement(ServiceWorkerContainerClient::supplementName(), ServiceWorkerContainerClient::create(document->frame()->loader().client()->createServiceWorkerProvider()));
return static_cast<ServiceWorkerContainerClient*>(Supplement<Page>::from(document->page(), supplementName())); return static_cast<ServiceWorkerContainerClient*>(DocumentSupplement::from(document, supplementName()));
} }
ASSERT(context->isWorkerGlobalScope()); ASSERT(context->isWorkerGlobalScope());
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef ServiceWorkerContainerClient_h #ifndef ServiceWorkerContainerClient_h
#define ServiceWorkerContainerClient_h #define ServiceWorkerContainerClient_h
#include "core/page/Page.h" #include "core/dom/DocumentSupplementable.h"
#include "core/workers/WorkerClients.h" #include "core/workers/WorkerClients.h"
#include "wtf/Forward.h" #include "wtf/Forward.h"
...@@ -18,9 +18,9 @@ namespace WebCore { ...@@ -18,9 +18,9 @@ namespace WebCore {
class ExecutionContext; class ExecutionContext;
// This mainly exists to provide access to WebServiceWorkerProvider. // This mainly exists to provide access to WebServiceWorkerProvider.
// Owned by Page (or WorkerClients). // Owned by Document (or WorkerClients).
class ServiceWorkerContainerClient FINAL : class ServiceWorkerContainerClient FINAL :
public Supplement<Page>, public DocumentSupplement,
public Supplement<WorkerClients> { public Supplement<WorkerClients> {
WTF_MAKE_NONCOPYABLE(ServiceWorkerContainerClient); WTF_MAKE_NONCOPYABLE(ServiceWorkerContainerClient);
public: public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment