1bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)/*
2bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
3bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
4bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * modification, are permitted provided that the following conditions are
6bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * met:
7bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
8bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
9bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
10bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
11bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
12bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * in the documentation and/or other materials provided with the
13bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * distribution.
14bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
15bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
16bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * this software without specific prior written permission.
17bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
18bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) */
30bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
31bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "config.h"
32bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/dom/PresentationAttributeStyle.h"
33bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
34bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/css/StylePropertySet.h"
35bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/dom/Attribute.h"
36bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/dom/Element.h"
37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/html/HTMLInputElement.h"
385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "platform/Timer.h"
39bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/HashFunctions.h"
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/HashMap.h"
41bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "wtf/text/CString.h"
42bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
43c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
44bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
45bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)using namespace HTMLNames;
46bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
47bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)struct PresentationAttributeCacheKey {
48bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    PresentationAttributeCacheKey() : tagName(0) { }
49bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    StringImpl* tagName;
50bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    Vector<std::pair<StringImpl*, AtomicString>, 3> attributesAndValues;
51bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)};
52bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
53bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static bool operator!=(const PresentationAttributeCacheKey& a, const PresentationAttributeCacheKey& b)
54bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
55bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (a.tagName != b.tagName)
56bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return true;
57bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return a.attributesAndValues != b.attributesAndValues;
58bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
59bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
60197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct PresentationAttributeCacheEntry FINAL : public NoBaseWillBeGarbageCollectedFinalized<PresentationAttributeCacheEntry> {
61197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
62bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)public:
63197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void trace(Visitor* visitor) { visitor->trace(value); }
64197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
65bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    PresentationAttributeCacheKey key;
66197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RefPtrWillBeMember<StylePropertySet> value;
67bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)};
68bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
69197021e6b966cfb06891637935ef33fff06433d1Ben Murdochtypedef WillBeHeapHashMap<unsigned, OwnPtrWillBeMember<PresentationAttributeCacheEntry>, AlreadyHashed> PresentationAttributeCache;
70bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static PresentationAttributeCache& presentationAttributeCache()
71bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<PresentationAttributeCache>, cache, (adoptPtrWillBeNoop(new PresentationAttributeCache())));
73197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return *cache;
74bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
75bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
76bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)class PresentationAttributeCacheCleaner {
77bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    WTF_MAKE_NONCOPYABLE(PresentationAttributeCacheCleaner); WTF_MAKE_FAST_ALLOCATED;
78bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)public:
79bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    PresentationAttributeCacheCleaner()
80bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        : m_hitCount(0)
81bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        , m_cleanTimer(this, &PresentationAttributeCacheCleaner::cleanCache)
82bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    {
83bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
84bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
85bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    void didHitPresentationAttributeCache()
86bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    {
87bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        if (presentationAttributeCache().size() < minimumPresentationAttributeCacheSizeForCleaning)
88bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            return;
89bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
90bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        m_hitCount++;
91bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
92bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        if (!m_cleanTimer.isActive())
93d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            m_cleanTimer.startOneShot(presentationAttributeCacheCleanTimeInSeconds, FROM_HERE);
94bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
95bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
96bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)private:
97bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    static const unsigned presentationAttributeCacheCleanTimeInSeconds = 60;
9851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    static const unsigned minimumPresentationAttributeCacheSizeForCleaning = 100;
99bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    static const unsigned minimumPresentationAttributeCacheHitCountPerMinute = (100 * presentationAttributeCacheCleanTimeInSeconds) / 60;
100bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
101bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    void cleanCache(Timer<PresentationAttributeCacheCleaner>* timer)
102bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    {
103bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        ASSERT_UNUSED(timer, timer == &m_cleanTimer);
104bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        unsigned hitCount = m_hitCount;
105bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        m_hitCount = 0;
106bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        if (hitCount > minimumPresentationAttributeCacheHitCountPerMinute)
107bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            return;
108bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        presentationAttributeCache().clear();
109bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
110bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
111bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    unsigned m_hitCount;
112bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    Timer<PresentationAttributeCacheCleaner> m_cleanTimer;
113bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)};
114bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
115bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static bool attributeNameSort(const pair<StringImpl*, AtomicString>& p1, const pair<StringImpl*, AtomicString>& p2)
116bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
117bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Sort based on the attribute name pointers. It doesn't matter what the order is as long as it is always the same.
118bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return p1.first < p2.first;
119bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
120bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
121bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static void makePresentationAttributeCacheKey(Element& element, PresentationAttributeCacheKey& result)
122bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
123bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // FIXME: Enable for SVG.
124bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!element.isHTMLElement())
125bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
126bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Interpretation of the size attributes on <input> depends on the type attribute.
127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isHTMLInputElement(element))
128bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    AttributeCollection attributes = element.attributesWithoutUpdate();
130e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    AttributeCollection::iterator end = attributes.end();
131e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
132f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (!element.isPresentationAttribute(it->name()))
133bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            continue;
134f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (!it->namespaceURI().isNull())
135bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            return;
136bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // FIXME: Background URL may depend on the base URL and can't be shared. Disallow caching.
137f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (it->name() == backgroundAttr)
138bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            return;
139f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        result.attributesAndValues.append(std::make_pair(it->localName().impl(), it->value()));
140bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
141bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (result.attributesAndValues.isEmpty())
142bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
143bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Attribute order doesn't matter. Sort for easy equality comparison.
144bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    std::sort(result.attributesAndValues.begin(), result.attributesAndValues.end(), attributeNameSort);
145bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // The cache key is non-null when the tagName is set.
146bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    result.tagName = element.localName().impl();
147bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
148bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
149bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static unsigned computePresentationAttributeCacheHash(const PresentationAttributeCacheKey& key)
150bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
151bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!key.tagName)
152bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return 0;
153bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(key.attributesAndValues.size());
154bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    unsigned attributeHash = StringHasher::hashMemory(key.attributesAndValues.data(), key.attributesAndValues.size() * sizeof(key.attributesAndValues[0]));
155bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return WTF::pairIntHash(key.tagName->existingHash(), attributeHash);
156bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
157bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
158197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPassRefPtrWillBeRawPtr<StylePropertySet> computePresentationAttributeStyle(Element& element)
159bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
160bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    DEFINE_STATIC_LOCAL(PresentationAttributeCacheCleaner, cacheCleaner, ());
161bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
162bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(element.isStyledElement());
163bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
164bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    PresentationAttributeCacheKey cacheKey;
165bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    makePresentationAttributeCacheKey(element, cacheKey);
166bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
167bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    unsigned cacheHash = computePresentationAttributeCacheHash(cacheKey);
168bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    PresentationAttributeCache::ValueType* cacheValue;
170bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (cacheHash) {
17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        cacheValue = presentationAttributeCache().add(cacheHash, nullptr).storedValue;
17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (cacheValue->value && cacheValue->value->key != cacheKey)
173bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            cacheHash = 0;
174bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    } else {
17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        cacheValue = 0;
176bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
177bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
178197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RefPtrWillBeRawPtr<StylePropertySet> style = nullptr;
17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (cacheHash && cacheValue->value) {
18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        style = cacheValue->value->value;
181bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        cacheCleaner.didHitPresentationAttributeCache();
182bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    } else {
183f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        style = MutableStylePropertySet::create(element.isSVGElement() ? SVGAttributeMode : HTMLAttributeMode);
184c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        AttributeCollection attributes = element.attributesWithoutUpdate();
185e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        AttributeCollection::iterator end = attributes.end();
186e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it)
187f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            element.collectStyleForPresentationAttribute(it->name(), it->value(), toMutableStylePropertySet(style));
188bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
189bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
19009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!cacheHash || cacheValue->value)
191bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return style.release();
192bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
193197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    OwnPtrWillBeRawPtr<PresentationAttributeCacheEntry> newEntry = adoptPtrWillBeNoop(new PresentationAttributeCacheEntry);
194bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    newEntry->key = cacheKey;
195bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    newEntry->value = style;
196bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
19751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    static const unsigned presentationAttributeCacheMaximumSize = 4096;
198bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (presentationAttributeCache().size() > presentationAttributeCacheMaximumSize) {
199bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // FIXME: Discarding the entire cache when it gets too big is probably bad
200bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // since it creates a perf "cliff". Perhaps we should use an LRU?
201bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        presentationAttributeCache().clear();
202bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        presentationAttributeCache().set(cacheHash, newEntry.release());
203bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    } else {
20409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        cacheValue->value = newEntry.release();
205bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
206bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
207bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return style.release();
208bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
209bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
210c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
211