Rename pageCache() to PageCache::shared() and return a reference
[WebKit-https.git] / Source / WebKit / mac / WebCoreSupport / WebVisitedLinkStore.mm
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "WebVisitedLinkStore.h"
27
28 #import "WebDelegateImplementationCaching.h"
29 #import "WebFrameInternal.h"
30 #import "WebHistoryInternal.h"
31 #import "WebViewInternal.h"
32 #import <WebCore/BlockExceptions.h>
33 #import <WebCore/PageCache.h>
34 #import <wtf/NeverDestroyed.h>
35
36 using namespace WebCore;
37
38 static bool s_shouldTrackVisitedLinks;
39
40 static HashSet<WebVisitedLinkStore*>& visitedLinkStores()
41 {
42     static NeverDestroyed<HashSet<WebVisitedLinkStore*>> visitedLinkStores;
43
44     return visitedLinkStores;
45 }
46
47
48 Ref<WebVisitedLinkStore> WebVisitedLinkStore::create()
49 {
50     return adoptRef(*new WebVisitedLinkStore);
51 }
52
53 WebVisitedLinkStore::WebVisitedLinkStore()
54     : m_visitedLinksPopulated(false)
55 {
56     visitedLinkStores().add(this);
57 }
58
59 WebVisitedLinkStore::~WebVisitedLinkStore()
60 {
61     visitedLinkStores().remove(this);
62 }
63
64 void WebVisitedLinkStore::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)
65 {
66     if (s_shouldTrackVisitedLinks == shouldTrackVisitedLinks)
67         return;
68     s_shouldTrackVisitedLinks = shouldTrackVisitedLinks;
69     if (!s_shouldTrackVisitedLinks)
70         removeAllVisitedLinks();
71 }
72
73 void WebVisitedLinkStore::removeAllVisitedLinks()
74 {
75     for (auto& visitedLinkStore : visitedLinkStores())
76         visitedLinkStore->removeVisitedLinkHashes();
77     PageCache::shared().markPagesForVistedLinkStyleRecalc();
78 }
79
80 void WebVisitedLinkStore::addVisitedLink(NSString *urlString)
81 {
82     if (!s_shouldTrackVisitedLinks)
83         return;
84
85     size_t length = urlString.length;
86
87     if (const UChar* characters = CFStringGetCharactersPtr((__bridge CFStringRef)urlString)) {
88         addVisitedLinkHash(visitedLinkHash(characters, length));
89         return;
90     }
91
92     Vector<UChar, 512> buffer(length);
93     [urlString getCharacters:buffer.data()];
94
95     addVisitedLinkHash(visitedLinkHash(buffer.data(), length));
96 }
97
98 void WebVisitedLinkStore::removeVisitedLink(NSString *urlString)
99 {
100     LinkHash linkHash = visitedLinkHash(urlString);
101
102     ASSERT(m_visitedLinkHashes.contains(linkHash));
103     m_visitedLinkHashes.remove(linkHash);
104
105     invalidateStylesForLink(linkHash);
106     PageCache::shared().markPagesForVistedLinkStyleRecalc();
107 }
108
109 bool WebVisitedLinkStore::isLinkVisited(Page& page, LinkHash linkHash, const URL& baseURL, const AtomicString& attributeURL)
110 {
111     populateVisitedLinksIfNeeded(page);
112
113     return m_visitedLinkHashes.contains(linkHash);
114 }
115
116 void WebVisitedLinkStore::addVisitedLink(Page& sourcePage, LinkHash linkHash)
117 {
118     if (!s_shouldTrackVisitedLinks)
119         return;
120
121     addVisitedLinkHash(linkHash);
122 }
123
124 void WebVisitedLinkStore::populateVisitedLinksIfNeeded(Page& page)
125 {
126     if (m_visitedLinksPopulated)
127         return;
128
129     m_visitedLinksPopulated = true;
130
131     WebView *webView = kit(&page);
132     ASSERT(webView);
133
134     if (webView.historyDelegate) {
135         WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(webView);
136
137         if (implementations->populateVisitedLinksFunc)
138             CallHistoryDelegate(implementations->populateVisitedLinksFunc, webView, @selector(populateVisitedLinksForWebView:));
139
140         return;
141     }
142
143     BEGIN_BLOCK_OBJC_EXCEPTIONS;
144     [[WebHistory optionalSharedHistory] _addVisitedLinksToVisitedLinkStore:*this];
145     END_BLOCK_OBJC_EXCEPTIONS;
146 }
147
148 void WebVisitedLinkStore::addVisitedLinkHash(LinkHash linkHash)
149 {
150     ASSERT(s_shouldTrackVisitedLinks);
151
152     m_visitedLinkHashes.add(linkHash);
153
154     invalidateStylesForLink(linkHash);
155     PageCache::shared().markPagesForVistedLinkStyleRecalc();
156 }
157
158 void WebVisitedLinkStore::removeVisitedLinkHashes()
159 {
160     m_visitedLinksPopulated = false;
161     if (m_visitedLinkHashes.isEmpty())
162         return;
163     m_visitedLinkHashes.clear();
164
165     invalidateStylesForAllLinks();
166 }