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..206b46820eee6fc0519fd5c1acac0674dcbe3f11 |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp |
@@ -0,0 +1,133 @@ |
+// 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); |
esprehn
2016/10/25 01:18:42
What about this feature needs a preFinalizer?
fs
2016/10/25 15:00:53
It's for calling removeClient on m_document (balan
|
+ } |
+} |
+ |
+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).elementProxySet().add(*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(); |
+} |
+ |
+void SVGElementProxy::proxiedElementChanged() { |
+ incrementGeneration(); |
+ HeapVector<Member<SVGResourceClient>> clients; |
+ copyToVector(m_clients, clients); |
+ for (SVGResourceClient* client : clients) |
+ client->resourceElementChanged(); |
+} |
+ |
+void SVGElementProxy::notifyFinished(Resource*) { |
+ proxiedElementChanged(); |
+} |
+ |
+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 SVGElementProxySet::add(SVGElementProxy& elementProxy) { |
+ m_elementProxies.add(&elementProxy); |
+} |
+ |
+bool SVGElementProxySet::isEmpty() const { |
+ return m_elementProxies.isEmpty(); |
+} |
+ |
+void SVGElementProxySet::notifyContentChanged() { |
+ for (SVGElementProxy* proxy : m_elementProxies) |
+ proxy->contentChanged(); |
+} |
+ |
+void SVGElementProxySet::invalidateProxies() { |
+ ProxySet elementProxies; |
+ elementProxies.swap(m_elementProxies); |
+ for (SVGElementProxy* proxy : elementProxies) |
+ proxy->proxiedElementChanged(); |
+} |
+ |
+DEFINE_TRACE(SVGElementProxySet) { |
+ visitor->trace(m_elementProxies); |
+} |
+ |
+} // namespace blink |