Convert PageGroup to using std::unique_ptr
[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 "Document.h"
33 #include "DocumentStyleSheetCollection.h"
34 #include "GroupSettings.h"
35 #include "MainFrame.h"
36 #include "Page.h"
37 #include "PageCache.h"
38 #include "SecurityOrigin.h"
39 #include "Settings.h"
40 #include "StorageNamespace.h"
41 #include <wtf/StdLibExtras.h>
42
43 #if ENABLE(VIDEO_TRACK)
44 #if (PLATFORM(MAC) && !PLATFORM(IOS)) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
45 #include "CaptionUserPreferencesMediaAF.h"
46 #else
47 #include "CaptionUserPreferences.h"
48 #endif
49 #endif
50
51 namespace WebCore {
52
53 static unsigned getUniqueIdentifier()
54 {
55     static unsigned currentIdentifier = 0;
56     return ++currentIdentifier;
57 }
58
59 // --------
60
61 static bool shouldTrackVisitedLinks = false;
62
63 PageGroup::PageGroup(const String& name)
64     : m_name(name)
65     , m_visitedLinksPopulated(false)
66     , m_identifier(getUniqueIdentifier())
67     , m_groupSettings(std::make_unique<GroupSettings>())
68 {
69 }
70
71 PageGroup::PageGroup(Page& page)
72     : m_visitedLinksPopulated(false)
73     , m_identifier(getUniqueIdentifier())
74     , m_groupSettings(std::make_unique<GroupSettings>())
75 {
76     addPage(page);
77 }
78
79 PageGroup::~PageGroup()
80 {
81     removeAllUserContent();
82 }
83
84 typedef HashMap<String, PageGroup*> PageGroupMap;
85 static PageGroupMap* pageGroups = 0;
86
87 PageGroup* PageGroup::pageGroup(const String& groupName)
88 {
89     ASSERT(!groupName.isEmpty());
90     
91     if (!pageGroups)
92         pageGroups = new PageGroupMap;
93
94     PageGroupMap::AddResult result = pageGroups->add(groupName, nullptr);
95
96     if (result.isNewEntry) {
97         ASSERT(!result.iterator->value);
98         result.iterator->value = new PageGroup(groupName);
99     }
100
101     ASSERT(result.iterator->value);
102     return result.iterator->value;
103 }
104
105 void PageGroup::closeLocalStorage()
106 {
107     if (!pageGroups)
108         return;
109
110     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
111         if (it->value->hasLocalStorage())
112             it->value->localStorage()->close();
113     }
114 }
115
116 void PageGroup::clearLocalStorageForAllOrigins()
117 {
118     if (!pageGroups)
119         return;
120
121     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
122         if (it->value->hasLocalStorage())
123             it->value->localStorage()->clearAllOriginsForDeletion();
124     }
125 }
126
127 void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
128 {
129     if (!pageGroups)
130         return;
131
132     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
133         if (it->value->hasLocalStorage())
134             it->value->localStorage()->clearOriginForDeletion(origin);
135     }
136 }
137
138 void PageGroup::closeIdleLocalStorageDatabases()
139 {
140     if (!pageGroups)
141         return;
142
143     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
144         if (it->value->hasLocalStorage())
145             it->value->localStorage()->closeIdleLocalStorageDatabases();
146     }
147 }
148
149 void PageGroup::syncLocalStorage()
150 {
151     if (!pageGroups)
152         return;
153
154     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
155         if (it->value->hasLocalStorage())
156             it->value->localStorage()->sync();
157     }
158 }
159
160 unsigned PageGroup::numberOfPageGroups()
161 {
162     if (!pageGroups)
163         return 0;
164
165     return pageGroups->size();
166 }
167
168 void PageGroup::addPage(Page& page)
169 {
170     ASSERT(!m_pages.contains(&page));
171     m_pages.add(&page);
172 }
173
174 void PageGroup::removePage(Page& page)
175 {
176     ASSERT(m_pages.contains(&page));
177     m_pages.remove(&page);
178 }
179
180 bool PageGroup::isLinkVisited(LinkHash visitedLinkHash)
181 {
182     if (!m_visitedLinksPopulated) {
183         m_visitedLinksPopulated = true;
184         ASSERT(!m_pages.isEmpty());
185         (*m_pages.begin())->chrome().client().populateVisitedLinks();
186     }
187     return m_visitedLinkHashes.contains(visitedLinkHash);
188 }
189
190 void PageGroup::addVisitedLinkHash(LinkHash hash)
191 {
192     if (shouldTrackVisitedLinks)
193         addVisitedLink(hash);
194 }
195
196 inline void PageGroup::addVisitedLink(LinkHash hash)
197 {
198     ASSERT(shouldTrackVisitedLinks);
199     if (!m_visitedLinkHashes.add(hash).isNewEntry)
200         return;
201     Page::visitedStateChanged(this, hash);
202     pageCache()->markPagesForVistedLinkStyleRecalc();
203 }
204
205 void PageGroup::addVisitedLink(const URL& url)
206 {
207     if (!shouldTrackVisitedLinks)
208         return;
209     ASSERT(!url.isEmpty());
210     addVisitedLink(visitedLinkHash(url.string()));
211 }
212
213 void PageGroup::addVisitedLink(const UChar* characters, size_t length)
214 {
215     if (!shouldTrackVisitedLinks)
216         return;
217     addVisitedLink(visitedLinkHash(characters, length));
218 }
219
220 void PageGroup::removeVisitedLinks()
221 {
222     m_visitedLinksPopulated = false;
223     if (m_visitedLinkHashes.isEmpty())
224         return;
225     m_visitedLinkHashes.clear();
226     Page::allVisitedStateChanged(this);
227     pageCache()->markPagesForVistedLinkStyleRecalc();
228 }
229
230 void PageGroup::removeAllVisitedLinks()
231 {
232     Page::removeAllVisitedLinks();
233     pageCache()->markPagesForVistedLinkStyleRecalc();
234 }
235
236 void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
237 {
238     if (shouldTrackVisitedLinks == shouldTrack)
239         return;
240     shouldTrackVisitedLinks = shouldTrack;
241     if (!shouldTrackVisitedLinks)
242         removeAllVisitedLinks();
243 }
244
245 StorageNamespace* PageGroup::localStorage()
246 {
247     if (!m_localStorage)
248         m_localStorage = StorageNamespace::localStorageNamespace(this);
249
250     return m_localStorage.get();
251 }
252
253 StorageNamespace* PageGroup::transientLocalStorage(SecurityOrigin* topOrigin)
254 {
255     auto result = m_transientLocalStorageMap.add(topOrigin, nullptr);
256
257     if (result.isNewEntry)
258         result.iterator->value = StorageNamespace::transientLocalStorageNamespace(this, topOrigin);
259
260     return result.iterator->value.get();
261 }
262
263 void PageGroup::addUserScriptToWorld(DOMWrapperWorld* world, const String& source, const URL& url,
264                                      const Vector<String>& whitelist, const Vector<String>& blacklist,
265                                      UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
266 {
267     ASSERT_ARG(world, world);
268
269     auto userScript = std::make_unique<UserScript>(source, url, whitelist, blacklist, injectionTime, injectedFrames);
270     if (!m_userScripts)
271         m_userScripts = std::make_unique<UserScriptMap>();
272     std::unique_ptr<UserScriptVector>& scriptsInWorld = m_userScripts->add(world, nullptr).iterator->value;
273     if (!scriptsInWorld)
274         scriptsInWorld = std::make_unique<UserScriptVector>();
275     scriptsInWorld->append(std::move(userScript));
276 }
277
278 void PageGroup::addUserStyleSheetToWorld(DOMWrapperWorld* world, const String& source, const URL& url,
279                                          const Vector<String>& whitelist, const Vector<String>& blacklist,
280                                          UserContentInjectedFrames injectedFrames,
281                                          UserStyleLevel level,
282                                          UserStyleInjectionTime injectionTime)
283 {
284     ASSERT_ARG(world, world);
285
286     auto userStyleSheet = std::make_unique<UserStyleSheet>(source, url, whitelist, blacklist, injectedFrames, level);
287     if (!m_userStyleSheets)
288         m_userStyleSheets = std::make_unique<UserStyleSheetMap>();
289     std::unique_ptr<UserStyleSheetVector>& styleSheetsInWorld = m_userStyleSheets->add(world, nullptr).iterator->value;
290     if (!styleSheetsInWorld)
291         styleSheetsInWorld = std::make_unique<UserStyleSheetVector>();
292     styleSheetsInWorld->append(std::move(userStyleSheet));
293
294     if (injectionTime == InjectInExistingDocuments)
295         invalidateInjectedStyleSheetCacheInAllFrames();
296 }
297
298 void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld* world, const URL& url)
299 {
300     ASSERT_ARG(world, world);
301
302     if (!m_userScripts)
303         return;
304
305     auto it = m_userScripts->find(world);
306     if (it == m_userScripts->end())
307         return;
308     
309     auto scripts = it->value.get();
310     for (int i = scripts->size() - 1; i >= 0; --i) {
311         if (scripts->at(i)->url() == url)
312             scripts->remove(i);
313     }
314     
315     if (scripts->isEmpty())
316         m_userScripts->remove(it);
317 }
318
319 void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld* world, const URL& url)
320 {
321     ASSERT_ARG(world, world);
322
323     if (!m_userStyleSheets)
324         return;
325
326     auto it = m_userStyleSheets->find(world);
327     bool sheetsChanged = false;
328     if (it == m_userStyleSheets->end())
329         return;
330     
331     auto stylesheets = it->value.get();
332     for (int i = stylesheets->size() - 1; i >= 0; --i) {
333         if (stylesheets->at(i)->url() == url) {
334             stylesheets->remove(i);
335             sheetsChanged = true;
336         }
337     }
338         
339     if (!sheetsChanged)
340         return;
341
342     if (stylesheets->isEmpty())
343         m_userStyleSheets->remove(it);
344
345     invalidateInjectedStyleSheetCacheInAllFrames();
346 }
347
348 void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld* world)
349 {
350     ASSERT_ARG(world, world);
351
352     if (!m_userScripts)
353         return;
354
355     m_userScripts->remove(world);
356 }
357
358 void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld* world)
359 {
360     ASSERT_ARG(world, world);
361
362     if (!m_userStyleSheets)
363         return;
364
365     if (!m_userStyleSheets->remove(world))
366         return;
367
368     invalidateInjectedStyleSheetCacheInAllFrames();
369 }
370
371 void PageGroup::removeAllUserContent()
372 {
373     m_userScripts = nullptr;
374
375     if (m_userStyleSheets) {
376         m_userStyleSheets = nullptr;
377         invalidateInjectedStyleSheetCacheInAllFrames();
378     }
379 }
380
381 void PageGroup::invalidateInjectedStyleSheetCacheInAllFrames()
382 {
383     // Clear our cached sheets and have them just reparse.
384     for (auto it = m_pages.begin(), end = m_pages.end(); it != end; ++it) {
385         for (Frame* frame = &(*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
386             frame->document()->styleSheetCollection().invalidateInjectedStyleSheetCache();
387             frame->document()->styleResolverChanged(DeferRecalcStyle);
388         }
389     }
390 }
391
392 #if ENABLE(VIDEO_TRACK)
393 void PageGroup::captionPreferencesChanged()
394 {
395     for (auto it = m_pages.begin(), end = m_pages.end(); it != end; ++it)
396         (*it)->captionPreferencesChanged();
397     pageCache()->markPagesForCaptionPreferencesChanged();
398 }
399
400 CaptionUserPreferences* PageGroup::captionPreferences()
401 {
402     if (!m_captionPreferences) {
403 #if (PLATFORM(MAC) && !PLATFORM(IOS)) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
404         m_captionPreferences = std::make_unique<CaptionUserPreferencesMediaAF>(*this);
405 #else
406         m_captionPreferences = std::make_unique<CaptionUserPreferences>(*this);
407 #endif
408     }
409
410     return m_captionPreferences.get();
411 }
412 #endif
413
414 } // namespace WebCore