Index: third_party/WebKit/Source/core/svg/SVGElementProxy.cpp |
diff --git a/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp b/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9787ceb62b807ba750304f16d970c5c66f6ec1ba |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp |
@@ -0,0 +1,134 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "core/svg/SVGElementProxy.h" |
+ |
+#include "core/fetch/FetchInitiatorTypeNames.h" |
+#include "core/fetch/FetchRequest.h" |
+#include "core/fetch/ResourceFetcher.h" |
+#include "core/svg/SVGDocumentExtensions.h" |
+#include "core/svg/SVGElement.h" |
+#include "core/svg/SVGFilterElement.h" |
+#include "core/svg/SVGResourceClient.h" |
+ |
+namespace blink { |
+ |
+SVGElementProxy::SVGElementProxy(const AtomicString& id) |
+ : m_id(id), m_generation(0), m_isLocal(true) {} |
+ |
+SVGElementProxy::SVGElementProxy(const String& url, const AtomicString& id) |
+ : m_id(id), m_url(url), m_generation(0), m_isLocal(false) {} |
+ |
+SVGElementProxy::~SVGElementProxy() {} |
+ |
+void SVGElementProxy::addClient(SVGResourceClient* client) { |
+ m_clients.add(client); |
+} |
+ |
+void SVGElementProxy::removeClient(SVGResourceClient* client) { |
+ m_clients.remove(client); |
+} |
+ |
+void SVGElementProxy::resolve(Document& document) { |
+ if (m_isLocal || m_url.isEmpty()) |
+ return; |
+ FetchRequest request(ResourceRequest(m_url), FetchInitiatorTypeNames::css); |
+ m_document = DocumentResource::fetchSVGDocument(request, document.fetcher()); |
+ m_url = String(); |
+ if (m_document) { |
+ m_document->addClient(this); |
+ ThreadState::current()->registerPreFinalizer(this); |
+ } |
+} |
+ |
+TreeScope* SVGElementProxy::treeScopeForLookup(TreeScope& treeScope) const { |
+ if (m_isLocal) |
+ return &treeScope; |
+ if (!m_document) |
+ return nullptr; |
+ return m_document->document(); |
+} |
+ |
+SVGElement* SVGElementProxy::element(TreeScope& treeScope) { |
+ // An empty id will never be a valid element reference. |
+ if (m_id.isEmpty()) |
+ return nullptr; |
+ TreeScope* lookupScope = treeScopeForLookup(treeScope); |
+ if (!lookupScope) |
+ return nullptr; |
+ if (Element* targetElement = lookupScope->getElementById(m_id)) { |
+ if (isSVGFilterElement(*targetElement)) { |
+ toSVGFilterElement(*targetElement) |
+ .elementProxyTracker() |
+ .attachElementProxy(*this); |
+ return toSVGElement(targetElement); |
+ } |
+ } |
+ // For external references we wait for the document to finish loading. If the |
+ // reference is not valid then it will never be (because the document will |
+ // not mutate.) |
+ if (!m_isLocal) |
+ return nullptr; |
+ // If the lookup fails for some reason (no element with said 'id' or no |
+ // element of the required type), attach the proxy to SVGDocumentExtensions. |
+ // It will then send notifications when an element with the associated id is |
+ // added to the tree etc. |
+ treeScope.document().accessSVGExtensions().attachPendingProxy(*this); |
+ return nullptr; |
+} |
+ |
+void SVGElementProxy::contentChanged() { |
+ HeapVector<Member<SVGResourceClient>> clients; |
+ copyToVector(m_clients, clients); |
+ for (SVGResourceClient* client : clients) |
+ client->resourceContentChanged(this); |
+} |
+ |
+void SVGElementProxy::referenceChanged() { |
+ nextGeneration(); |
+ HeapVector<Member<SVGResourceClient>> clients; |
+ copyToVector(m_clients, clients); |
+ for (SVGResourceClient* client : clients) |
+ client->resourceReferenceChanged(this); |
+} |
+ |
+void SVGElementProxy::notifyFinished(Resource*) { |
+ referenceChanged(); |
+} |
+ |
+void SVGElementProxy::detachDocumentClient() { |
+ m_document->removeClient(this); |
+ m_document = nullptr; |
+} |
+ |
+DEFINE_TRACE(SVGElementProxy) { |
+ visitor->trace(m_clients); |
+ visitor->trace(m_document); |
+ DocumentResourceClient::trace(visitor); |
+} |
+ |
+void SVGElementProxyTracker::attachElementProxy(SVGElementProxy& elementProxy) { |
+ m_elementProxies.add(&elementProxy); |
+} |
+ |
+bool SVGElementProxyTracker::isEmpty() const { |
+ return m_elementProxies.isEmpty(); |
+} |
+ |
+void SVGElementProxyTracker::invalidateProxyClients() { |
+ for (SVGElementProxy* proxy : m_elementProxies) |
+ proxy->contentChanged(); |
+} |
+ |
+void SVGElementProxyTracker::invalidateProxies() { |
+ for (SVGElementProxy* proxy : m_elementProxies) |
pdr.
2016/10/20 03:11:05
Should we save off the proxies, clear them, then i
fs
2016/10/20 11:28:00
Sure. Reworked.
|
+ proxy->referenceChanged(); |
+ m_elementProxies.clear(); |
+} |
+ |
+DEFINE_TRACE(SVGElementProxyTracker) { |
+ visitor->trace(m_elementProxies); |
+} |
+ |
+} // namespace blink |