Index: third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp |
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp |
index 46628934b330656e7879b91b4065efa2db80b819..551459fd0b78451c3c8604c86589ce4e987f419c 100644 |
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp |
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp |
@@ -67,7 +67,8 @@ namespace blink { |
SVGImage::SVGImage(ImageObserver* observer) |
: Image(observer), |
m_paintController(PaintController::create()), |
- m_hasPendingTimelineRewind(false) {} |
+ m_hasPendingTimelineRewind(false), |
+ m_weakPtrFactory(this) {} |
SVGImage::~SVGImage() { |
if (m_page) { |
@@ -560,6 +561,39 @@ void SVGImage::updateUseCounters(const Document& document) const { |
} |
} |
+// SVGImageLocalFrameClient is used to wait until SVG document's load event |
+// in the case where there are subresources asynchronously loaded. |
+class SVGImage::SVGImageLocalFrameClient : public EmptyLocalFrameClient { |
+ public: |
+ SVGImageLocalFrameClient(WeakPtr<SVGImage> image) : m_image(image) {} |
+ |
+ private: |
+ void dispatchDidHandleOnloadEvents() override { |
+ // The SVGImage is destructed before SVG load completion. |
+ if (!m_image) |
+ return; |
+ |
+ switch (m_image->m_loadStatus) { |
fs
2017/03/15 14:22:17
Could we have this just call a method on SVGImage,
hiroshige
2017/05/04 22:50:50
Done.
|
+ case InDataChanged: |
+ m_image->m_loadStatus = LoadCompletedWithinDataChanged; |
+ break; |
+ |
+ case AfterDataChanged: |
+ m_image->m_loadStatus = LoadCompletedAsynchronously; |
+ if (m_image->getImageObserver()) |
+ m_image->getImageObserver()->loadCompleted(m_image.get()); |
+ break; |
+ |
+ case DataChangedNotStarted: |
+ case LoadCompletedWithinDataChanged: |
+ case LoadCompletedAsynchronously: |
+ CHECK(false); |
+ break; |
+ } |
+ } |
+ WeakPtr<SVGImage> m_image; |
+}; |
+ |
Image::SizeAvailability SVGImage::dataChanged(bool allDataReceived) { |
TRACE_EVENT0("blink", "SVGImage::dataChanged"); |
@@ -567,17 +601,20 @@ Image::SizeAvailability SVGImage::dataChanged(bool allDataReceived) { |
if (!data()->size()) |
return SizeAvailable; |
- if (allDataReceived) { |
+ if (!allDataReceived) |
+ return m_page ? SizeAvailable : SizeUnavailable; |
+ |
+ CHECK(!m_page); |
+ |
+ { |
kouhei (in TOK)
2017/03/15 11:32:34
remove { and unindent
hiroshige
2017/05/04 22:50:50
Done.
|
// SVGImage will fire events (and the default C++ handlers run) but doesn't |
// actually allow script to run so it's fine to call into it. We allow this |
// since it means an SVG data url can synchronously load like other image |
// types. |
EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents; |
- DEFINE_STATIC_LOCAL(LocalFrameClient, dummyLocalFrameClient, |
- (EmptyLocalFrameClient::create())); |
- |
- CHECK(!m_page); |
+ CHECK_EQ(m_loadStatus, DataChangedNotStarted); |
+ m_loadStatus = InDataChanged; |
Page::PageClients pageClients; |
fillWithEmptyClients(pageClients); |
@@ -620,7 +657,9 @@ Image::SizeAvailability SVGImage::dataChanged(bool allDataReceived) { |
LocalFrame* frame = nullptr; |
{ |
TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame"); |
- frame = LocalFrame::create(&dummyLocalFrameClient, &page->frameHost(), 0); |
+ frame = |
+ LocalFrame::create(new SVGImageLocalFrameClient(this->asWeakPtr()), |
fs
2017/03/15 14:22:17
What is the case that prompts the use of a WeakPtr
hiroshige
2017/05/04 22:50:50
While I don't know concrete cases, the following i
fs
2017/05/05 10:52:42
Yes, a RefPtr would certainly not work. With the c
hiroshige
2017/05/08 17:22:06
Oh, and I noticed we cannot use WeakPtr with Threa
hiroshige
2017/05/08 18:37:11
So, this means SVGImage is always alive when the n
fs
2017/05/08 18:52:33
Yes, AFAICS.
|
+ &page->frameHost(), 0); |
frame->setView(FrameView::create(*frame)); |
frame->init(); |
} |
@@ -648,7 +687,24 @@ Image::SizeAvailability SVGImage::dataChanged(bool allDataReceived) { |
LayoutReplaced::defaultWidth, LayoutReplaced::defaultHeight))); |
} |
- return m_page ? SizeAvailable : SizeUnavailable; |
+ DCHECK(m_page); |
+ switch (m_loadStatus) { |
+ case InDataChanged: |
+ m_loadStatus = AfterDataChanged; |
+ return SizeAvailableAndLoadingAsynchronously; |
+ |
+ case LoadCompletedWithinDataChanged: |
+ return SizeAvailable; |
+ |
+ case DataChangedNotStarted: |
+ case AfterDataChanged: |
+ case LoadCompletedAsynchronously: |
+ CHECK(false); |
+ break; |
+ } |
+ |
+ NOTREACHED(); |
+ return SizeAvailable; |
} |
String SVGImage::filenameExtension() const { |