2011-03-15 David Grogan <dgrogan@chromium.org>

        Reviewed by Jeremy Orlow.

        Fix crash caused by Invalid call to destroyActiveDOMObject during stopActiveDOMObjects
        https://bugs.webkit.org/show_bug.cgi?id=56350

        When a frame is unloaded, ScriptExecutionContext::stopActiveDOMObjects
        calls stop() on each ActiveDOMObject.

        Calling IDBDatabase::stop() can cause IDBDatabase to be destroyed:
        * IDBDatabase::stop() causes the chrome message dispatcher to remove
        its reference to IDBDatabase, which it has as type
        IDBDatabaseCallbacks.
        * If that reference is the last one, the IDBDatabase is destroyed.
        * Destroying an ActiveDOMObject while they are being iterated over causes
        a defensive crash.

        This change creates a separate IDBDatabaseCallbacks object that is not
        an ActiveDOMObject, so it can be destroyed by
        ScriptExecutionContext::stopActiveDOMObjects.

        Because the chrome message dispatcher is only used in multi-process
        chromium, that's the only platform affected.  Chromium browser tests
        forthcoming.

        * WebCore.gypi:
        * storage/IDBDatabase.cpp:
        (WebCore::IDBDatabase::IDBDatabase):
        (WebCore::IDBDatabase::~IDBDatabase):
        (WebCore::IDBDatabase::setVersion):
        (WebCore::IDBDatabase::close):
        (WebCore::IDBDatabase::open):
        * storage/IDBDatabase.h:
        * storage/IDBDatabaseCallbacks.h:
        (WebCore::IDBDatabaseCallbacks::unRegisterDatabase):
        * storage/IDBDatabaseCallbacksImpl.cpp: Copied from Source/WebCore/storage/IDBDatabaseCallbacks.h.
        (WebCore::IDBDatabaseCallbacksImpl::create):
        (WebCore::IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl):
        (WebCore::IDBDatabaseCallbacksImpl::onVersionChange):
        (WebCore::IDBDatabaseCallbacksImpl::unRegisterDatabase):
        * storage/IDBDatabaseCallbacksImpl.h: Copied from Source/WebCore/storage/IDBDatabaseCallbacks.h.
        (WebCore::IDBDatabaseCallbacksImpl::~IDBDatabaseCallbacksImpl):

