Unreviewed, rolling out r163048.
[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 "UserContentController.h"
42 #include "VisitedLinkProvider.h"
43 #include <wtf/StdLibExtras.h>
44
45 #if ENABLE(VIDEO_TRACK)
46 #if (PLATFORM(MAC) && !PLATFORM(IOS)) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
47 #include "CaptionUserPreferencesMediaAF.h"
48 #else
49 #include "CaptionUserPreferences.h"
50 #endif
51 #endif
52
53 namespace WebCore {
54
55 static unsigned getUniqueIdentifier()
56 {
57     static unsigned currentIdentifier = 0;
58     return ++currentIdentifier;
59 }
60
61 // --------
62
63 static bool shouldTrackVisitedLinks = false;
64
65 PageGroup::PageGroup(const String& name)
66     : m_name(name)
67     , m_visitedLinkProvider(VisitedLinkProvider::create())
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_visitedLinkProvider(VisitedLinkProvider::create())
77     , m_visitedLinksPopulated(false)
78     , m_identifier(getUniqueIdentifier())
79     , m_userContentController(UserContentController::create())
80     , m_groupSettings(std::make_unique<GroupSettings>())
81 {
82     addPage(page);
83 }
84
85 PageGroup::~PageGroup()
86 {
87     removeAllUserContent();
88 }
89
90 typedef HashMap<String, PageGroup*> PageGroupMap;
91 static PageGroupMap* pageGroups = 0;
92
93 PageGroup* PageGroup::pageGroup(const String& groupName)
94 {
95     ASSERT(!groupName.isEmpty());
96     
97     if (!pageGroups)
98         pageGroups = new PageGroupMap;
99
100     PageGroupMap::AddResult result = pageGroups->add(groupName, nullptr);
101
102     if (result.isNewEntry) {
103         ASSERT(!result.iterator->value);
104         result.iterator->value = new PageGroup(groupName);
105     }
106
107     ASSERT(result.iterator->value);
108     return result.iterator->value;
109 }
110
111 void PageGroup::closeLocalStorage()
112 {
113     if (!pageGroups)
114         return;
115
116     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
117         if (it->value->hasLocalStorage())
118             it->value->localStorage()->close();
119     }
120 }
121
122 void PageGroup::clearLocalStorageForAllOrigins()
123 {
124     if (!pageGroups)
125         return;
126
127     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
128         if (it->value->hasLocalStorage())
129             it->value->localStorage()->clearAllOriginsForDeletion();
130     }
131 }
132
133 void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
134 {
135     if (!pageGroups)
136         return;
137
138     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
139         if (it->value->hasLocalStorage())
140             it->value->localStorage()->clearOriginForDeletion(origin);
141     }
142 }
143
144 void PageGroup::closeIdleLocalStorageDatabases()
145 {
146     if (!pageGroups)
147         return;
148
149     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
150         if (it->value->hasLocalStorage())
151             it->value->localStorage()->closeIdleLocalStorageDatabases();
152     }
153 }
154
155 void PageGroup::syncLocalStorage()
156 {
157     if (!pageGroups)
158         return;
159
160     for (auto it = pageGroups->begin(), end = pageGroups->end(); it != end; ++it) {
161         if (it->value->hasLocalStorage())
162             it->value->localStorage()->sync();
163     }
164 }
165
166 void PageGroup::addPage(Page& page)
167 {
168     ASSERT(!m_pages.contains(&page));
169     m_pages.add(&page);
170
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     page.setUserContentController(nullptr);
180 }
181
182 bool PageGroup::isLinkVisited(LinkHash visitedLinkHash)
183 {
184     if (!m_visitedLinksPopulated) {
185         m_visitedLinksPopulated = true;
186         ASSERT(!m_pages.isEmpty());
187         (*m_pages.begin())->chrome().client().populateVisitedLinks();
188     }
189     return m_visitedLinkHashes.contains(visitedLinkHash);
190 }
191
192 void PageGroup::addVisitedLinkHash(LinkHash hash)
193 {
194     if (shouldTrackVisitedLinks)
195         addVisitedLink(hash);
196 }
197
198 inline void PageGroup::addVisitedLink(LinkHash hash)
199 {
200     ASSERT(shouldTrackVisitedLinks);
201     if (!m_visitedLinkHashes.add(hash).isNewEntry)
202         return;
203     Page::visitedStateChanged(this, hash);
204     pageCache()->markPagesForVistedLinkStyleRecalc();
205 }
206
207 void PageGroup::addVisitedLink(const URL& url)
208 {
209     if (!shouldTrackVisitedLinks)
210         return;
211     ASSERT(!url.isEmpty());
212     addVisitedLink(visitedLinkHash(url.string()));
213 }
214
215 void PageGroup::addVisitedLink(const UChar* characters, size_t length)
216 {
217     if (!shouldTrackVisitedLinks)
218         return;
219     addVisitedLink(visitedLinkHash(characters, length));
220 }
221
222 void PageGroup::removeVisitedLink(const URL& url)
223 {
224     LinkHash hash = visitedLinkHash(url.string());
225     ASSERT(m_visitedLinkHashes.contains(hash));
226     m_visitedLinkHashes.remove(hash);
227
228     Page::allVisitedStateChanged(this);
229     pageCache()->markPagesForVistedLinkStyleRecalc();
230 }
231
232 void PageGroup::removeVisitedLinks()
233 {
234     m_visitedLinksPopulated = false;
235     if (m_visitedLinkHashes.isEmpty())
236         return;
237     m_visitedLinkHashes.clear();
238     Page::allVisitedStateChanged(this);
239     pageCache()->markPagesForVistedLinkStyleRecalc();
240 }
241
242 void PageGroup::removeAllVisitedLinks()
243 {
244     Page::removeAllVisitedLinks();
245     pageCache()->markPagesForVistedLinkStyleRecalc();
246 }
247
248 void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
249 {
250     if (shouldTrackVisitedLinks == shouldTrack)
251         return;
252     shouldTrackVisitedLinks = shouldTrack;
253     if (!shouldTrackVisitedLinks)
254         removeAllVisitedLinks();
255 }
256
257 StorageNamespace* PageGroup::localStorage()
258 {
259     if (!m_localStorage)
260         m_localStorage = StorageNamespace::localStorageNamespace(this);
261
262     return m_localStorage.get();
263 }
264
265 StorageNamespace* PageGroup::transientLocalStorage(SecurityOrigin* topOrigin)
266 {
267     auto result = m_transientLocalStorageMap.add(topOrigin, nullptr);
268
269     if (result.isNewEntry)
270         result.iterator->value = StorageNamespace::transientLocalStorageNamespace(this, topOrigin);
271
272     return result.iterator->value.get();
273 }
274
275 void PageGroup::addUserScriptToWorld(DOMWrapperWorld& world, const String& source, const URL& url, const Vector<String>& whitelist, const Vector<String>& blacklist, UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
276 {
277     auto userScript = std::make_unique<UserScript>(source, url, whitelist, blacklist, injectionTime, injectedFrames);
278     m_userContentController->addUserScript(world, std::move(userScript));
279 }
280
281 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)
282 {
283     auto userStyleSheet = std::make_unique<UserStyleSheet>(source, url, whitelist, blacklist, injectedFrames, level);
284     m_userContentController->addUserStyleSheet(world, std::move(userStyleSheet), injectionTime);
285
286 }
287
288 void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld& world, const URL& url)
289 {
290     m_userContentController->removeUserScript(world, url);
291 }
292
293 void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld& world, const URL& url)
294 {
295     m_userContentController->removeUserStyleSheet(world, url);
296 }
297
298 void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld& world)
299 {
300     m_userContentController->removeUserScripts(world);
301 }
302
303 void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld& world)
304 {
305     m_userContentController->removeUserStyleSheets(world);
306 }
307
308 void PageGroup::removeAllUserContent()
309 {
310     m_userContentController->removeAllUserContent();
311 }
312
313 #if ENABLE(VIDEO_TRACK)
314 void PageGroup::captionPreferencesChanged()
315 {
316     for (auto it = m_pages.begin(), end = m_pages.end(); it != end; ++it)
317         (*it)->captionPreferencesChanged();
318     pageCache()->markPagesForCaptionPreferencesChanged();
319 }
320
321 CaptionUserPreferences* PageGroup::captionPreferences()
322 {
323     if (!m_captionPreferences) {
324 #if (PLATFORM(MAC) && !PLATFORM(IOS)) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
325         m_captionPreferences = std::make_unique<CaptionUserPreferencesMediaAF>(*this);
326 #else
327         m_captionPreferences = std::make_unique<CaptionUserPreferences>(*this);
328 #endif
329     }
330
331     return m_captionPreferences.get();
332 }
333 #endif
334
335 } // namespace WebCore