diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/dom/ScriptExecutionContext.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/dom/ScriptExecutionContext.cpp')
-rw-r--r-- | Source/WebCore/dom/ScriptExecutionContext.cpp | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/Source/WebCore/dom/ScriptExecutionContext.cpp b/Source/WebCore/dom/ScriptExecutionContext.cpp new file mode 100644 index 0000000..bfda17b --- /dev/null +++ b/Source/WebCore/dom/ScriptExecutionContext.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "config.h" +#include "ScriptExecutionContext.h" + +#include "ActiveDOMObject.h" +#include "Blob.h" +#include "BlobURL.h" +#include "Database.h" +#include "DatabaseTask.h" +#include "DatabaseThread.h" +#include "FileThread.h" +#include "MessagePort.h" +#include "SecurityOrigin.h" +#include "ThreadableBlobRegistry.h" +#include "WorkerContext.h" +#include "WorkerThread.h" +#include <wtf/MainThread.h> +#include <wtf/PassRefPtr.h> + +#if USE(JSC) +#include "JSDOMWindow.h" +#endif + +namespace WebCore { + +class ProcessMessagesSoonTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<ProcessMessagesSoonTask> create() + { + return new ProcessMessagesSoonTask; + } + + virtual void performTask(ScriptExecutionContext* context) + { + context->dispatchMessagePortEvents(); + } +}; + +ScriptExecutionContext::ScriptExecutionContext() +#if ENABLE(DATABASE) + : m_hasOpenDatabases(false) +#endif +{ +} + +ScriptExecutionContext::~ScriptExecutionContext() +{ + HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end(); + for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) { + ASSERT(iter->first->scriptExecutionContext() == this); + iter->first->contextDestroyed(); + } + + HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end(); + for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) { + ASSERT((*iter)->scriptExecutionContext() == this); + (*iter)->contextDestroyed(); + } +#if ENABLE(DATABASE) + if (m_databaseThread) { + ASSERT(m_databaseThread->terminationRequested()); + m_databaseThread = 0; + } +#endif +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) + if (m_fileThread) { + m_fileThread->stop(); + m_fileThread = 0; + } +#endif + +#if ENABLE(BLOB) + HashSet<String>::iterator publicBlobURLsEnd = m_publicBlobURLs.end(); + for (HashSet<String>::iterator iter = m_publicBlobURLs.begin(); iter != publicBlobURLsEnd; ++iter) + ThreadableBlobRegistry::unregisterBlobURL(KURL(ParsedURLString, *iter)); +#endif +} + +#if ENABLE(DATABASE) + +DatabaseThread* ScriptExecutionContext::databaseThread() +{ + if (!m_databaseThread && !m_hasOpenDatabases) { + // Create the database thread on first request - but not if at least one database was already opened, + // because in that case we already had a database thread and terminated it and should not create another. + m_databaseThread = DatabaseThread::create(); + if (!m_databaseThread->start()) + m_databaseThread = 0; + } + + return m_databaseThread.get(); +} + +void ScriptExecutionContext::stopDatabases(DatabaseTaskSynchronizer* cleanupSync) +{ + ASSERT(isContextThread()); + if (m_databaseThread) + m_databaseThread->requestTermination(cleanupSync); + else if (cleanupSync) + cleanupSync->taskCompleted(); +} + +#endif + +void ScriptExecutionContext::processMessagePortMessagesSoon() +{ + postTask(ProcessMessagesSoonTask::create()); +} + +void ScriptExecutionContext::dispatchMessagePortEvents() +{ + RefPtr<ScriptExecutionContext> protect(this); + + // Make a frozen copy. + Vector<MessagePort*> ports; + copyToVector(m_messagePorts, ports); + + unsigned portCount = ports.size(); + for (unsigned i = 0; i < portCount; ++i) { + MessagePort* port = ports[i]; + // The port may be destroyed, and another one created at the same address, but this is safe, as the worst that can happen + // as a result is that dispatchMessages() will be called needlessly. + if (m_messagePorts.contains(port) && port->started()) + port->dispatchMessages(); + } +} + +void ScriptExecutionContext::createdMessagePort(MessagePort* port) +{ + ASSERT(port); +#if ENABLE(WORKERS) + ASSERT((isDocument() && isMainThread()) + || (isWorkerContext() && currentThread() == static_cast<WorkerContext*>(this)->thread()->threadID())); +#endif + + m_messagePorts.add(port); +} + +void ScriptExecutionContext::destroyedMessagePort(MessagePort* port) +{ + ASSERT(port); +#if ENABLE(WORKERS) + ASSERT((isDocument() && isMainThread()) + || (isWorkerContext() && currentThread() == static_cast<WorkerContext*>(this)->thread()->threadID())); +#endif + + m_messagePorts.remove(port); +} + +bool ScriptExecutionContext::canSuspendActiveDOMObjects() +{ + // No protection against m_activeDOMObjects changing during iteration: canSuspend() shouldn't execute arbitrary JS. + HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end(); + for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) { + ASSERT(iter->first->scriptExecutionContext() == this); + if (!iter->first->canSuspend()) + return false; + } + return true; +} + +void ScriptExecutionContext::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why) +{ + // No protection against m_activeDOMObjects changing during iteration: suspend() shouldn't execute arbitrary JS. + HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end(); + for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) { + ASSERT(iter->first->scriptExecutionContext() == this); + iter->first->suspend(why); + } +} + +void ScriptExecutionContext::resumeActiveDOMObjects() +{ + // No protection against m_activeDOMObjects changing during iteration: resume() shouldn't execute arbitrary JS. + HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end(); + for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) { + ASSERT(iter->first->scriptExecutionContext() == this); + iter->first->resume(); + } +} + +void ScriptExecutionContext::stopActiveDOMObjects() +{ + // No protection against m_activeDOMObjects changing during iteration: stop() shouldn't execute arbitrary JS. + HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end(); + for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) { + ASSERT(iter->first->scriptExecutionContext() == this); + iter->first->stop(); + } + + // Also close MessagePorts. If they were ActiveDOMObjects (they could be) then they could be stopped instead. + closeMessagePorts(); +} + +void ScriptExecutionContext::createdActiveDOMObject(ActiveDOMObject* object, void* upcastPointer) +{ + ASSERT(object); + ASSERT(upcastPointer); + m_activeDOMObjects.add(object, upcastPointer); +} + +void ScriptExecutionContext::destroyedActiveDOMObject(ActiveDOMObject* object) +{ + ASSERT(object); + m_activeDOMObjects.remove(object); +} + +void ScriptExecutionContext::closeMessagePorts() { + HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end(); + for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) { + ASSERT((*iter)->scriptExecutionContext() == this); + (*iter)->close(); + } +} + +void ScriptExecutionContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin) +{ + m_securityOrigin = securityOrigin; +} + +void ScriptExecutionContext::addTimeout(int timeoutId, DOMTimer* timer) +{ + ASSERT(!m_timeouts.contains(timeoutId)); + m_timeouts.set(timeoutId, timer); +} + +void ScriptExecutionContext::removeTimeout(int timeoutId) +{ + m_timeouts.remove(timeoutId); +} + +DOMTimer* ScriptExecutionContext::findTimeout(int timeoutId) +{ + return m_timeouts.get(timeoutId); +} + +#if ENABLE(BLOB) +KURL ScriptExecutionContext::createPublicBlobURL(Blob* blob) +{ + if (!blob) + return KURL(); + KURL publicURL = BlobURL::createPublicURL(securityOrigin()); + ThreadableBlobRegistry::registerBlobURL(publicURL, blob->url()); + m_publicBlobURLs.add(publicURL.string()); + return publicURL; +} + +void ScriptExecutionContext::revokePublicBlobURL(const KURL& url) +{ + if (m_publicBlobURLs.contains(url.string())) { + ThreadableBlobRegistry::unregisterBlobURL(url); + m_publicBlobURLs.remove(url.string()); + } +} +#endif + +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) +FileThread* ScriptExecutionContext::fileThread() +{ + if (!m_fileThread) { + m_fileThread = FileThread::create(); + if (!m_fileThread->start()) + m_fileThread = 0; + } + return m_fileThread.get(); +} +#endif + +ScriptExecutionContext::Task::~Task() +{ +} + +#if USE(JSC) +JSC::JSGlobalData* ScriptExecutionContext::globalData() +{ + if (isDocument()) + return JSDOMWindow::commonJSGlobalData(); + +#if ENABLE(WORKERS) + if (isWorkerContext()) + return static_cast<WorkerContext*>(this)->script()->globalData(); +#endif + + ASSERT_NOT_REACHED(); + return 0; +} +#endif + +} // namespace WebCore |