git-svn-id: svn://svn.chromium.org/blink/trunk@81181 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 08d85699
2011-03-15 David Grogan <dgrogan@chromium.org>
Reviewed by Jeremy Orlow.
Fix crash caused by Invalid call to destroyActiveDOMObject during stopActiveDOMObjects
https://bugs.webkit.org/show_bug.cgi?id=56350
When a frame is unloaded, ScriptExecutionContext::stopActiveDOMObjects
calls stop() on each ActiveDOMObject.
Calling IDBDatabase::stop() can cause IDBDatabase to be destroyed:
* IDBDatabase::stop() causes the chrome message dispatcher to remove
its reference to IDBDatabase, which it has as type
IDBDatabaseCallbacks.
* If that reference is the last one, the IDBDatabase is destroyed.
* Destroying an ActiveDOMObject while they are being iterated over causes
a defensive crash.
This change creates a separate IDBDatabaseCallbacks object that is not
an ActiveDOMObject, so it can be destroyed by
ScriptExecutionContext::stopActiveDOMObjects.
Because the chrome message dispatcher is only used in multi-process
chromium, that's the only platform affected. Chromium browser tests
forthcoming.
* WebCore.gypi:
* storage/IDBDatabase.cpp:
(WebCore::IDBDatabase::IDBDatabase):
(WebCore::IDBDatabase::~IDBDatabase):
(WebCore::IDBDatabase::setVersion):
(WebCore::IDBDatabase::close):
(WebCore::IDBDatabase::open):
* storage/IDBDatabase.h:
* storage/IDBDatabaseCallbacks.h:
(WebCore::IDBDatabaseCallbacks::unRegisterDatabase):
* storage/IDBDatabaseCallbacksImpl.cpp: Copied from Source/WebCore/storage/IDBDatabaseCallbacks.h.
(WebCore::IDBDatabaseCallbacksImpl::create):
(WebCore::IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl):
(WebCore::IDBDatabaseCallbacksImpl::onVersionChange):
(WebCore::IDBDatabaseCallbacksImpl::unRegisterDatabase):
* storage/IDBDatabaseCallbacksImpl.h: Copied from Source/WebCore/storage/IDBDatabaseCallbacks.h.
(WebCore::IDBDatabaseCallbacksImpl::~IDBDatabaseCallbacksImpl):
2011-03-15 Adam Barth <abarth@webkit.org>
Reviewed by Dimitri Glazkov.
......
......@@ -4913,6 +4913,9 @@
'storage/IDBCursorWithValue.h',
'storage/IDBDatabase.cpp',
'storage/IDBDatabase.h',
'storage/IDBDatabaseCallbacks.h',
'storage/IDBDatabaseCallbacksImpl.cpp',
'storage/IDBDatabaseCallbacksImpl.h',
'storage/IDBDatabaseBackendImpl.cpp',
'storage/IDBDatabaseBackendImpl.h',
'storage/IDBDatabaseBackendInterface.h',
......
......@@ -29,6 +29,7 @@
#include "Document.h"
#include "EventQueue.h"
#include "IDBAny.h"
#include "IDBDatabaseCallbacksImpl.h"
#include "IDBDatabaseError.h"
#include "IDBDatabaseException.h"
#include "IDBEventDispatcher.h"
......@@ -58,10 +59,12 @@ IDBDatabase::IDBDatabase(ScriptExecutionContext* context, PassRefPtr<IDBDatabase
{
// We pass a reference of this object before it can be adopted.
relaxAdoptionRequirement();
m_databaseCallbacks = IDBDatabaseCallbacksImpl::create(this);
}
IDBDatabase::~IDBDatabase()
{
m_databaseCallbacks->unregisterDatabase(this);
}
void IDBDatabase::setSetVersionTransaction(IDBTransaction* transaction)
......@@ -103,7 +106,7 @@ void IDBDatabase::deleteObjectStore(const String& name, ExceptionCode& ec)
PassRefPtr<IDBVersionChangeRequest> IDBDatabase::setVersion(ScriptExecutionContext* context, const String& version, ExceptionCode& ec)
{
RefPtr<IDBVersionChangeRequest> request = IDBVersionChangeRequest::create(context, IDBAny::create(this), version);
m_backend->setVersion(version, request, this, ec);
m_backend->setVersion(version, request, m_databaseCallbacks, ec);
return request;
}
......@@ -154,7 +157,7 @@ void IDBDatabase::close()
}
m_noNewTransactions = true;
m_backend->close(this);
m_backend->close(m_databaseCallbacks);
}
void IDBDatabase::onVersionChange(const String& version)
......@@ -174,7 +177,7 @@ bool IDBDatabase::hasPendingActivity() const
void IDBDatabase::open()
{
m_backend->open(this);
m_backend->open(m_databaseCallbacks);
}
void IDBDatabase::enqueueEvent(PassRefPtr<Event> event)
......
......@@ -32,7 +32,7 @@
#include "EventTarget.h"
#include "ExceptionCode.h"
#include "IDBDatabaseBackendInterface.h"
#include "IDBDatabaseCallbacks.h"
#include "IDBDatabaseCallbacksImpl.h"
#include "IDBObjectStore.h"
#include "IDBTransaction.h"
#include "OptionsObject.h"
......@@ -47,7 +47,7 @@ namespace WebCore {
class IDBVersionChangeRequest;
class ScriptExecutionContext;
class IDBDatabase : public IDBDatabaseCallbacks, public EventTarget, public ActiveDOMObject {
class IDBDatabase : public RefCounted<IDBDatabase>, public EventTarget, public ActiveDOMObject {
public:
static PassRefPtr<IDBDatabase> create(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
~IDBDatabase();
......@@ -91,8 +91,8 @@ public:
bool dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) { return EventTarget::dispatchEvent(event, ec); }
virtual bool dispatchEvent(PassRefPtr<Event>);
using RefCounted<IDBDatabaseCallbacks>::ref;
using RefCounted<IDBDatabaseCallbacks>::deref;
using RefCounted<IDBDatabase>::ref;
using RefCounted<IDBDatabase>::deref;
private:
IDBDatabase(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
......@@ -114,6 +114,8 @@ private:
// Keep track of the versionchange events waiting to be fired on this
// database so that we can cancel them if the database closes.
Vector<RefPtr<Event> > m_enqueuedEvents;
RefPtr<IDBDatabaseCallbacksImpl> m_databaseCallbacks;
};
} // namespace WebCore
......
/*
* Copyright (C) 2011 Google 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 AND ITS CONTRIBUTORS "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 OR ITS 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 "IDBDatabaseCallbacksImpl.h"
#include "IDBDatabase.h"
namespace WebCore {
PassRefPtr<IDBDatabaseCallbacksImpl> IDBDatabaseCallbacksImpl::create(IDBDatabase* database)
{
return adoptRef(new IDBDatabaseCallbacksImpl(database));
}
IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl(IDBDatabase* database)
: m_database(database)
{
}
IDBDatabaseCallbacksImpl::~IDBDatabaseCallbacksImpl()
{
}
void IDBDatabaseCallbacksImpl::onVersionChange(const String& version)
{
if (m_database)
m_database->onVersionChange(version);
}
void IDBDatabaseCallbacksImpl::unregisterDatabase(IDBDatabase* database)
{
ASSERT(database == m_database);
m_database = 0;
}
} // namespace WebCore
/*
* Copyright (C) 2011 Google 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 AND ITS CONTRIBUTORS "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 OR ITS 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.
*/
#ifndef IDBDatabaseCallbacksImpl_h
#define IDBDatabaseCallbacksImpl_h
#include "IDBDatabaseCallbacks.h"
#include "PlatformString.h"
#include <wtf/RefCounted.h>
#if ENABLE(INDEXED_DATABASE)
namespace WebCore {
class IDBDatabase;
class IDBDatabaseCallbacksImpl : public IDBDatabaseCallbacks {
public:
static PassRefPtr<IDBDatabaseCallbacksImpl> create(IDBDatabase*);
virtual ~IDBDatabaseCallbacksImpl();
virtual void onVersionChange(const String& version);
void unregisterDatabase(IDBDatabase*);
private:
IDBDatabaseCallbacksImpl(IDBDatabase*);
// m_database has a RefPtr to this, so use a weak pointer to avoid a cycle.
IDBDatabase* m_database;
};
} // namespace WebCore
#endif
#endif // IDBDatabaseCallbacksImpl_h
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment