View | Details | Raw Unified | Return to bug 105367 | Differences between
and this patch

Collapse All | Expand All

(-)a/Source/WebCore/ChangeLog (+19 lines)
Lines 1-3 Link Here
1
2013-01-02  Kenneth Russell  <kbr@google.com>
2
3
        [chromium] Creation of dedicated workers (isolates) leaks reference to HTMLDocument
4
        https://bugs.webkit.org/show_bug.cgi?id=105367
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Eliminated a Chromium-specific object wrapping WorkerMessagingProxy in order to fix a
9
        lifetime management bug, which leaked every Document which started a dedicated worker.
10
11
        Test: fast/workers/worker-document-leak.html
12
13
        * workers/WorkerLoaderProxy.h:
14
        (WorkerLoaderProxy):
15
            Added Chromium-specific casting method to bridge two now-distinct class hierarchies.
16
        * workers/WorkerMessagingProxy.h:
17
        (WorkerMessagingProxy):
18
            Made destructor protected instead of private to allow subclassing.
19
1
2013-01-02  Tony Chang  <tony@chromium.org>
20
2013-01-02  Tony Chang  <tony@chromium.org>
2
21
3
        Generate internal.settings from Settings.in
22
        Generate internal.settings from Settings.in
(-)a/Source/WebKit/chromium/ChangeLog (+69 lines)
Lines 1-3 Link Here
1
2013-01-02  Kenneth Russell  <kbr@google.com>
2
3
        [chromium] Creation of dedicated workers (isolates) leaks reference to HTMLDocument
4
        https://bugs.webkit.org/show_bug.cgi?id=105367
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Made WebWorkerClientImpl a subclass of WorkerMessagingProxy rather than an object wrapping
9
        WorkerMessagingProxy. WorkerMessagingProxy manages its own lifetime and it is impossible to
10
        properly synchronize the lifetime of WebWorkerClientImpl separately.
11
12
        This allowed most of WebWorkerClientImpl to be deleted, but forced a divergence in the class
13
        hierarchies of WebWorkerClientImpl and WebSharedWorkerImpl. Conversion methods were added to
14
        WorkerLoaderProxy and WebWorkerBase to bridge the hierarchies of in-process and
15
        out-of-process workers.
16
17
        * src/DatabaseObserver.cpp:
18
        (WebCore::DatabaseObserver::canEstablishDatabase):
19
            Adjusted how WebWorkerBase is obtained from WorkerLoaderProxy.
20
        * src/IDBFactoryBackendProxy.cpp:
21
        (WebKit::AllowIndexedDBMainThreadBridge::signalCompleted):
22
            Adjusted how WorkerLoaderProxy's methods are called.
23
        (WebKit::IDBFactoryBackendProxy::allowIndexedDB):
24
            Adjusted how WebWorkerBase is obtained from WorkerLoaderProxy.
25
        * src/LocalFileSystemChromium.cpp:
26
        (WebCore::openFileSystemHelper):
27
            Adjusted how WebWorkerBase is obtained from WorkerLoaderProxy.
28
        * src/WebSharedWorkerImpl.cpp:
29
        (WebKit::WebSharedWorkerImpl::toWebWorkerBase):
30
            Implemented new conversion method.
31
        * src/WebSharedWorkerImpl.h:
32
        (WebSharedWorkerImpl):
33
            Explicitly derive from WorkerLoaderProxy now that WebWorkerBase no longer does.
34
        (WebKit::WebSharedWorkerImpl::workerLoaderProxy):
35
            Added new conversion method.
36
        * src/WebWorkerBase.h:
37
        (WebWorkerBase):
38
            Removed derivation from WorkerLoaderProxy. Added method to convert to WorkerLoaderProxy.
39
        * src/WebWorkerClientImpl.cpp:
40
        (WebKit):
41
            Adjusted comment.
42
        (WebKit::WebWorkerClientImpl::createWorkerContextProxy):
43
            Adjusted whitespace.
44
        (WebKit::WebWorkerClientImpl::terminateWorkerContext):
45
            Eliminated delegation to separate object.
46
        (WebKit::WebWorkerClientImpl::toWebWorkerBase):
47
            Implemented new conversion method.
48
        (WebKit::WebWorkerClientImpl::view):
49
        (WebKit::WebWorkerClientImpl::allowDatabase):
50
        (WebKit::WebWorkerClientImpl::allowFileSystem):
51
        (WebKit::WebWorkerClientImpl::openFileSystem):
52
        (WebKit::WebWorkerClientImpl::allowIndexedDB):
53
            Eliminated delegation to separate object.
54
        (WebKit::WebWorkerClientImpl::WebWorkerClientImpl):
55
        * src/WebWorkerClientImpl.h:
56
        (WebKit):
57
            Changed to inherit from WorkerMessagingProxy directly.
58
        (WebWorkerClientImpl):
59
            Deleted most methods previously overridden from WorkerContextProxy, etc.
60
        * src/WorkerAsyncFileSystemChromium.cpp:
61
        (WebCore::WorkerAsyncFileSystemChromium::WorkerAsyncFileSystemChromium):
62
        (WebCore::WorkerAsyncFileSystemChromium::createWorkerFileSystemCallbacksBridge):
63
            Hold on to, and use, WorkerLoaderProxy rather than WebWorkerBase.
64
        * src/WorkerAsyncFileSystemChromium.h:
65
        (WebKit):
66
        (WebCore):
67
        (WorkerAsyncFileSystemChromium):
