| Index: Source/core/dom/ScriptExecutionContext.cpp
|
| diff --git a/Source/core/dom/ScriptExecutionContext.cpp b/Source/core/dom/ScriptExecutionContext.cpp
|
| index f0128f58406ad670e6d75e083851523d2355ee94..2f621cd99d155f96ea0a4a61b6f8fab5c8c5b3f6 100644
|
| --- a/Source/core/dom/ScriptExecutionContext.cpp
|
| +++ b/Source/core/dom/ScriptExecutionContext.cpp
|
| @@ -28,7 +28,6 @@
|
| #include "config.h"
|
| #include "core/dom/ScriptExecutionContext.h"
|
|
|
| -#include "core/dom/ContextLifecycleNotifier.h"
|
| #include "core/dom/ErrorEvent.h"
|
| #include "core/dom/EventTarget.h"
|
| #include "core/dom/MessagePort.h"
|
| @@ -88,7 +87,9 @@ void ScriptExecutionContext::AddConsoleMessageTask::performTask(ScriptExecutionC
|
| }
|
|
|
| ScriptExecutionContext::ScriptExecutionContext()
|
| - : m_circularSequentialID(0)
|
| + : m_iteratingActiveDOMObjects(false)
|
| + , m_inDestructor(false)
|
| + , m_circularSequentialID(0)
|
| , m_inDispatchErrorEvent(false)
|
| , m_activeDOMObjectsAreSuspended(false)
|
| , m_reasonForSuspendingActiveDOMObjects(static_cast<ActiveDOMObject::ReasonForSuspension>(-1))
|
| @@ -98,6 +99,14 @@ ScriptExecutionContext::ScriptExecutionContext()
|
|
|
| ScriptExecutionContext::~ScriptExecutionContext()
|
| {
|
| + m_inDestructor = true;
|
| + for (HashSet<ContextDestructionObserver*>::iterator iter = m_destructionObservers.begin(); iter != m_destructionObservers.end(); iter = m_destructionObservers.begin()) {
|
| + ContextDestructionObserver* observer = *iter;
|
| + m_destructionObservers.remove(observer);
|
| + ASSERT(observer->scriptExecutionContext() == this);
|
| + observer->contextDestroyed();
|
| + }
|
| +
|
| HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end();
|
| for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) {
|
| ASSERT((*iter)->scriptExecutionContext() == this);
|
| @@ -148,26 +157,32 @@ void ScriptExecutionContext::destroyedMessagePort(MessagePort* port)
|
|
|
| bool ScriptExecutionContext::canSuspendActiveDOMObjects()
|
| {
|
| - return lifecycleNotifier()->canSuspendActiveDOMObjects();
|
| -}
|
| -
|
| -bool ScriptExecutionContext::hasPendingActivity()
|
| -{
|
| - if (lifecycleNotifier()->hasPendingActivity())
|
| - return true;
|
| -
|
| - HashSet<MessagePort*>::const_iterator messagePortsEnd = m_messagePorts.end();
|
| - for (HashSet<MessagePort*>::const_iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) {
|
| - if ((*iter)->hasPendingActivity())
|
| - return true;
|
| + // No protection against m_activeDOMObjects changing during iteration: canSuspend() shouldn't execute arbitrary JS.
|
| + m_iteratingActiveDOMObjects = true;
|
| + ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
|
| + for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
|
| + ASSERT((*iter)->scriptExecutionContext() == this);
|
| + ASSERT((*iter)->suspendIfNeededCalled());
|
| + if (!(*iter)->canSuspend()) {
|
| + m_iteratingActiveDOMObjects = false;
|
| + return false;
|
| + }
|
| }
|
| -
|
| - return false;
|
| + m_iteratingActiveDOMObjects = false;
|
| + return true;
|
| }
|
|
|
| void ScriptExecutionContext::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
|
| {
|
| - lifecycleNotifier()->notifySuspendingActiveDOMObjects(why);
|
| + // No protection against m_activeDOMObjects changing during iteration: suspend() shouldn't execute arbitrary JS.
|
| + m_iteratingActiveDOMObjects = true;
|
| + ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
|
| + for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
|
| + ASSERT((*iter)->scriptExecutionContext() == this);
|
| + ASSERT((*iter)->suspendIfNeededCalled());
|
| + (*iter)->suspend(why);
|
| + }
|
| + m_iteratingActiveDOMObjects = false;
|
| m_activeDOMObjectsAreSuspended = true;
|
| m_reasonForSuspendingActiveDOMObjects = why;
|
| }
|
| @@ -175,33 +190,70 @@ void ScriptExecutionContext::suspendActiveDOMObjects(ActiveDOMObject::ReasonForS
|
| void ScriptExecutionContext::resumeActiveDOMObjects()
|
| {
|
| m_activeDOMObjectsAreSuspended = false;
|
| - lifecycleNotifier()->notifyResumingActiveDOMObjects();
|
| + // No protection against m_activeDOMObjects changing during iteration: resume() shouldn't execute arbitrary JS.
|
| + m_iteratingActiveDOMObjects = true;
|
| + ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
|
| + for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
|
| + ASSERT((*iter)->scriptExecutionContext() == this);
|
| + ASSERT((*iter)->suspendIfNeededCalled());
|
| + (*iter)->resume();
|
| + }
|
| + m_iteratingActiveDOMObjects = false;
|
| }
|
|
|
| void ScriptExecutionContext::stopActiveDOMObjects()
|
| {
|
| m_activeDOMObjectsAreStopped = true;
|
| - lifecycleNotifier()->notifyStoppingActiveDOMObjects();
|
| + // No protection against m_activeDOMObjects changing during iteration: stop() shouldn't execute arbitrary JS.
|
| + m_iteratingActiveDOMObjects = true;
|
| + ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
|
| + for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
|
| + ASSERT((*iter)->scriptExecutionContext() == this);
|
| + ASSERT((*iter)->suspendIfNeededCalled());
|
| + (*iter)->stop();
|
| + }
|
| + m_iteratingActiveDOMObjects = false;
|
| +
|
| // Also close MessagePorts. If they were ActiveDOMObjects (they could be) then they could be stopped instead.
|
| closeMessagePorts();
|
| }
|
|
|
| void ScriptExecutionContext::suspendActiveDOMObjectIfNeeded(ActiveDOMObject* object)
|
| {
|
| - ASSERT(lifecycleNotifier()->contains(object));
|
| + ASSERT(m_activeDOMObjects.contains(object));
|
| // Ensure all ActiveDOMObjects are suspended also newly created ones.
|
| if (m_activeDOMObjectsAreSuspended)
|
| object->suspend(m_reasonForSuspendingActiveDOMObjects);
|
| }
|
|
|
| -void ScriptExecutionContext::wasObservedBy(ContextDestructionObserver* observer, ContextDestructionObserver::Type as)
|
| +void ScriptExecutionContext::didCreateActiveDOMObject(ActiveDOMObject* object)
|
| +{
|
| + ASSERT(object);
|
| + ASSERT(!m_inDestructor);
|
| + if (m_iteratingActiveDOMObjects)
|
| + CRASH();
|
| + m_activeDOMObjects.add(object);
|
| +}
|
| +
|
| +void ScriptExecutionContext::willDestroyActiveDOMObject(ActiveDOMObject* object)
|
| +{
|
| + ASSERT(object);
|
| + if (m_iteratingActiveDOMObjects)
|
| + CRASH();
|
| + m_activeDOMObjects.remove(object);
|
| +}
|
| +
|
| +void ScriptExecutionContext::didCreateDestructionObserver(ContextDestructionObserver* observer)
|
| {
|
| - lifecycleNotifier()->addObserver(observer, as);
|
| + ASSERT(observer);
|
| + ASSERT(!m_inDestructor);
|
| + m_destructionObservers.add(observer);
|
| }
|
|
|
| -void ScriptExecutionContext::wasUnobservedBy(ContextDestructionObserver* observer, ContextDestructionObserver::Type as)
|
| +void ScriptExecutionContext::willDestroyDestructionObserver(ContextDestructionObserver* observer)
|
| {
|
| - lifecycleNotifier()->removeObserver(observer, as);
|
| + ASSERT(observer);
|
| + m_destructionObservers.remove(observer);
|
| }
|
|
|
| void ScriptExecutionContext::closeMessagePorts() {
|
| @@ -298,27 +350,19 @@ double ScriptExecutionContext::timerAlignmentInterval() const
|
| return DOMTimer::visiblePageAlignmentInterval();
|
| }
|
|
|
| -ContextLifecycleNotifier* ScriptExecutionContext::lifecycleNotifier()
|
| -{
|
| - if (!m_lifecycleNotifier)
|
| - m_lifecycleNotifier = const_cast<ScriptExecutionContext*>(this)->createLifecycleNotifier();
|
| - return m_lifecycleNotifier.get();
|
| -}
|
| -
|
| -PassOwnPtr<ContextLifecycleNotifier> ScriptExecutionContext::createLifecycleNotifier()
|
| -{
|
| - return ContextLifecycleNotifier::create(this);
|
| -}
|
| -
|
| void ScriptExecutionContext::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
| {
|
| MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
|
| SecurityContext::reportMemoryUsage(memoryObjectInfo);
|
| info.addMember(m_messagePorts, "messagePorts");
|
| - info.addMember(m_lifecycleNotifier, "lifecycleObserver");
|
| + info.addMember(m_destructionObservers, "destructionObservers");
|
| + info.addMember(m_activeDOMObjects, "activeDOMObjects");
|
| info.addMember(m_timeouts, "timeouts");
|
| info.addMember(m_pendingExceptions, "pendingExceptions");
|
| info.addMember(m_publicURLManager, "publicURLManager");
|
| + ActiveDOMObjectsSet::iterator activeObjectsEnd = m_activeDOMObjects.end();
|
| + for (ActiveDOMObjectsSet::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter)
|
| + info.addMember(*iter, "activeDOMObject", WTF::RetainingPointer);
|
| }
|
|
|
| ScriptExecutionContext::Task::~Task()
|
| @@ -327,6 +371,7 @@ ScriptExecutionContext::Task::~Task()
|
|
|
| void ScriptExecutionContext::setDatabaseContext(DatabaseContext* databaseContext)
|
| {
|
| + ASSERT(!m_databaseContext);
|
| m_databaseContext = databaseContext;
|
| }
|
|
|
|
|