SharedWorkerRepository.cpp [plain text]
#include "config.h"
#if ENABLE(SHARED_WORKERS)
#include "SharedWorkerRepository.h"
#include "Event.h"
#include "EventNames.h"
#include "InspectorController.h"
#include "MessagePortChannel.h"
#include "PlatformMessagePortChannel.h"
#include "ScriptExecutionContext.h"
#include "SharedWorker.h"
#include "WebFrameClient.h"
#include "WebFrameImpl.h"
#include "WebKit.h"
#include "WebKitClient.h"
#include "WebMessagePortChannel.h"
#include "WebSharedWorker.h"
#include "WebSharedWorkerRepository.h"
#include "WebString.h"
#include "WebURL.h"
#include "WorkerScriptLoader.h"
#include "WorkerScriptLoaderClient.h"
namespace WebCore {
class Document;
using WebKit::WebFrameImpl;
using WebKit::WebMessagePortChannel;
using WebKit::WebSharedWorker;
using WebKit::WebSharedWorkerRepository;
class SharedWorkerScriptLoader : private WorkerScriptLoaderClient, private WebSharedWorker::ConnectListener {
public:
SharedWorkerScriptLoader(PassRefPtr<SharedWorker> worker, const KURL& url, const String& name, PassOwnPtr<MessagePortChannel> port, PassOwnPtr<WebSharedWorker> webWorker)
: m_worker(worker)
, m_url(url)
, m_name(name)
, m_webWorker(webWorker)
, m_port(port)
, m_scriptLoader(ResourceRequestBase::TargetIsSharedWorker)
, m_loading(false)
{
}
~SharedWorkerScriptLoader();
void load();
static void stopAllLoadersForContext(ScriptExecutionContext*);
private:
virtual void notifyFinished();
virtual void connected();
const ScriptExecutionContext* loadingContext() { return m_worker->scriptExecutionContext(); }
void sendConnect();
RefPtr<SharedWorker> m_worker;
KURL m_url;
String m_name;
OwnPtr<WebSharedWorker> m_webWorker;
OwnPtr<MessagePortChannel> m_port;
WorkerScriptLoader m_scriptLoader;
bool m_loading;
};
static Vector<SharedWorkerScriptLoader*>& pendingLoaders()
{
AtomicallyInitializedStatic(Vector<SharedWorkerScriptLoader*>&, loaders = *new Vector<SharedWorkerScriptLoader*>);
return loaders;
}
void SharedWorkerScriptLoader::stopAllLoadersForContext(ScriptExecutionContext* context)
{
Vector<SharedWorkerScriptLoader*>& loaders = pendingLoaders();
for (unsigned i = 0; i < loaders.size(); ) {
SharedWorkerScriptLoader* loader = loaders[i];
if (context == loader->loadingContext()) {
loaders.remove(i);
delete loader;
} else
i++;
}
}
SharedWorkerScriptLoader::~SharedWorkerScriptLoader()
{
if (m_loading)
m_worker->unsetPendingActivity(m_worker.get());
}
void SharedWorkerScriptLoader::load()
{
ASSERT(!m_loading);
if (m_webWorker->isStarted())
sendConnect();
else {
m_scriptLoader.loadAsynchronously(m_worker->scriptExecutionContext(), m_url, DenyCrossOriginRequests, this);
m_worker->setPendingActivity(m_worker.get());
m_loading = true;
}
}
static WebMessagePortChannel* getWebPort(PassOwnPtr<MessagePortChannel> port)
{
PlatformMessagePortChannel* platformChannel = port->channel();
WebMessagePortChannel* webPort = platformChannel->webChannelRelease();
webPort->setClient(0);
return webPort;
}
void SharedWorkerScriptLoader::notifyFinished()
{
if (m_scriptLoader.failed()) {
m_worker->dispatchEvent(Event::create(eventNames().errorEvent, false, true));
delete this;
} else {
#if ENABLE(INSPECTOR)
if (InspectorController* inspector = m_worker->scriptExecutionContext()->inspectorController())
inspector->scriptImported(m_scriptLoader.identifier(), m_scriptLoader.script());
#endif
m_webWorker->startWorkerContext(m_url, m_name, m_worker->scriptExecutionContext()->userAgent(m_url), m_scriptLoader.script());
sendConnect();
}
}
void SharedWorkerScriptLoader::sendConnect()
{
m_webWorker->connect(getWebPort(m_port.release()), this);
}
void SharedWorkerScriptLoader::connected()
{
delete this;
}
bool SharedWorkerRepository::isAvailable()
{
return WebKit::webKitClient()->sharedWorkerRepository();
}
static WebSharedWorkerRepository::DocumentID getId(void* document)
{
ASSERT(document);
return reinterpret_cast<WebSharedWorkerRepository::DocumentID>(document);
}
void SharedWorkerRepository::connect(PassRefPtr<SharedWorker> worker, PassOwnPtr<MessagePortChannel> port, const KURL& url, const String& name, ExceptionCode& ec)
{
ASSERT(WebKit::webKitClient()->sharedWorkerRepository());
ASSERT(worker->scriptExecutionContext()->isDocument());
Document* document = static_cast<Document*>(worker->scriptExecutionContext());
WebFrameImpl* webFrame = WebFrameImpl::fromFrame(document->frame());
OwnPtr<WebSharedWorker> webWorker;
webWorker = webFrame->client()->createSharedWorker(webFrame, url, name, getId(document));
if (!webWorker) {
ec = URL_MISMATCH_ERR;
return;
}
WebKit::webKitClient()->sharedWorkerRepository()->addSharedWorker(
webWorker.get(), getId(document));
SharedWorkerScriptLoader* loader = new SharedWorkerScriptLoader(worker, url, name, port.release(), webWorker.release());
loader->load();
}
void SharedWorkerRepository::documentDetached(Document* document)
{
WebSharedWorkerRepository* repo = WebKit::webKitClient()->sharedWorkerRepository();
if (repo)
repo->documentDetached(getId(document));
SharedWorkerScriptLoader::stopAllLoadersForContext(document);
}
bool SharedWorkerRepository::hasSharedWorkers(Document* document)
{
WebSharedWorkerRepository* repo = WebKit::webKitClient()->sharedWorkerRepository();
return repo && repo->hasSharedWorkers(getId(document));
}
}
#endif // ENABLE(SHARED_WORKERS)