Add WTF::move()
[WebKit-https.git] / Source / WebCore / page / PageGroup.cpp
1 /*
2  * Copyright (C) 2008 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "PageGroup.h"
28
29 #include "Chrome.h"
30 #include "ChromeClient.h"
31 #include "DOMWrapperWorld.h"
32 #include "DefaultVisitedLinkStore.h"
33 #include "Document.h"
34 #include "DocumentStyleSheetCollection.h"
35 #include "GroupSettings.h"
36 #include "MainFrame.h"
37 #include "Page.h"
38 #include "PageCache.h"
39 #include "SecurityOrigin.h"
40 #include "Settings.h"
41 #include "StorageNamespace.h"
42 #include "UserContentController.h"
43 #include "VisitedLinkStore.h"
44 #include <wtf/StdLibExtras.h>
45
46 #if ENABLE(VIDEO_TRACK)
47 #if PLATFORM(MAC) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
48 #include "CaptionUserPreferencesMediaAF.h"
49 #else
50 #include "CaptionUserPreferences.h"
51 #endif
52 #endif
53
54 namespace WebCore {
55
56 static unsigned getUniqueIdentifier()
57 {
58     static unsigned currentIdentifier = 0;
59     return ++currentIdentifier;
60 }
61
62 // --------
63
64 static bool shouldTrackVisitedLinks = false;
65
66 PageGroup::PageGroup(const String& name)
67     : m_name(name)
68     , m_visitedLinksPopulated(false)
69     , m_identifier(getUniqueIdentifier())
70     , m_userContentController(UserContentController::create())
71     , m_groupSettings(std::make_unique<GroupSettings>())
72 {
73 }
74
75 PageGroup::PageGroup(Page& page)
76     : m_visitedLinksPopulated(false)
77     , m_identifier(getUniqueIdentifier())
78     , m_userContentController(UserContentController::create())
79     , m_groupSettings(std::make_unique<GroupSettings>())
80 {
81     addPage(page);
82 }
83
84 PageGroup::~PageGroup()
85 {
86     removeAllUserContent();
87 }
88
89 typedef HashMap<String, PageGroup*> PageGroupMap;
90 static PageGroupMap* pageGroups = 0;
91
92 PageGroup* PageGroup::pageGroup(const String& groupName)
93 {
94     ASSERT(!groupName.isEmpty());
95     
96     if (!pageGroups)
97         pageGroups = new PageGroupMap;
98
99     PageGroupMap::AddResult result = pageGroups->add(groupName, nullptr);
100
101     if (result.isNewEntry) {
102         ASSERT(!result.iterator->value);
103         result.iterator->value = new PageGroup(groupName);
104     }
105
106     ASSERT(result.iterator->value);
107     return result.iterator->value;
108 }
109
110 void PageGroup::closeLocalStorage()
111 {
112     if (!pageGroups)
113         return;
114
115     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
116         if (it->value->hasLocalStorage())
117             it->value->localStorage()->close();
118     }
119 }
120
121 void PageGroup::clearLocalStorageForAllOrigins()
122 {
123     if (!pageGroups)
124         return;
125
126     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
127         if (it->value->hasLocalStorage())
128             it->value->localStorage()->clearAllOriginsForDeletion();
129     }
130 }
131
132 void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
133 {
134     if (!pageGroups)
135         return;
136
137     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
138         if (it->value->hasLocalStorage())
139             it->value->localStorage()->clearOriginForDeletion(origin);
140     }
141 }
142
143 void PageGroup::closeIdleLocalStorageDatabases()
144 {
145     if (!pageGroups)
146         return;
147
148     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
149         if (it->value->hasLocalStorage())
150             it->value->localStorage()->closeIdleLocalStorageDatabases();
151     }
152 }
153
154 void PageGroup::syncLocalStorage()
155 {
156     if (!pageGroups)
157         return;
158
159     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
160         if (it->value->hasLocalStorage())
161             it->value->localStorage()->sync();
162     }
163 }
164
165 void PageGroup::addPage(Page& page)
166 {
167     ASSERT(!m_pages.contains(&page));
168     m_pages.add(&page);
169
170     if (!page.userContentController())
171         page.setUserContentController(m_userContentController.get());
172 }
173
174 void PageGroup::removePage(Page& page)
175 {
176     ASSERT(m_pages.contains(&page));
177     m_pages.remove(&page);
178
179     if (page.userContentController() == m_userContentController)
180         page.setUserContentController(nullptr);
181 }
182
183 VisitedLinkStore& PageGroup::visitedLinkStore()
184 {
185     if (!m_visitedLinkStore)
186         m_visitedLinkStore = DefaultVisitedLinkStore::create();
187
188     return *m_visitedLinkStore;
189 }
190
191 bool PageGroup::isLinkVisited(LinkHash visitedLinkHash)
192 {
193     if (!m_visitedLinksPopulated) {
194         m_visitedLinksPopulated = true;
195         ASSERT(!m_pages.isEmpty());
196         (*m_pages.begin())->chrome().client().populateVisitedLinks();
197     }
198     return m_visitedLinkHashes.contains(visitedLinkHash);
199 }
200
201 void PageGroup::addVisitedLinkHash(LinkHash hash)
202 {
203     if (shouldTrackVisitedLinks)
204         addVisitedLink(hash);
205 }
206
207 inline void PageGroup::addVisitedLink(LinkHash hash)
208 {
209     ASSERT(shouldTrackVisitedLinks);
210     if (!m_visitedLinkHashes.add(hash).isNewEntry)
211         return;
212     for (auto& page : m_pages)
213         page->invalidateStylesForLink(hash);
214     pageCache()->markPagesForVistedLinkStyleRecalc();
215 }
216
217 void PageGroup::addVisitedLink(const URL& url)
218 {
219     if (!shouldTrackVisitedLinks)
220         return;
221     ASSERT(!url.isEmpty());
222     addVisitedLink(visitedLinkHash(url.string()));
223 }
224
225 void PageGroup::addVisitedLink(const UChar* characters, size_t length)
226 {
227     if (!shouldTrackVisitedLinks)
228         return;
229     addVisitedLink(visitedLinkHash(characters, length));
230 }
231
232 void PageGroup::removeVisitedLink(const URL& url)
233 {
234     LinkHash hash = visitedLinkHash(url.string());
235     ASSERT(m_visitedLinkHashes.contains(hash));
236     m_visitedLinkHashes.remove(hash);
237
238     // FIXME: Why can't we just invalidate the single visited link hash here?
239     for (auto& page : m_pages)
240         page->invalidateStylesForAllLinks();
241     pageCache()->markPagesForVistedLinkStyleRecalc();
242 }
243
244 void PageGroup::removeVisitedLinks()
245 {
246     m_visitedLinksPopulated = false;
247     if (m_visitedLinkHashes.isEmpty())
248         return;
249     m_visitedLinkHashes.clear();
250
251     for (auto& page : m_pages)
252         page->invalidateStylesForAllLinks();
253     pageCache()->markPagesForVistedLinkStyleRecalc();
254 }
255
256 void PageGroup::removeAllVisitedLinks()
257 {
258     Page::removeAllVisitedLinks();
259     pageCache()->markPagesForVistedLinkStyleRecalc();
260 }
261
262 void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
263 {
264     if (shouldTrackVisitedLinks == shouldTrack)
265         return;
266     shouldTrackVisitedLinks = shouldTrack;
267     if (!shouldTrackVisitedLinks)
268         removeAllVisitedLinks();
269 }
270
271 StorageNamespace* PageGroup::localStorage()
272 {
273     if (!m_localStorage)
274         m_localStorage = StorageNamespace::localStorageNamespace(this);
275
276     return m_localStorage.get();
277 }
278
279 StorageNamespace* PageGroup::transientLocalStorage(SecurityOrigin* topOrigin)
280 {
281     auto result = m_transientLocalStorageMap.add(topOrigin, nullptr);
282
283     if (result.isNewEntry)
284         result.iterator->value = StorageNamespace::transientLocalStorageNamespace(this, topOrigin);
285
286     return result.iterator->value.get();
287 }
288
289 void PageGroup::addUserScriptToWorld(DOMWrapperWorld& world, const String& source, const URL& url, const Vector<String>& whitelist, const Vector<String>& blacklist, UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
290 {
291     auto userScript = std::make_unique<UserScript>(source, url, whitelist, blacklist, injectionTime, injectedFrames);
292     m_userContentController->addUserScript(world, WTF::move(userScript));
293 }
294
295 void PageGroup::addUserStyleSheetToWorld(DOMWrapperWorld& world, const String& source, const URL& url, const Vector<String>& whitelist, const Vector<String>& blacklist, UserContentInjectedFrames injectedFrames, UserStyleLevel level, UserStyleInjectionTime injectionTime)
296 {
297     auto userStyleSheet = std::make_unique<UserStyleSheet>(source, url, whitelist, blacklist, injectedFrames, level);
298     m_userContentController->addUserStyleSheet(world, WTF::move(userStyleSheet), injectionTime);
299
300 }
301
302 void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld& world, const URL& url)
303 {
304     m_userContentController->removeUserScript(world, url);
305 }
306
307 void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld& world, const URL& url)
308 {
309     m_userContentController->removeUserStyleSheet(world, url);
310 }
311
312 void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld& world)
313 {
314     m_userContentController->removeUserScripts(world);
315 }
316
317 void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld& world)
318 {
319     m_userContentController->removeUserStyleSheets(world);
320 }
321
322 void PageGroup::removeAllUserContent()
323 {
324     m_userContentController->removeAllUserContent();
325 }
326
327 #if ENABLE(VIDEO_TRACK)
328 void PageGroup::captionPreferencesChanged()
329 {
330     for (auto it = m_pages.begin(), end = m_pages.end(); it != end; ++it)
331         (*it)->captionPreferencesChanged();
332     pageCache()->markPagesForCaptionPreferencesChanged();
333 }
334
335 CaptionUserPreferences* PageGroup::captionPreferences()
336 {
337     if (!m_captionPreferences) {
338 #if PLATFORM(MAC) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
339         m_captionPreferences = std::make_unique<CaptionUserPreferencesMediaAF>(*this);
340 #else
341         m_captionPreferences = std::make_unique<CaptionUserPreferences>(*this);
342 #endif
343     }
344
345     return m_captionPreferences.get();
346 }
347 #endif
348
349 } // namespace WebCore