Commit 3d42c21b authored by kouhei@chromium.org's avatar kouhei@chromium.org

Oilpan: Delay frameDetached() so it won't dispatch event inside ~SVGImage

This CL moves frameDetached() call outside of ~SVGImage. Oilpan disallows any heap-allocated object creation inside destructors. SVGImageChromeClient and Page to be deleted are queued to DelayedSVGImageDestructor singleton, and oneshot timer is invoked to call |frameDetached| outside of destructor scope.

TESTS=svg/ (w/ enable_oilpan=1)
BUG=None
NOTRY=true

Review URL: https://codereview.chromium.org/185613003

git-svn-id: svn://svn.chromium.org/blink/trunk@168612 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent c53653f5
...@@ -57,16 +57,61 @@ SVGImage::SVGImage(ImageObserver* observer) ...@@ -57,16 +57,61 @@ SVGImage::SVGImage(ImageObserver* observer)
{ {
} }
SVGImage::~SVGImage() // Delay destruction of Page attached to SVGImage.
{ // We need to call |loader().frameDetached()| before disposing a Page, however
if (m_page) { // the call is non-trivial and involves touching/creating on-heap objects
// Store m_page in a local variable, clearing m_page, so that SVGImageChromeClient knows we're destructed. // which is not possible from a GarbageCollected object finalizer.
OwnPtr<Page> currentPage = m_page.release(); // To circumvent this, DelayedSVGImageDestructor will delay the call to
currentPage->mainFrame()->loader().frameDetached(); // Break both the loader and view references to the frame // the end of current event loop.
class DelayedSVGImageDestructor {
public:
void add(PassOwnPtr<SVGImageChromeClient> chromeClient, PassOwnPtr<Page> page)
{
Entry entry;
entry.chromeClient = chromeClient.leakPtr();
entry.page = page.leakPtr();
m_entries.append(entry);
m_detachTimer.startOneShot(0.0);
}
static DelayedSVGImageDestructor* get()
{
DEFINE_STATIC_LOCAL(DelayedSVGImageDestructor, delayed, ());
return &delayed;
} }
// Verify that page teardown destroyed the Chrome private:
ASSERT(!m_chromeClient || !m_chromeClient->image()); DelayedSVGImageDestructor()
: m_detachTimer(this, &DelayedSVGImageDestructor::detachTimerFired)
{
}
void detachTimerFired(Timer<DelayedSVGImageDestructor>*)
{
Vector<Entry>::const_iterator it = m_entries.begin();
Vector<Entry>::const_iterator itEnd = m_entries.end();
for (; it != itEnd; ++it) {
it->page->mainFrame()->loader().frameDetached();
delete it->page;
delete it->chromeClient;
}
m_entries.clear();
}
struct Entry {
SVGImageChromeClient* chromeClient;
Page* page;
};
Vector<Entry> m_entries;
Timer<DelayedSVGImageDestructor> m_detachTimer;
};
SVGImage::~SVGImage()
{
m_chromeClient->clearImage();
DelayedSVGImageDestructor::get()->add(m_chromeClient.release(), m_page.release());
} }
bool SVGImage::isInSVGImage(const Element* element) bool SVGImage::isInSVGImage(const Element* element)
......
...@@ -40,6 +40,7 @@ public: ...@@ -40,6 +40,7 @@ public:
explicit SVGImageChromeClient(SVGImage*); explicit SVGImageChromeClient(SVGImage*);
virtual bool isSVGImageChromeClient() const OVERRIDE; virtual bool isSVGImageChromeClient() const OVERRIDE;
void clearImage() { m_image = 0; }
SVGImage* image() const { return m_image; } SVGImage* image() const { return m_image; }
private: private:
......
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