Remove Chromium code from WebCore/page
[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 "Document.h"
32 #include "DocumentStyleSheetCollection.h"
33 #include "Frame.h"
34 #include "GroupSettings.h"
35 #include "Page.h"
36 #include "PageCache.h"
37 #include "SecurityOrigin.h"
38 #include "Settings.h"
39 #include "StorageNamespace.h"
40
41 #if ENABLE(VIDEO_TRACK)
42 #if (PLATFORM(MAC) && !PLATFORM(IOS)) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
43 #include "CaptionUserPreferencesMac.h"
44 #else
45 #include "CaptionUserPreferences.h"
46 #endif
47 #endif
48
49 namespace WebCore {
50
51 static unsigned getUniqueIdentifier()
52 {
53     static unsigned currentIdentifier = 0;
54     return ++currentIdentifier;
55 }
56
57 // --------
58
59 static bool shouldTrackVisitedLinks = false;
60
61 PageGroup::PageGroup(const String& name)
62     : m_name(name)
63     , m_visitedLinksPopulated(false)
64     , m_identifier(getUniqueIdentifier())
65     , m_groupSettings(GroupSettings::create())
66 {
67 }
68
69 PageGroup::PageGroup(Page* page)
70     : m_visitedLinksPopulated(false)
71     , m_identifier(getUniqueIdentifier())
72     , m_groupSettings(GroupSettings::create())
73 {
74     ASSERT(page);
75     addPage(page);
76 }
77
78 PageGroup::~PageGroup()
79 {
80     removeAllUserContent();
81 }
82
83 PassOwnPtr<PageGroup> PageGroup::create(Page* page)
84 {
85     return adoptPtr(new PageGroup(page));
86 }
87
88 typedef HashMap<String, PageGroup*> PageGroupMap;
89 static PageGroupMap* pageGroups = 0;
90
91 PageGroup* PageGroup::pageGroup(const String& groupName)
92 {
93     ASSERT(!groupName.isEmpty());
94     
95     if (!pageGroups)
96         pageGroups = new PageGroupMap;
97
98     PageGroupMap::AddResult result = pageGroups->add(groupName, 0);
99
100     if (result.isNewEntry) {
101         ASSERT(!result.iterator->value);
102         result.iterator->value = new PageGroup(groupName);
103     }
104
105     ASSERT(result.iterator->value);
106     return result.iterator->value;
107 }
108
109 void PageGroup::closeLocalStorage()
110 {
111     if (!pageGroups)
112         return;
113
114     PageGroupMap::iterator end = pageGroups->end();
115
116     for (PageGroupMap::iterator it = pageGroups->begin(); 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     PageGroupMap::iterator end = pageGroups->end();
128     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
129         if (it->value->hasLocalStorage())
130             it->value->localStorage()->clearAllOriginsForDeletion();
131     }
132 }
133
134 void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
135 {
136     if (!pageGroups)
137         return;
138
139     PageGroupMap::iterator end = pageGroups->end();
140     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
141         if (it->value->hasLocalStorage())
142             it->value->localStorage()->clearOriginForDeletion(origin);
143     }
144 }
145
146 void PageGroup::closeIdleLocalStorageDatabases()
147 {
148     if (!pageGroups)
149         return;
150
151     PageGroupMap::iterator end = pageGroups->end();
152     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
153         if (it->value->hasLocalStorage())
154             it->value->localStorage()->closeIdleLocalStorageDatabases();
155     }
156 }
157
158 void PageGroup::syncLocalStorage()
159 {
160     if (!pageGroups)
161         return;
162
163     PageGroupMap::iterator end = pageGroups->end();
164     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
165         if (it->value->hasLocalStorage())
166             it->value->localStorage()->sync();
167     }
168 }
169
170 unsigned PageGroup::numberOfPageGroups()
171 {
172     if (!pageGroups)
173         return 0;
174
175     return pageGroups->size();
176 }
177
178 void PageGroup::addPage(Page* page)
179 {
180     ASSERT(page);
181     ASSERT(!m_pages.contains(page));
182     m_pages.add(page);
183 }
184
185 void PageGroup::removePage(Page* page)
186 {
187     ASSERT(page);
188     ASSERT(m_pages.contains(page));
189     m_pages.remove(page);
190 }
191
192 bool PageGroup::isLinkVisited(LinkHash visitedLinkHash)
193 {
194     if (!m_visitedLinksPopulated) {
195         m_visitedLinksPopulated = true;
196         ASSERT(!m_pages.isEmpty());
197         (*m_pages.begin())->chrome()->client()->populateVisitedLinks();
198     }
199     return m_visitedLinkHashes.contains(visitedLinkHash);
200 }
201
202 void PageGroup::addVisitedLinkHash(LinkHash hash)
203 {
204     if (shouldTrackVisitedLinks)
205         addVisitedLink(hash);
206 }
207
208 inline void PageGroup::addVisitedLink(LinkHash hash)
209 {
210     ASSERT(shouldTrackVisitedLinks);
211     if (!m_visitedLinkHashes.add(hash).isNewEntry)
212         return;
213     Page::visitedStateChanged(this, hash);
214     pageCache()->markPagesForVistedLinkStyleRecalc();
215 }
216
217 void PageGroup::addVisitedLink(const KURL& 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::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         // Need a page in this page group to query the settings for the local storage database path.
261         // Having these parameters attached to the page settings is unfortunate since these settings are
262         // not per-page (and, in fact, we simply grab the settings from some page at random), but
263         // at this point we're stuck with it.
264         Page* page = *m_pages.begin();
265         const String& path = page->settings()->localStorageDatabasePath();
266         unsigned quota = m_groupSettings->localStorageQuotaBytes();
267         m_localStorage = StorageNamespace::localStorageNamespace(path, quota);
268     }
269
270     return m_localStorage.get();
271 }
272
273 void PageGroup::addUserScriptToWorld(DOMWrapperWorld* world, const String& source, const KURL& url,
274                                      const Vector<String>& whitelist, const Vector<String>& blacklist,
275                                      UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
276 {
277     ASSERT_ARG(world, world);
278
279     OwnPtr<UserScript> userScript = adoptPtr(new UserScript(source, url, whitelist, blacklist, injectionTime, injectedFrames));
280     if (!m_userScripts)
281         m_userScripts = adoptPtr(new UserScriptMap);
282     OwnPtr<UserScriptVector>& scriptsInWorld = m_userScripts->add(world, nullptr).iterator->value;
283     if (!scriptsInWorld)
284         scriptsInWorld = adoptPtr(new UserScriptVector);
285     scriptsInWorld->append(userScript.release());
286 }
287
288 void PageGroup::addUserStyleSheetToWorld(DOMWrapperWorld* world, const String& source, const KURL& url,
289                                          const Vector<String>& whitelist, const Vector<String>& blacklist,
290                                          UserContentInjectedFrames injectedFrames,
291                                          UserStyleLevel level,
292                                          UserStyleInjectionTime injectionTime)
293 {
294     ASSERT_ARG(world, world);
295
296     OwnPtr<UserStyleSheet> userStyleSheet = adoptPtr(new UserStyleSheet(source, url, whitelist, blacklist, injectedFrames, level));
297     if (!m_userStyleSheets)
298         m_userStyleSheets = adoptPtr(new UserStyleSheetMap);
299     OwnPtr<UserStyleSheetVector>& styleSheetsInWorld = m_userStyleSheets->add(world, nullptr).iterator->value;
300     if (!styleSheetsInWorld)
301         styleSheetsInWorld = adoptPtr(new UserStyleSheetVector);
302     styleSheetsInWorld->append(userStyleSheet.release());
303
304     if (injectionTime == InjectInExistingDocuments)
305         invalidatedInjectedStyleSheetCacheInAllFrames();
306 }
307
308 void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld* world, const KURL& url)
309 {
310     ASSERT_ARG(world, world);
311
312     if (!m_userScripts)
313         return;
314
315     UserScriptMap::iterator it = m_userScripts->find(world);
316     if (it == m_userScripts->end())
317         return;
318     
319     UserScriptVector* scripts = it->value.get();
320     for (int i = scripts->size() - 1; i >= 0; --i) {
321         if (scripts->at(i)->url() == url)
322             scripts->remove(i);
323     }
324     
325     if (scripts->isEmpty())
326         m_userScripts->remove(it);
327 }
328
329 void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld* world, const KURL& url)
330 {
331     ASSERT_ARG(world, world);
332
333     if (!m_userStyleSheets)
334         return;
335
336     UserStyleSheetMap::iterator it = m_userStyleSheets->find(world);
337     bool sheetsChanged = false;
338     if (it == m_userStyleSheets->end())
339         return;
340     
341     UserStyleSheetVector* stylesheets = it->value.get();
342     for (int i = stylesheets->size() - 1; i >= 0; --i) {
343         if (stylesheets->at(i)->url() == url) {
344             stylesheets->remove(i);
345             sheetsChanged = true;
346         }
347     }
348         
349     if (!sheetsChanged)
350         return;
351
352     if (stylesheets->isEmpty())
353         m_userStyleSheets->remove(it);
354
355     invalidatedInjectedStyleSheetCacheInAllFrames();
356 }
357
358 void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld* world)
359 {
360     ASSERT_ARG(world, world);
361
362     if (!m_userScripts)
363         return;
364
365     UserScriptMap::iterator it = m_userScripts->find(world);
366     if (it == m_userScripts->end())
367         return;
368        
369     m_userScripts->remove(it);
370 }
371
372 void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld* world)
373 {
374     ASSERT_ARG(world, world);
375
376     if (!m_userStyleSheets)
377         return;
378     
379     UserStyleSheetMap::iterator it = m_userStyleSheets->find(world);
380     if (it == m_userStyleSheets->end())
381         return;
382     
383     m_userStyleSheets->remove(it);
384
385     invalidatedInjectedStyleSheetCacheInAllFrames();
386 }
387
388 void PageGroup::removeAllUserContent()
389 {
390     m_userScripts.clear();
391
392     if (m_userStyleSheets) {
393         m_userStyleSheets.clear();
394         invalidatedInjectedStyleSheetCacheInAllFrames();
395     }
396 }
397
398 void PageGroup::invalidatedInjectedStyleSheetCacheInAllFrames()
399 {
400     // Clear our cached sheets and have them just reparse.
401     HashSet<Page*>::const_iterator end = m_pages.end();
402     for (HashSet<Page*>::const_iterator it = m_pages.begin(); it != end; ++it) {
403         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
404             frame->document()->styleSheetCollection()->invalidateInjectedStyleSheetCache();
405     }
406 }
407
408 #if ENABLE(VIDEO_TRACK)
409 void PageGroup::captionPreferencesChanged()
410 {
411     for (HashSet<Page*>::iterator i = m_pages.begin(); i != m_pages.end(); ++i)
412         (*i)->captionPreferencesChanged();
413     pageCache()->markPagesForCaptionPreferencesChanged();
414 }
415
416 CaptionUserPreferences* PageGroup::captionPreferences()
417 {
418     if (!m_captionPreferences)
419 #if (PLATFORM(MAC) && !PLATFORM(IOS)) || HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
420         m_captionPreferences = CaptionUserPreferencesMac::create(this);
421 #else
422         m_captionPreferences = CaptionUserPreferences::create(this);
423 #endif
424
425     return m_captionPreferences.get();
426 }
427
428 #endif
429
430 } // namespace WebCore