Chromium Code Reviews| 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 |