10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch/*
20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Google Inc. All rights reserved.
30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Redistribution and use in source and binary forms, with or without
50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * modification, are permitted provided that the following conditions are
60bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * met:
70bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
80bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     * Redistributions of source code must retain the above copyright
90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * notice, this list of conditions and the following disclaimer.
100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     * Redistributions in binary form must reproduce the above
110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * copyright notice, this list of conditions and the following disclaimer
120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * in the documentation and/or other materials provided with the
130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * distribution.
140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     * Neither the name of Google Inc. nor the names of its
150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * contributors may be used to endorse or promote products derived from
160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * this software without specific prior written permission.
170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch */
300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "config.h"
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if ENABLE(SHARED_WORKERS)
340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "DefaultSharedWorkerRepository.h"
360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "ActiveDOMObject.h"
38e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "CrossThreadTask.h"
39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Document.h"
4065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "InspectorInstrumentation.h"
41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "MessageEvent.h"
420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "MessagePort.h"
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "NotImplemented.h"
440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "PlatformString.h"
45ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "ScriptCallStack.h"
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SecurityOrigin.h"
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SecurityOriginHash.h"
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SharedWorker.h"
490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SharedWorkerContext.h"
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "SharedWorkerRepository.h"
510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SharedWorkerThread.h"
520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WorkerLoaderProxy.h"
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "WorkerReportingProxy.h"
540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WorkerScriptLoader.h"
550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WorkerScriptLoaderClient.h"
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/HashSet.h>
570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <wtf/Threading.h>
580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochnamespace WebCore {
600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
612bde8e466a4451c7319e3a072d118917957d6554Steve Blockclass SharedWorkerProxy : public ThreadSafeRefCounted<SharedWorkerProxy>, public WorkerLoaderProxy, public WorkerReportingProxy {
620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochpublic:
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    static PassRefPtr<SharedWorkerProxy> create(const String& name, const KURL& url, PassRefPtr<SecurityOrigin> origin) { return adoptRef(new SharedWorkerProxy(name, url, origin)); }
640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void setThread(PassRefPtr<SharedWorkerThread> thread) { m_thread = thread; }
660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SharedWorkerThread* thread() { return m_thread.get(); }
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool isClosing() const { return m_closing; }
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    KURL url() const
69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Don't use m_url.copy() because it isn't a threadsafe method.
71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return KURL(ParsedURLString, m_url.string().threadsafeCopy());
72231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    String name() const { return m_name.threadsafeCopy(); }
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool matches(const String& name, PassRefPtr<SecurityOrigin> origin, const KURL& urlToMatch) const;
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // WorkerLoaderProxy
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    virtual void postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task>);
79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    virtual void postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutionContext::Task>, const String&);
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // WorkerReportingProxy
82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL);
83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    virtual void postConsoleMessageToWorkerObject(MessageSource, MessageType, MessageLevel, const String& message, int lineNumber, const String& sourceURL);
84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void workerContextClosed();
85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void workerContextDestroyed();
860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Updates the list of the worker's documents, per section 4.5 of the WebWorkers spec.
880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void addToWorkerDocuments(ScriptExecutionContext*);
89231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool isInWorkerDocuments(Document* document) { return m_workerDocuments.contains(document); }
91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Removes a detached document from the list of worker's documents. May set the closing flag if this is the last document in the list.
93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void documentDetached(Document*);
94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochprivate:
96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    SharedWorkerProxy(const String& name, const KURL&, PassRefPtr<SecurityOrigin>);
97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void close();
98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    bool m_closing;
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    String m_name;
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    KURL m_url;
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // The thread is freed when the proxy is destroyed, so we need to make sure that the proxy stays around until the SharedWorkerContext exits.
1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<SharedWorkerThread> m_thread;
104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<SecurityOrigin> m_origin;
105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    HashSet<Document*> m_workerDocuments;
106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Ensures exclusive access to the worker documents. Must not grab any other locks (such as the DefaultSharedWorkerRepository lock) while holding this one.
107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Mutex m_workerDocumentsLock;
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch};
1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockSharedWorkerProxy::SharedWorkerProxy(const String& name, const KURL& url, PassRefPtr<SecurityOrigin> origin)
1110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    : m_closing(false)
112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_name(name.crossThreadString())
1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_url(url.copy())
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_origin(origin)
115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // We should be the sole owner of the SecurityOrigin, as we will free it on another thread.
117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(m_origin->hasOneRef());
118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool SharedWorkerProxy::matches(const String& name, PassRefPtr<SecurityOrigin> origin, const KURL& urlToMatch) const
121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If the origins don't match, or the names don't match, then this is not the proxy we are looking for.
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!origin->equal(m_origin.get()))
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If the names are both empty, compares the URLs instead per the Web Workers spec.
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (name.isEmpty() && m_name.isEmpty())
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return urlToMatch == url();
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return name == m_name;
131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
133643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid SharedWorkerProxy::postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task> task)
134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_workerDocumentsLock);
136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (isClosing())
138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If we aren't closing, then we must have at least one document.
141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(m_workerDocuments.size());
142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Just pick an arbitrary active document from the HashSet and pass load requests to it.
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // FIXME: Do we need to deal with the case where the user closes the document mid-load, via a shadow document or some other solution?
145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Document* document = *(m_workerDocuments.begin());
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    document->postTask(task);
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
149643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid SharedWorkerProxy::postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode)
150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (isClosing())
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(m_thread);
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_thread->runLoop().postTaskForMode(task, mode);
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void postExceptionTask(ScriptExecutionContext* context, const String& errorMessage, int lineNumber, const String& sourceURL)
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
159ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    context->reportException(errorMessage, lineNumber, sourceURL, 0);
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SharedWorkerProxy::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL)
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_workerDocumentsLock);
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (HashSet<Document*>::iterator iter = m_workerDocuments.begin(); iter != m_workerDocuments.end(); ++iter)
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        (*iter)->postTask(createCallbackTask(&postExceptionTask, errorMessage, lineNumber, sourceURL));
167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic void postConsoleMessageTask(ScriptExecutionContext* document, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
171ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    document->addMessage(source, type, level, message, lineNumber, sourceURL, 0);
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid SharedWorkerProxy::postConsoleMessageToWorkerObject(MessageSource source, MessageType type, MessageLevel level, const String& message, int lineNumber, const String& sourceURL)
175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_workerDocumentsLock);
177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (HashSet<Document*>::iterator iter = m_workerDocuments.begin(); iter != m_workerDocuments.end(); ++iter)
178dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        (*iter)->postTask(createCallbackTask(&postConsoleMessageTask, source, type, level, message, lineNumber, sourceURL));
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SharedWorkerProxy::workerContextClosed()
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
183231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (isClosing())
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    close();
186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SharedWorkerProxy::workerContextDestroyed()
1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // The proxy may be freed by this call, so do not reference it any further.
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DefaultSharedWorkerRepository::instance().removeProxy(this);
1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SharedWorkerProxy::addToWorkerDocuments(ScriptExecutionContext* context)
1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Nested workers are not yet supported, so passed-in context should always be a Document.
1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(context->isDocument());
198231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(!isClosing());
199231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_workerDocumentsLock);
200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Document* document = static_cast<Document*>(context);
201231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_workerDocuments.add(document);
202231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
203231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
204231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SharedWorkerProxy::documentDetached(Document* document)
205231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
206231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (isClosing())
207231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
208231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Remove the document from our set (if it's there) and if that was the last document in the set, mark the proxy as closed.
209231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_workerDocumentsLock);
210231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_workerDocuments.remove(document);
211231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_workerDocuments.size())
212231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        close();
213231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
214231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
215231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SharedWorkerProxy::close()
216231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
217231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(!isClosing());
218231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_closing = true;
219231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Stop the worker thread - the proxy will stay around until we get workerThreadExited() notification.
220231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_thread)
221231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_thread->stop();
2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass SharedWorkerConnectTask : public ScriptExecutionContext::Task {
2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochpublic:
226643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static PassOwnPtr<SharedWorkerConnectTask> create(PassOwnPtr<MessagePortChannel> channel)
2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
228643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return new SharedWorkerConnectTask(channel);
2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochprivate:
2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SharedWorkerConnectTask(PassOwnPtr<MessagePortChannel> channel)
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        : m_channel(channel)
2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    virtual void performTask(ScriptExecutionContext* scriptContext)
2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        RefPtr<MessagePort> port = MessagePort::create(*scriptContext);
2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        port->entangle(m_channel.release());
2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(scriptContext->isWorkerContext());
2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        WorkerContext* workerContext = static_cast<WorkerContext*>(scriptContext);
243231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Since close() stops the thread event loop, this should not ever get called while closing.
244231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(!workerContext->isClosing());
2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(workerContext->isSharedWorkerContext());
246231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        workerContext->toSharedWorkerContext()->dispatchEvent(createConnectEvent(port));
2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    OwnPtr<MessagePortChannel> m_channel;
2500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch};
2510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Loads the script on behalf of a worker.
2535e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Blockclass SharedWorkerScriptLoader : public RefCounted<SharedWorkerScriptLoader>, private WorkerScriptLoaderClient {
2540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochpublic:
2550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SharedWorkerScriptLoader(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortChannel>, PassRefPtr<SharedWorkerProxy>);
2560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void load(const KURL&);
2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochprivate:
2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // WorkerScriptLoaderClient callback
2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    virtual void notifyFinished();
2610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<SharedWorker> m_worker;
2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    OwnPtr<MessagePortChannel> m_port;
2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<SharedWorkerProxy> m_proxy;
2650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    OwnPtr<WorkerScriptLoader> m_scriptLoader;
2660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch};
2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochSharedWorkerScriptLoader::SharedWorkerScriptLoader(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, PassRefPtr<SharedWorkerProxy> proxy)
2695e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    : m_worker(worker)
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_port(port)
2710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_proxy(proxy)
2720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SharedWorkerScriptLoader::load(const KURL& url)
2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Mark this object as active for the duration of the load.
27821939df44de1705786c545cd1bf519d47250322dBen Murdoch    m_scriptLoader = new WorkerScriptLoader(ResourceRequestBase::TargetIsSharedWorker);
2795e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    m_scriptLoader->loadAsynchronously(m_worker->scriptExecutionContext(), url, DenyCrossOriginRequests, this);
2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2815e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // Stay alive (and keep the SharedWorker and JS wrapper alive) until the load finishes.
2825e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    this->ref();
283231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_worker->setPendingActivity(m_worker.get());
2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SharedWorkerScriptLoader::notifyFinished()
2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2885e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // FIXME: This method is not guaranteed to be invoked if we are loading from WorkerContext (see comment for WorkerScriptLoaderClient::notifyFinished()).
2895e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // We need to address this before supporting nested workers.
2905e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Hand off the just-loaded code to the repository to start up the worker thread.
2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_scriptLoader->failed())
293231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_worker->dispatchEvent(Event::create(eventNames().errorEvent, false, true));
294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else {
29565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        InspectorInstrumentation::scriptImported(m_worker->scriptExecutionContext(), m_scriptLoader->identifier(), m_scriptLoader->script());
2965e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        DefaultSharedWorkerRepository::instance().workerScriptLoaded(*m_proxy, m_worker->scriptExecutionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script(), m_port.release());
297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
298231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_worker->unsetPendingActivity(m_worker.get());
2995e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    this->deref(); // This frees this object - must be the last action in this function.
3000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochDefaultSharedWorkerRepository& DefaultSharedWorkerRepository::instance()
3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    AtomicallyInitializedStatic(DefaultSharedWorkerRepository*, instance = new DefaultSharedWorkerRepository);
3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return *instance;
3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid DefaultSharedWorkerRepository::workerScriptLoaded(SharedWorkerProxy& proxy, const String& userAgent, const String& workerScript, PassOwnPtr<MessagePortChannel> port)
3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    MutexLocker lock(m_lock);
311231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (proxy.isClosing())
3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
3130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Another loader may have already started up a thread for this proxy - if so, just send a connect to the pre-existing thread.
3150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!proxy.thread()) {
316231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        RefPtr<SharedWorkerThread> thread = SharedWorkerThread::create(proxy.name(), proxy.url(), userAgent, workerScript, proxy, proxy);
3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        proxy.setThread(thread);
3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        thread->start();
3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    proxy.thread()->runLoop().postTask(SharedWorkerConnectTask::create(port));
3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
323231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool SharedWorkerRepository::isAvailable()
324231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
325231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // SharedWorkers are enabled on the default WebKit platform.
326231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
327231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
328231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SharedWorkerRepository::connect(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, const KURL& url, const String& name, ExceptionCode& ec)
3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DefaultSharedWorkerRepository::instance().connectToWorker(worker, port, url, name, ec);
3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
334231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SharedWorkerRepository::documentDetached(Document* document)
335231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
336231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DefaultSharedWorkerRepository::instance().documentDetached(document);
337231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
338231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
339231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool SharedWorkerRepository::hasSharedWorkers(Document* document)
340231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
341231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return DefaultSharedWorkerRepository::instance().hasSharedWorkers(document);
342231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
343231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
344231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool DefaultSharedWorkerRepository::hasSharedWorkers(Document* document)
345231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
346231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_lock);
347231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (unsigned i = 0; i < m_proxies.size(); i++) {
348231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (m_proxies[i]->isInWorkerDocuments(document))
349231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return true;
350231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
351231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return false;
352231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
353231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
354231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DefaultSharedWorkerRepository::removeProxy(SharedWorkerProxy* proxy)
355231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
356231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_lock);
357231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (unsigned i = 0; i < m_proxies.size(); i++) {
358231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (proxy == m_proxies[i].get()) {
359231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_proxies.remove(i);
360231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return;
361231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
362231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
363231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
364231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
365231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DefaultSharedWorkerRepository::documentDetached(Document* document)
366231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
367231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    MutexLocker lock(m_lock);
368231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (unsigned i = 0; i < m_proxies.size(); i++)
369231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_proxies[i]->documentDetached(document);
370231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
371231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid DefaultSharedWorkerRepository::connectToWorker(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, const KURL& url, const String& name, ExceptionCode& ec)
3730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    MutexLocker lock(m_lock);
3750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(worker->scriptExecutionContext()->securityOrigin()->canAccess(SecurityOrigin::create(url).get()));
3760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Fetch a proxy corresponding to this SharedWorker.
3770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<SharedWorkerProxy> proxy = getProxy(name, url);
3780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    proxy->addToWorkerDocuments(worker->scriptExecutionContext());
3790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (proxy->url() != url) {
3800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Proxy already existed under alternate URL - return an error.
3810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ec = URL_MISMATCH_ERR;
3820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
3830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If proxy is already running, just connect to it - otherwise, kick off a loader to load the script.
3850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (proxy->thread())
3860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        proxy->thread()->runLoop().postTask(SharedWorkerConnectTask::create(port));
3870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    else {
388e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        RefPtr<SharedWorkerScriptLoader> loader = adoptRef(new SharedWorkerScriptLoader(worker, port, proxy.release()));
3890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        loader->load(url);
3900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Creates a new SharedWorkerProxy or returns an existing one from the repository. Must only be called while the repository mutex is held.
3940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<SharedWorkerProxy> DefaultSharedWorkerRepository::getProxy(const String& name, const KURL& url)
3950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Look for an existing worker, and create one if it doesn't exist.
397231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Items in the cache are freed on another thread, so do a threadsafe copy of the URL before creating the origin,
398231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // to make sure no references to external strings linger.
399231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<SecurityOrigin> origin = SecurityOrigin::create(KURL(ParsedURLString, url.string().threadsafeCopy()));
400231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    for (unsigned i = 0; i < m_proxies.size(); i++) {
401231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!m_proxies[i]->isClosing() && m_proxies[i]->matches(name, origin, url))
402231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return m_proxies[i];
4030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
404231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Proxy is not in the repository currently - create a new one.
405231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<SharedWorkerProxy> proxy = SharedWorkerProxy::create(name, url, origin.release());
406231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_proxies.append(proxy);
407231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return proxy.release();
4080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
4090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochDefaultSharedWorkerRepository::DefaultSharedWorkerRepository()
4110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
4120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
4130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochDefaultSharedWorkerRepository::~DefaultSharedWorkerRepository()
4150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
4160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
4170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} // namespace WebCore
4190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif // ENABLE(SHARED_WORKERS)
421