68
            Hold on to WorkerLoaderProxy rather than WebWorkerBase.
69
1
2013-01-02  Robert Kroeger  <rjkroege@chromium.org>
70
2013-01-02  Robert Kroeger  <rjkroege@chromium.org>
2
71
3
        [chromium] Use top level field for gesture event source
72
        [chromium] Use top level field for gesture event source
(-)a/Source/WebCore/workers/WorkerLoaderProxy.h (+11 lines)
Lines 37-42 Link Here
37
#include <wtf/Forward.h>
37
#include <wtf/Forward.h>
38
#include <wtf/PassOwnPtr.h>
38
#include <wtf/PassOwnPtr.h>
39
39
40
#if PLATFORM(CHROMIUM)
41
namespace WebKit {
42
class WebWorkerBase;
43
}
44
#endif // PLATFORM(CHROMIUM)
45
40
namespace WebCore {
46
namespace WebCore {
41
47
42
    // A proxy to talk to the loader context. Normally, the document on the main thread
48
    // A proxy to talk to the loader context. Normally, the document on the main thread
Lines 55-60 namespace WebCore { Link Here
55
        // specific synchronous loading requests so they can be 'nested', per spec.
61
        // specific synchronous loading requests so they can be 'nested', per spec.
56
        // Returns true if the task was posted successfully.
62
        // Returns true if the task was posted successfully.
57
        virtual bool postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutionContext::Task>, const String& mode) = 0;
63
        virtual bool postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutionContext::Task>, const String& mode) = 0;
64
65
#if PLATFORM(CHROMIUM)
66
        // Spans divergent class hierarchies for dedicated and shared workers.
67
        virtual WebKit::WebWorkerBase* toWebWorkerBase() = 0;
68
#endif
58
    };
69
    };
