The problem was that WebDataSource does not hold a strong reference to the WebDocumentLoader. If
a WebDataSource is still around after the loader has been destroyed, it'll just point to
a stale WebDocumentLoader.
To fix this without a circular reference, WebDataSource now holds a strong reference to the
WebDocumentLoader. The WebDocumentLoader holds a strong reference to the WebDataSource
until it's detached from the WebFrame. When the WebDataSource is destroyed, it'll notify
its WebDocumentLoader so the loader will clear any references to it.
Reviewed by Darin.
* WebDataSource.cpp:
(WebDataSource::~WebDataSource): call WebDocumentLoader::detachDataSource() so the loader
will clear any references to this data source
(WebDataSource::documentLoader): m_loader is now a RefPtr so we need to call get().
* WebDataSource.h:
* WebDocumentLoader.cpp:
(WebDocumentLoader::WebDocumentLoader): initialize m_dataSource since it's no longer a COMPtr.
(WebDocumentLoader::~WebDocumentLoader): release m_dataSource if necessary
(WebDocumentLoader::setDataSource): add a reference to m_dataSource
(WebDocumentLoader::dataSource):
(WebDocumentLoader::detachDataSource): clear m_detachedDataSource.
(WebDocumentLoader::attachToFrame): call setDataSource() so it'll add the reference to the data source if necessary.
(WebDocumentLoader::detachFromFrame): release the reference to the data source
* WebDocumentLoader.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@25415
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-09-07 Ada Chan <adachan@apple.com>
+
+ <rdar://problem/5453494> Better lifetime management of WebDataSource and WebDocumentLoader
+ The problem was that WebDataSource does not hold a strong reference to the WebDocumentLoader. If
+ a WebDataSource is still around after the loader has been destroyed, it'll just point to
+ a stale WebDocumentLoader.
+ To fix this without a circular reference, WebDataSource now holds a strong reference to the
+ WebDocumentLoader. The WebDocumentLoader holds a strong reference to the WebDataSource
+ until it's detached from the WebFrame. When the WebDataSource is destroyed, it'll notify
+ its WebDocumentLoader so the loader will clear any references to it.
+
+ Reviewed by Darin.
+
+ * WebDataSource.cpp:
+ (WebDataSource::~WebDataSource): call WebDocumentLoader::detachDataSource() so the loader
+ will clear any references to this data source
+ (WebDataSource::documentLoader): m_loader is now a RefPtr so we need to call get().
+ * WebDataSource.h:
+ * WebDocumentLoader.cpp:
+ (WebDocumentLoader::WebDocumentLoader): initialize m_dataSource since it's no longer a COMPtr.
+ (WebDocumentLoader::~WebDocumentLoader): release m_dataSource if necessary
+ (WebDocumentLoader::setDataSource): add a reference to m_dataSource
+ (WebDocumentLoader::dataSource):
+ (WebDocumentLoader::detachDataSource): clear m_detachedDataSource.
+ (WebDocumentLoader::attachToFrame): call setDataSource() so it'll add the reference to the data source if necessary.
+ (WebDocumentLoader::detachFromFrame): release the reference to the data source
+ * WebDocumentLoader.h:
+
2007-09-05 Dave Hyatt <hyatt@apple.com>
Make sure ALT+other keys is properly sent into the DOM so that Web pages (and editing fields) can
WebDataSource::~WebDataSource()
{
+ if (m_loader)
+ m_loader->detachDataSource();
WebDataSourceCount--;
gClassCount--;
}
WebDocumentLoader* WebDataSource::documentLoader() const
{
- return m_loader;
+ return m_loader.get();
}
// IWebDataSourcePrivate ------------------------------------------------------
#include "IWebDataSource.h"
#include "COMPtr.h"
+#include <WTF/RefPtr.h>
class WebDocumentLoader;
class WebMutableURLRequest;
WebDocumentLoader* documentLoader() const;
protected:
ULONG m_refCount;
- WebDocumentLoader* m_loader;
+ RefPtr<WebDocumentLoader> m_loader;
COMPtr<IWebDocumentRepresentation> m_representation;
};
WebDocumentLoader::WebDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
: DocumentLoader(request, substituteData)
+ , m_dataSource(0)
, m_detachedDataSource(0)
{
}
+WebDocumentLoader::~WebDocumentLoader()
+{
+ if (m_dataSource) {
+ ASSERT(!m_detachedDataSource);
+ m_dataSource->Release();
+ }
+}
+
void WebDocumentLoader::setDataSource(WebDataSource *dataSource)
{
+ ASSERT(!m_dataSource);
m_dataSource = dataSource;
+ if (m_dataSource)
+ m_dataSource->AddRef();
}
WebDataSource* WebDocumentLoader::dataSource() const
{
- return m_dataSource.get();
+ return m_dataSource;
+}
+
+void WebDocumentLoader::detachDataSource()
+{
+ // we only call detachDataSource when the WebDataSource is freed - and we won't get there if m_dataSource is not
+ // null (because that would mean the loader still has a reference to the data source)
+ ASSERT(!m_dataSource);
+ m_detachedDataSource = 0;
}
void WebDocumentLoader::attachToFrame()
DocumentLoader::attachToFrame();
if (m_detachedDataSource) {
ASSERT(!m_dataSource);
- m_dataSource = m_detachedDataSource;
+ setDataSource(m_detachedDataSource);
m_detachedDataSource = 0;
}
}
void WebDocumentLoader::detachFromFrame()
{
DocumentLoader::detachFromFrame();
- m_detachedDataSource = m_dataSource.get();
- m_dataSource = 0;
+ m_detachedDataSource = m_dataSource;
+ if (m_dataSource) {
+ WebDataSource* dataSourceToBeReleased = m_dataSource;
+ // It's important to null out m_dataSource before calling release on the data source. That release can cause the data
+ // source to be deleted - which ends up calling loader->detachDataSource() which makes the assumption that the loader no
+ // longer holds a reference to the data source.
+ m_dataSource = 0;
+ dataSourceToBeReleased->Release();
+ }
}
#include "WebDataSource.h"
-#include "COMPtr.h"
-
#pragma warning(push, 0)
#include <WebCore/DocumentLoader.h>
#pragma warning(pop)
{
public:
WebDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&);
+ ~WebDocumentLoader();
void setDataSource(WebDataSource*);
WebDataSource* dataSource() const;
+ void detachDataSource();
virtual void attachToFrame();
virtual void detachFromFrame();
private:
- COMPtr<WebDataSource> m_dataSource;
+ WebDataSource* m_dataSource;
WebDataSource* m_detachedDataSource; // not retained
};