59
70
60
} // namespace WebCore
71
} // namespace WebCore
(-)a/Source/WebCore/workers/WorkerMessagingProxy.h (-2 / +3 lines)
Lines 89-94 namespace WebCore { Link Here
89
        // Only use this method on the worker object thread.
89
        // Only use this method on the worker object thread.
90
        bool askedToTerminate() const { return m_askedToTerminate; }
90
        bool askedToTerminate() const { return m_askedToTerminate; }
91
91
92
    protected:
93
        virtual ~WorkerMessagingProxy();
94
92
    private:
95
    private:
93
        friend class MessageWorkerTask;
96
        friend class MessageWorkerTask;
94
        friend class PostMessageToPageInspectorTask;
97
        friend class PostMessageToPageInspectorTask;
Lines 96-103 namespace WebCore { Link Here
96
        friend class WorkerExceptionTask;
99
        friend class WorkerExceptionTask;
97
        friend class WorkerThreadActivityReportTask;
100
        friend class WorkerThreadActivityReportTask;
98
101
99
        virtual ~WorkerMessagingProxy();
100
101
        void workerContextDestroyedInternal();
102
        void workerContextDestroyedInternal();
102
        static void workerObjectDestroyedInternal(ScriptExecutionContext*, WorkerMessagingProxy*);
103
        static void workerObjectDestroyedInternal(ScriptExecutionContext*, WorkerMessagingProxy*);
103
        void reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity);
104
        void reportPendingActivityInternal(bool confirmingMessage, bool hasPendingActivity);
(-)a/Source/WebKit/chromium/src/DatabaseObserver.cpp (-2 / +1 lines)
Lines 164-171 bool DatabaseObserver::canEstablishDatabase(ScriptExecutionContext* scriptExecut Link Here
164
    } else {
164
    } else {
165
#if ENABLE(WORKERS)
165
#if ENABLE(WORKERS)
166
        WorkerContext* workerContext = static_cast<WorkerContext*>(scriptExecutionContext);
166
        WorkerContext* workerContext = static_cast<WorkerContext*>(scriptExecutionContext);
167
        WorkerLoaderProxy* workerLoaderProxy = &workerContext->thread()->workerLoaderProxy();
167
        WebWorkerBase* webWorker = static_cast<WebWorkerBase*>(workerContext->thread()->workerLoaderProxy().toWebWorkerBase());
168
        WebWorkerBase* webWorker = static_cast<WebWorkerBase*>(workerLoaderProxy);
169
        WebView* view = webWorker->view();
168
        WebView* view = webWorker->view();
170
        if (!view)
169
        if (!view)
171
            return false;
170
            return false;
(-)a/Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp (-2 / +2 lines)
Lines 111-117 public: Link Here
111
    {
111
    {
112
        MutexLocker locker(m_mutex);
112
        MutexLocker locker(m_mutex);
113
        if (m_webWorkerBase)
113
        if (m_webWorkerBase)
114
            m_webWorkerBase->postTaskForModeToWorkerContext(createCallbackTask(&didComplete, this, result), mode);
114
            m_webWorkerBase->workerLoaderProxy()->postTaskForModeToWorkerContext(createCallbackTask(&didComplete, this, result), mode);
115
    }
115
    }
116
116
117
private:
117
private:
Lines 172-178 bool IDBFactoryBackendProxy::allowIndexedDB(ScriptExecutionContext* context, con Link Here
172
        allowed = !webView->permissionClient() || webView->permissionClient()->allowIndexedDB(webFrame, name, origin);
172
        allowed = !webView->permissionClient() || webView->permissionClient()->allowIndexedDB(webFrame, name, origin);
173
    } else {
173
    } else {
174
        WorkerContext* workerContext = static_cast<WorkerContext*>(context);
174
        WorkerContext* workerContext = static_cast<WorkerContext*>(context);
175
        WebWorkerBase* webWorkerBase = static_cast<WebWorkerBase*>(&workerContext->thread()->workerLoaderProxy());
175
        WebWorkerBase* webWorkerBase = static_cast<WebWorkerBase*>(workerContext->thread()->workerLoaderProxy().toWebWorkerBase());
176
        WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
176
        WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
177
177
178
        String mode = allowIndexedDBMode;
178
        String mode = allowIndexedDBMode;
(-)a/Source/WebKit/chromium/src/LocalFileSystemChromium.cpp (-2 / +1 lines)
Lines 203-210 static void openFileSystemHelper(ScriptExecutionContext* context, FileSystemType Link Here
203
    } else {
203
    } else {
204
#if ENABLE(WORKERS)
204
#if ENABLE(WORKERS)
205
        WorkerContext* workerContext = static_cast<WorkerContext*>(context);
205
        WorkerContext* workerContext = static_cast<WorkerContext*>(context);
206
        WorkerLoaderProxy* workerLoaderProxy = &workerContext->thread()->workerLoaderProxy();
206
        WebWorkerBase* webWorker = static_cast<WebWorkerBase*>(workerContext->thread()->workerLoaderProxy().toWebWorkerBase());
207
        WebWorkerBase* webWorker = static_cast<WebWorkerBase*>(workerLoaderProxy);
208
        if (!allowFileSystemForWorker(webWorker->commonClient()))
207
        if (!allowFileSystemForWorker(webWorker->commonClient()))
209
            allowed = false;
208
            allowed = false;
210
        else
209
        else
(-)a/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp (+4 lines)
Lines 324-329 bool WebSharedWorkerImpl::postTaskForModeToWorkerContext( Link Here
324
    return true;
324
    return true;
325
}
325
}
326
326
327
WebWorkerBase* WebSharedWorkerImpl::toWebWorkerBase()
328
{
329
    return this;
330
}
327
331
328
332
329
bool WebSharedWorkerImpl::isStarted()
333
bool WebSharedWorkerImpl::isStarted()
(-)a/Source/WebKit/chromium/src/WebSharedWorkerImpl.h (-5 / +9 lines)
Lines 61-70 class WebSharedWorkerClient; Link Here
61
// It can't use it directly since it uses WebKit types, so this class converts the data types.
61
// It can't use it directly since it uses WebKit types, so this class converts the data types.
62
// When the WebCore::SharedWorker object wants to call WebCore::WorkerReportingProxy, this class will
62
// When the WebCore::SharedWorker object wants to call WebCore::WorkerReportingProxy, this class will
63
// convert to Chrome data types first and then call the supplied WebCommonWorkerClient.
63
// convert to Chrome data types first and then call the supplied WebCommonWorkerClient.
64
class WebSharedWorkerImpl : public WebCore::WorkerObjectProxy
64
class WebSharedWorkerImpl
65
                          , public WebWorkerBase
65
    : public WebCore::WorkerObjectProxy
66
                          , public WebFrameClient
66
    , public WebCore::WorkerLoaderProxy
67
                          , public WebSharedWorker {
67
    , public WebWorkerBase
68
    , public WebFrameClient
69
    , public WebSharedWorker {
68
public:
70
public:
69
    explicit WebSharedWorkerImpl(WebSharedWorkerClient*);
71
    explicit WebSharedWorkerImpl(WebSharedWorkerClient*);
70
72
Lines 88-93 public: Link Here
88
    virtual void postTaskToLoader(PassOwnPtr<WebCore::ScriptExecutionContext::Task>);
90
    virtual void postTaskToLoader(PassOwnPtr<WebCore::ScriptExecutionContext::Task>);
89
    virtual bool postTaskForModeToWorkerContext(
91
    virtual bool postTaskForModeToWorkerContext(
90
        PassOwnPtr<WebCore::ScriptExecutionContext::Task>, const WTF::String& mode);
92
        PassOwnPtr<WebCore::ScriptExecutionContext::Task>, const WTF::String& mode);
93
    virtual WebWorkerBase* toWebWorkerBase() OVERRIDE;
91
94
92
    // WebFrameClient methods to support resource loading thru the 'shadow page'.
95
    // WebFrameClient methods to support resource loading thru the 'shadow page'.
93
    virtual void didCreateDataSource(WebFrame*, WebDataSource*);
96
    virtual void didCreateDataSource(WebFrame*, WebDataSource*);
Lines 111-117 public: Link Here
111
    virtual void dispatchDevToolsMessage(const WebString&);
114
    virtual void dispatchDevToolsMessage(const WebString&);
112
115
113
116
114
    // NewWebWorkerBase methods:
117
    // WebWorkerBase methods:
118
    WebCore::WorkerLoaderProxy* workerLoaderProxy() { return this; }
115
    WebCommonWorkerClient* commonClient() { return m_client; }
119
    WebCommonWorkerClient* commonClient() { return m_client; }
116
120
117
private:
121
private:
(-)a/Source/WebKit/chromium/src/WebWorkerBase.h (-1 / +2 lines)
Lines 48-55 class WebView; Link Here
48
// containing common interface for shared workers and dedicated in-proc workers implementation.
48
// containing common interface for shared workers and dedicated in-proc workers implementation.
49
//
49
//
50
// FIXME: Rename this class into WebWorkerBase, merge existing WebWorkerBase and WebSharedWorker.
50
// FIXME: Rename this class into WebWorkerBase, merge existing WebWorkerBase and WebSharedWorker.
51
class WebWorkerBase : public WebCore::WorkerLoaderProxy {
51
class WebWorkerBase {
52
public:
52
public:
53
    virtual WebCore::WorkerLoaderProxy* workerLoaderProxy() = 0;
53
    virtual WebCommonWorkerClient* commonClient() = 0;
54
    virtual WebCommonWorkerClient* commonClient() = 0;
54
    virtual WebView* view() const = 0;
55
    virtual WebView* view() const = 0;
55
56
(-)a/Source/WebKit/chromium/src/WebWorkerClientImpl.cpp (-125 / +23 lines)
Lines 69-75 using namespace WebCore; Link Here
69
69
70
namespace WebKit {
70
namespace WebKit {
71
71
72
// Chromium-specific wrapper over WorkerMessagingProxy.
72
// Chromium-specific decorator of WorkerMessagingProxy.
73
// Delegates implementation of Worker{Loader,Context,Object}Proxy to WorkerMessagingProxy.
73
// Delegates implementation of Worker{Loader,Context,Object}Proxy to WorkerMessagingProxy.
74
74
75
// static
75
// static
Lines 79-205 WorkerContextProxy* WebWorkerClientImpl::createWorkerContextProxy(Worker* worker Link Here
79
        Document* document = static_cast<Document*>(worker->scriptExecutionContext());
79
        Document* document = static_cast<Document*>(worker->scriptExecutionContext());
80
        WebFrameImpl* webFrame = WebFrameImpl::fromFrame(document->frame());
80
        WebFrameImpl* webFrame = WebFrameImpl::fromFrame(document->frame());
81
        WebWorkerClientImpl* proxy = new WebWorkerClientImpl(worker, webFrame);
81
        WebWorkerClientImpl* proxy = new WebWorkerClientImpl(worker, webFrame);
82
        return proxy; 
82
        return proxy;
83
    } 
83
    }
84
    ASSERT_NOT_REACHED();
84
    ASSERT_NOT_REACHED();
85
    return 0;
85
    return 0;
86
}
86
}
87
87
88
void WebWorkerClientImpl::startWorkerContext(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerThreadStartMode startMode)
89
{
90
    ASSERT(m_scriptExecutionContext->isDocument());
91
    Document* document = static_cast<Document*>(m_scriptExecutionContext.get());
92
    GroupSettings* settings = 0;
93
    if (document->page())
94
        settings = document->page()->group().groupSettings();
95
    RefPtr<DedicatedWorkerThread> thread = DedicatedWorkerThread::create(scriptURL, userAgent, settings, sourceCode, *this, *this, startMode,
96
                                                                         document->contentSecurityPolicy()->deprecatedHeader(),
97
                                                                         document->contentSecurityPolicy()->deprecatedHeaderType(),
98
                                                                         document->topDocument()->securityOrigin());
99
    m_proxy->workerThreadCreated(thread);
100
    thread->start();
101
    InspectorInstrumentation::didStartWorkerContext(m_scriptExecutionContext.get(), m_proxy, scriptURL);
102
}
103
104
void WebWorkerClientImpl::terminateWorkerContext()
88
void WebWorkerClientImpl::terminateWorkerContext()
105
{
89
{
106
    m_webFrame = 0;
90
    m_webFrame = 0;
107
    m_proxy->terminateWorkerContext();
91
    WebCore::WorkerMessagingProxy::terminateWorkerContext();
108
}
109
110
void WebWorkerClientImpl::postMessageToWorkerContext(
111
    PassRefPtr<SerializedScriptValue> value, 
112
    PassOwnPtr<MessagePortChannelArray> ports)
113
{
114
    m_proxy->postMessageToWorkerContext(value, ports);
115
}
116
117
bool WebWorkerClientImpl::hasPendingActivity() const
118
{
119
    return m_proxy->hasPendingActivity();
120
}
121
122
void WebWorkerClientImpl::workerObjectDestroyed()
123
{
124
    m_proxy->workerObjectDestroyed();
125
}
126
127
#if ENABLE(INSPECTOR)
128
void WebWorkerClientImpl::connectToInspector(PageInspector* inspector)
129
{
130
    m_proxy->connectToInspector(inspector);
131
}
132
133
void WebWorkerClientImpl::disconnectFromInspector()
134
{
135
    m_proxy->disconnectFromInspector();
136
}
137
138
void WebWorkerClientImpl::sendMessageToInspector(const String& message)
139
{
140
    m_proxy->sendMessageToInspector(message);
141
}
142
143
void WebWorkerClientImpl::postMessageToPageInspector(const String& message)
144
{
145
    m_proxy->postMessageToPageInspector(message);
146
}
147
148
void WebWorkerClientImpl::updateInspectorStateCookie(const String& cookie)
149
{
150
    m_proxy->updateInspectorStateCookie(cookie);
151
}
152
#endif // ENABLE(INSPECTOR)
153
154
155
void WebWorkerClientImpl::postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task> task)
156
{
157
    m_proxy->postTaskToLoader(task);
158
}
92
}
159
93
160
bool WebWorkerClientImpl::postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode)
94
WebWorkerBase* WebWorkerClientImpl::toWebWorkerBase()
161
{
95
{
162
    return m_proxy->postTaskForModeToWorkerContext(task, mode);
96
    return this;
163
}
97
}
164
98
165
void WebWorkerClientImpl::postMessageToWorkerObject(PassRefPtr<SerializedScriptValue> value, PassOwnPtr<MessagePortChannelArray> ports)
99
WebView* WebWorkerClientImpl::view() const
166
{
100
{
167
    m_proxy->postMessageToWorkerObject(value, ports);
101
    if (askedToTerminate())
168
}
102
        return 0;
169
103
    return m_webFrame->view();
170
void WebWorkerClientImpl::confirmMessageFromWorkerObject(bool hasPendingActivity)
171
{
172
    m_proxy->confirmMessageFromWorkerObject(hasPendingActivity);
173
}
174
175
void WebWorkerClientImpl::reportPendingActivity(bool hasPendingActivity)
176
{
177
    m_proxy->reportPendingActivity(hasPendingActivity);
178
}
179
180
void WebWorkerClientImpl::workerContextClosed()
181
{
182
    m_proxy->workerContextClosed();
183
}
184
185
void WebWorkerClientImpl::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL)
186
{
187
    m_proxy->postExceptionToWorkerObject(errorMessage, lineNumber, sourceURL);
188
}
189
190
void WebWorkerClientImpl::postConsoleMessageToWorkerObject(MessageSource source, MessageLevel level, const String& message, int lineNumber, const String& sourceURL)
191
{
192
    m_proxy->postConsoleMessageToWorkerObject(source, level, message, lineNumber, sourceURL);
193
}
104
}
194
105
195
void WebWorkerClientImpl::workerContextDestroyed()
106
bool WebWorkerClientImpl::allowDatabase(WebFrame*, const WebString& name, const WebString& displayName, unsigned long estimatedSize)
196
{
107
{
197
    m_proxy->workerContextDestroyed();
108
    if (askedToTerminate())
109
        return false;
110
    WebKit::WebViewImpl* webView = m_webFrame->viewImpl();
111
    if (!webView)
112
        return false;
113
    return !webView->permissionClient() || webView->permissionClient()->allowDatabase(m_webFrame, name, displayName, estimatedSize);
198
}
114
}
199
115
200
bool WebWorkerClientImpl::allowFileSystem()
116
bool WebWorkerClientImpl::allowFileSystem()
201
{
117
{
202
    if (m_proxy->askedToTerminate())
118
    if (askedToTerminate())
203
        return false;
119
        return false;
204
    WebKit::WebViewImpl* webView = m_webFrame->viewImpl();
120
    WebKit::WebViewImpl* webView = m_webFrame->viewImpl();
205
    if (!webView)
121
    if (!webView)
Lines 207-253 bool WebWorkerClientImpl::allowFileSystem() Link Here
207
    return !webView->permissionClient() || webView->permissionClient()->allowFileSystem(m_webFrame);
123
    return !webView->permissionClient() || webView->permissionClient()->allowFileSystem(m_webFrame);
208
}
124
}
209
125
210
void WebWorkerClientImpl::openFileSystem(WebFileSystem::Type type, long long size, bool create, 
126
void WebWorkerClientImpl::openFileSystem(WebFileSystem::Type type, long long size, bool create,
211
                                         WebFileSystemCallbacks* callbacks)
127
                                         WebFileSystemCallbacks* callbacks)
212
{
128
{
213
    if (m_proxy->askedToTerminate()) {
129
    if (askedToTerminate()) {
214
        callbacks->didFail(WebFileErrorAbort);
130
        callbacks->didFail(WebFileErrorAbort);
215
        return;
131
        return;
216
    }
132
    }
217
    m_webFrame->client()->openFileSystem(m_webFrame, type, size, create, callbacks);
133
    m_webFrame->client()->openFileSystem(m_webFrame, type, size, create, callbacks);
218
}
134
}
219
135
220
bool WebWorkerClientImpl::allowDatabase(WebFrame*, const WebString& name, const WebString& displayName, unsigned long estimatedSize) 
221
{
222
    if (m_proxy->askedToTerminate())
223
        return false;
224
    WebKit::WebViewImpl* webView = m_webFrame->viewImpl();
225
    if (!webView)
226
        return false;
227
    return !webView->permissionClient() || webView->permissionClient()->allowDatabase(m_webFrame, name, displayName, estimatedSize);
228
}
229
230
bool WebWorkerClientImpl::allowIndexedDB(const WebString& name)
136
bool WebWorkerClientImpl::allowIndexedDB(const WebString& name)
231
{
137
{
232
    if (m_proxy->askedToTerminate())
138
    if (askedToTerminate())
233
        return false;
139
        return false;
234
    WebKit::WebViewImpl* webView = m_webFrame->viewImpl();
140
    WebKit::WebViewImpl* webView = m_webFrame->viewImpl();
235
    if (!webView)
141
    if (!webView)
236
        return false;
142
        return false;
237
    return !webView->permissionClient() || webView->permissionClient()->allowIndexedDB(m_webFrame, name, WebSecurityOrigin());
143
    return !webView->permissionClient() || webView->permissionClient()->allowIndexedDB(m_webFrame, name, WebSecurityOrigin());
238
}
144
}
239
 
240
WebView* WebWorkerClientImpl::view() const 
241
{
242
    if (m_proxy->askedToTerminate())
243
        return 0;
244
    return m_webFrame->view(); 
245
}
246
145
247
WebWorkerClientImpl::WebWorkerClientImpl(Worker* worker, WebFrameImpl* webFrame)
146
WebWorkerClientImpl::WebWorkerClientImpl(Worker* worker, WebFrameImpl* webFrame)
248
    : m_proxy(new WorkerMessagingProxy(worker))
147
    : WebCore::WorkerMessagingProxy(worker)
249
    , m_scriptExecutionContext(worker->scriptExecutionContext())
148
    , m_webFrame(webFrame)
250
    , m_webFrame(webFrame)    
251
{
149
{
252
}
150
}
253
151
(-)a/Source/WebKit/chromium/src/WebWorkerClientImpl.h (-43 / +17 lines)
Lines 54-62 class WebFrameImpl; Link Here
54
// for in-proc dedicated workers. It also acts as a bridge for workers to chromium implementation of file systems,
54
// for in-proc dedicated workers. It also acts as a bridge for workers to chromium implementation of file systems,
55
// databases and other related functionality.
55
// databases and other related functionality.
56
//
56
//
57
// In essence, this class wraps WorkerMessagingProxy.
57
// In essence, this class decorates WorkerMessagingProxy.
58
class WebWorkerClientImpl : public WebCore::WorkerContextProxy
58
//
59
                          , public WebCore::WorkerObjectProxy
59
// It is imperative that this class inherit from WorkerMessagingProxy rather than delegate to an instance of
60
// WorkerMessagingProxy, because that class tracks and reports its activity to outside callers, and manages
61
// its own lifetime, via calls to workerObjectDestroyed, workerContextDestroyed, workerContextClosed, etc. It
62
// is basically impossible to correctly manage the lifetime of this class separately from WorkerMessagingProxy.
63
class WebWorkerClientImpl : public WebCore::WorkerMessagingProxy
60
                          , public WebWorkerBase
64
                          , public WebWorkerBase
61
                          , public WebCommonWorkerClient {
65
                          , public WebCommonWorkerClient {
62
public:
66
public:
Lines 66-122 public: Link Here
66
    // WebCore::WorkerContextProxy methods:
70
    // WebCore::WorkerContextProxy methods:
67
    // These are called on the thread that created the worker.  In the renderer
71
    // These are called on the thread that created the worker.  In the renderer
68
    // process, this will be the main WebKit thread.
72
    // process, this will be the main WebKit thread.
69
    virtual void startWorkerContext(const WebCore::KURL&,
70
                                    const WTF::String&,
71
                                    const WTF::String&,
72
                                    WebCore::WorkerThreadStartMode) OVERRIDE;
73
    virtual void terminateWorkerContext() OVERRIDE;
73
    virtual void terminateWorkerContext() OVERRIDE;
74
    virtual void postMessageToWorkerContext(
74
75
        PassRefPtr<WebCore::SerializedScriptValue> message,
75
    // WebCore::WorkerLoaderProxy methods
76
        PassOwnPtr<WebCore::MessagePortChannelArray> channels) OVERRIDE;
76
    virtual WebWorkerBase* toWebWorkerBase() OVERRIDE;
77
    virtual bool hasPendingActivity() const OVERRIDE;
77
78
    virtual void workerObjectDestroyed() OVERRIDE;
78
    // WebWorkerBase methods:
79
79
    virtual WebCore::WorkerLoaderProxy* workerLoaderProxy() OVERRIDE { return this; }
80
#if ENABLE(INSPECTOR)
80
    virtual WebCommonWorkerClient* commonClient() OVERRIDE { return this; }
81
    virtual void connectToInspector(WebCore::WorkerContextProxy::PageInspector*) OVERRIDE;
81
    virtual WebView* view() const OVERRIDE;
82
    virtual void disconnectFromInspector() OVERRIDE;
82
83
    virtual void sendMessageToInspector(const String&) OVERRIDE;
83
    // WebCommonWorkerClient methods:
84
    virtual void postMessageToPageInspector(const String&) OVERRIDE;
85
    virtual void updateInspectorStateCookie(const String&) OVERRIDE;
86
#endif
87
    // WebCore::WorkerLoaderProxy methods:
88
    virtual void postTaskToLoader(PassOwnPtr<WebCore::ScriptExecutionContext::Task>) OVERRIDE;
89
    virtual bool postTaskForModeToWorkerContext(PassOwnPtr<WebCore::ScriptExecutionContext::Task>, const String& mode) OVERRIDE;
90
91
    // WebCore::WorkerObjectProxy methods:
92
    virtual void postMessageToWorkerObject(PassRefPtr<WebCore::SerializedScriptValue>, PassOwnPtr<WebCore::MessagePortChannelArray>) OVERRIDE;
93
    virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL) OVERRIDE;
94
95
    virtual void postConsoleMessageToWorkerObject(WebCore::MessageSource, WebCore::MessageLevel,
96
                                                  const String& message, int lineNumber, const String& sourceURL) OVERRIDE;
97
    virtual void confirmMessageFromWorkerObject(bool) OVERRIDE;
98
    virtual void reportPendingActivity(bool) OVERRIDE;
99
    virtual void workerContextClosed() OVERRIDE;
100
    virtual void workerContextDestroyed() OVERRIDE;
101
102
    // WebWorkerClientBase methods:
103
    virtual bool allowDatabase(WebFrame*, const WebString& name, const WebString& displayName, unsigned long estimatedSize) OVERRIDE;
84
    virtual bool allowDatabase(WebFrame*, const WebString& name, const WebString& displayName, unsigned long estimatedSize) OVERRIDE;
104
    virtual bool allowFileSystem();
85
    virtual bool allowFileSystem();
105
    virtual void openFileSystem(WebFileSystem::Type, long long size, bool create,
86
    virtual void openFileSystem(WebFileSystem::Type, long long size, bool create,
106
                                WebFileSystemCallbacks*) OVERRIDE;
87
                                WebFileSystemCallbacks*) OVERRIDE;
107
    virtual bool allowIndexedDB(const WebString& name) OVERRIDE;
88
    virtual bool allowIndexedDB(const WebString& name) OVERRIDE;
108
89
109
    // WebCommentWorkerBase methods:
110
    virtual WebCommonWorkerClient* commonClient() OVERRIDE { return this; }
111
    virtual WebView* view() const OVERRIDE;
112
113
private:
90
private:
114
    WebWorkerClientImpl(WebCore::Worker*, WebFrameImpl*);
91
    WebWorkerClientImpl(WebCore::Worker*, WebFrameImpl*);
115
    virtual ~WebWorkerClientImpl();
92
    virtual ~WebWorkerClientImpl();
116
93
117
    WebCore::WorkerMessagingProxy* m_proxy;
118
    // Guard against context from being destroyed before a worker exits.
119
    RefPtr<WebCore::ScriptExecutionContext> m_scriptExecutionContext;
120
    WebFrameImpl* m_webFrame;
94
    WebFrameImpl* m_webFrame;
121
};
95
};
122
96
(-)a/Source/WebKit/chromium/src/WorkerAsyncFileSystemChromium.cpp (-4 / +2 lines)
Lines 40-46 Link Here
40
#include "NotImplemented.h"
40
#include "NotImplemented.h"
41
#include "WebFileSystemCallbacksImpl.h"
41
#include "WebFileSystemCallbacksImpl.h"
42
#include "WebFileWriter.h"
42
#include "WebFileWriter.h"
43
#include "WebWorkerBase.h"
44
#include "WorkerAsyncFileWriterChromium.h"
43
#include "WorkerAsyncFileWriterChromium.h"
45
#include "WorkerContext.h"
44
#include "WorkerContext.h"
46
#include "WorkerFileSystemCallbacksBridge.h"
45
#include "WorkerFileSystemCallbacksBridge.h"
Lines 62-69 WorkerAsyncFileSystemChromium::WorkerAsyncFileSystemChromium(ScriptExecutionCont Link Here
62
{
61
{
63
    ASSERT(m_scriptExecutionContext->isWorkerContext());
62
    ASSERT(m_scriptExecutionContext->isWorkerContext());
64
63
65
    WorkerLoaderProxy* workerLoaderProxy = &m_workerContext->thread()->workerLoaderProxy();
64
    m_workerLoaderProxy = &m_workerContext->thread()->workerLoaderProxy();
66
    m_worker = static_cast<WebWorkerBase*>(workerLoaderProxy);
67
}
65
}
68
66
69
WorkerAsyncFileSystemChromium::~WorkerAsyncFileSystemChromium()
67
WorkerAsyncFileSystemChromium::~WorkerAsyncFileSystemChromium()
Lines 194-200 PassRefPtr<WorkerFileSystemCallbacksBridge> WorkerAsyncFileSystemChromium::creat Link Here
194
    m_modeForCurrentOperation = fileSystemOperationsMode;
192
    m_modeForCurrentOperation = fileSystemOperationsMode;
195
    m_modeForCurrentOperation.append(String::number(m_workerContext->thread()->runLoop().createUniqueId()));
193
    m_modeForCurrentOperation.append(String::number(m_workerContext->thread()->runLoop().createUniqueId()));
196
194
197
    m_bridgeForCurrentOperation = WorkerFileSystemCallbacksBridge::create(m_worker, m_scriptExecutionContext, new WebKit::WebFileSystemCallbacksImpl(callbacks));
195
    m_bridgeForCurrentOperation = WorkerFileSystemCallbacksBridge::create(m_workerLoaderProxy, m_scriptExecutionContext, new WebKit::WebFileSystemCallbacksImpl(callbacks));
198
    return m_bridgeForCurrentOperation;
196
    return m_bridgeForCurrentOperation;
199
}
197
}
200
198
(-)a/Source/WebKit/chromium/src/WorkerAsyncFileSystemChromium.h (-2 / +2 lines)
Lines 41-47 Link Here
41
namespace WebKit {
41
namespace WebKit {
42
class WebFileSystem;
42
class WebFileSystem;
43
class WebURL;
43
class WebURL;
44
class WebWorkerBase;
45
class WorkerFileSystemCallbacksBridge;
44
class WorkerFileSystemCallbacksBridge;
46
}
45
}
47
46
Lines 50-55 namespace WebCore { Link Here
50
class AsyncFileSystemCallbacks;
49
class AsyncFileSystemCallbacks;
51
class ScriptExecutionContext;
50
class ScriptExecutionContext;
52
class WorkerContext;
51
class WorkerContext;
52
class WorkerLoaderProxy;
53
53
54
class WorkerAsyncFileSystemChromium : public AsyncFileSystemChromium {
54
class WorkerAsyncFileSystemChromium : public AsyncFileSystemChromium {
55
public:
55
public:
Lines 82-88 private: Link Here
82
    PassRefPtr<WebKit::WorkerFileSystemCallbacksBridge> createWorkerFileSystemCallbacksBridge(PassOwnPtr<AsyncFileSystemCallbacks>);
82
    PassRefPtr<WebKit::WorkerFileSystemCallbacksBridge> createWorkerFileSystemCallbacksBridge(PassOwnPtr<AsyncFileSystemCallbacks>);
83
83
84
    ScriptExecutionContext* m_scriptExecutionContext;
84
    ScriptExecutionContext* m_scriptExecutionContext;
85
    WebKit::WebWorkerBase* m_worker;
85
    WorkerLoaderProxy* m_workerLoaderProxy;
86
    WorkerContext* m_workerContext;
86
    WorkerContext* m_workerContext;
87
    RefPtr<WebKit::WorkerFileSystemCallbacksBridge> m_bridgeForCurrentOperation;
87
    RefPtr<WebKit::WorkerFileSystemCallbacksBridge> m_bridgeForCurrentOperation;
88
    String m_modeForCurrentOperation;
88
    String m_modeForCurrentOperation;
(-)a/LayoutTests/ChangeLog (+12 lines)
Lines 1-3 Link Here
1
2013-01-02  Kenneth Russell  <kbr@google.com>
2
3
        [chromium] Creation of dedicated workers (isolates) leaks reference to HTMLDocument
4
        https://bugs.webkit.org/show_bug.cgi?id=105367
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * fast/workers/resources/empty-worker.js: Added.
9
        * fast/workers/resources/worker-document-leak-iframe.html: Added.
10
        * fast/workers/worker-document-leak-expected.txt: Added.
11
        * fast/workers/worker-document-leak.html: Added.
12
1
2013-01-02  Ryosuke Niwa  <rniwa@webkit.org>
13
2013-01-02  Ryosuke Niwa  <rniwa@webkit.org>
2
14
3
        Add a failing test expectation to a test added by r136697.
15
        Add a failing test expectation to a test added by r136697.
(-)a/LayoutTests/fast/workers/resources/empty-worker.js (+2 lines)
Line 0 Link Here
1
postMessage("closing");
2
close();
(-)a/LayoutTests/fast/workers/resources/worker-document-leak-iframe.html (+14 lines)
Line 0 Link Here
1
<!DOCTYPE html>
2
<html>
3
<body>
4
<script src="worker-util.js"></script>
5
<script>
6
var worker = new Worker('empty-worker.js');
7
worker.onmessage = function(event) {
8
    waitUntilWorkerThreadsExit(function() {
9
        parent.postMessage("done", "*");
10
    });
11
};
12
</script>
13
</body>
14
</html>
(-)a/LayoutTests/fast/workers/worker-document-leak-expected.txt (+4 lines)
Line 0 Link Here
1
Verify that creation of a worker does not leak its creating document.
2
3
PASS: did not leak documents during test run
4
(-)a/LayoutTests/fast/workers/worker-document-leak.html (+89 lines)
Line 0 Link Here
1
<!DOCTYPE html>
2
<html>
3
<body>
4
<p>Verify that creation of a worker does not leak its creating document.</p>
5
<div id='console'></div>
6
<script src='resources/worker-util.js'></script>
7
<script>
8
function log(message)
9
{
10
    document.getElementById("console").innerHTML += message + "<br>";
11
}
12
13
if (window.testRunner) {
14
    testRunner.dumpAsText();
15
    testRunner.waitUntilDone();
16
}
17
18
// Set this number as high as possible without introducing timeouts in debug builds.
19
// Reducing it does not require rebaselines.
20
var numIterations = 6;
21
22
var currentIteration = 0;
23
var iframe = null;
24
var numLiveAtStart = 0;
25
var numLiveAtEnd = 0;
26
27
window.onmessage = function(event) {
28
    if (event.data == "done") {
29
        runOneIteration();
30
    }
31
};
32
33
function startTest()
34
{
35
    gc();
36
    if (window.internals && window.internals.numberOfLiveDocuments) {
37
        numLiveAtStart = window.internals.numberOfLiveDocuments();
38
        // Depending on which tests ran before this one in DumpRenderTree,
39
        // their Document instances may not have been fully cleaned up yet.
40
        // When this test is run in isolation, there should be only one
41
        // live document at this point.
42
        runOneIteration();
43
    } else {
44
        log("window.internals.numberOfLiveDocuments not available -- no point in running test");
45
        finishTest();
46
    }
47
}
48
49
function runOneIteration() {
50
    if (currentIteration < numIterations) {
51
        ++currentIteration;
52
53
        var createdIframe = false;
54
        if (!iframe) {
55
            iframe = document.createElement("iframe");
56
            createdIframe = true;
57
        }
58
        iframe.setAttribute("src", "resources/worker-document-leak-iframe.html");
59
        if (createdIframe)
60
            document.body.appendChild(iframe);
61
    } else {
62
        finishTest();
63
    }
64
}
65
66
function finishTest()
67
{
68
    gc();
69
70
    if (window.internals && window.internals.numberOfLiveDocuments) {
71
        numLiveAtEnd = window.internals.numberOfLiveDocuments();
72
        // Under no circumstances should the number of live documents
73
        // at the end be more than 1 greater than the number at the
74
        // beginning (because of the iframe).
75
        if (numLiveAtEnd > numLiveAtStart + 1) {
76
            log("FAIL: leaked documents during test run (started with " + numLiveAtStart + ", ended with " + numLiveAtEnd);
77
        } else {
78
            log("PASS: did not leak documents during test run");
79
        }
80
    }
81
82
    if (window.testRunner)
83
        testRunner.notifyDone();
84
}
85
86
window.onload = startTest;
87
</script>
88
</body>
89
</html>

Return to bug 105367