Remove last ENABLED(INDEXED_DATABASE) ifdef from WebCore proper
[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 "Frame.h"
33 #include "GroupSettings.h"
34 #include "IDBFactoryBackendInterface.h"
35 #include "Page.h"
36 #include "PageCache.h"
37 #include "SecurityOrigin.h"
38 #include "Settings.h"
39 #include "StorageNamespace.h"
40
41 #if PLATFORM(CHROMIUM)
42 #include "PlatformSupport.h"
43 #endif
44
45 namespace WebCore {
46
47 static unsigned getUniqueIdentifier()
48 {
49     static unsigned currentIdentifier = 0;
50     return ++currentIdentifier;
51 }
52
53 // --------
54
55 static bool shouldTrackVisitedLinks = false;
56
57 PageGroup::PageGroup(const String& name)
58     : m_name(name)
59     , m_visitedLinksPopulated(false)
60     , m_identifier(getUniqueIdentifier())
61     , m_groupSettings(GroupSettings::create())
62 {
63 }
64
65 PageGroup::PageGroup(Page* page)
66     : m_visitedLinksPopulated(false)
67     , m_identifier(getUniqueIdentifier())
68     , m_groupSettings(GroupSettings::create())
69 {
70     ASSERT(page);
71     addPage(page);
72 }
73
74 PageGroup::~PageGroup()
75 {
76     removeAllUserContent();
77 }
78
79 PassOwnPtr<PageGroup> PageGroup::create(Page* page)
80 {
81     return adoptPtr(new PageGroup(page));
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     pair<PageGroupMap::iterator, bool> result = pageGroups->add(groupName, 0);
95
96     if (result.second) {
97         ASSERT(!result.first->second);
98         result.first->second = new PageGroup(groupName);
99     }
100
101     ASSERT(result.first->second);
102     return result.first->second;
103 }
104
105 void PageGroup::closeLocalStorage()
106 {
107     if (!pageGroups)
108         return;
109
110     PageGroupMap::iterator end = pageGroups->end();
111
112     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
113         if (it->second->hasLocalStorage())
114             it->second->localStorage()->close();
115     }
116 }
117
118 void PageGroup::clearLocalStorageForAllOrigins()
119 {
120     if (!pageGroups)
121         return;
122
123     PageGroupMap::iterator end = pageGroups->end();
124     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
125         if (it->second->hasLocalStorage())
126             it->second->localStorage()->clearAllOriginsForDeletion();
127     }
128 }
129
130 void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
131 {
132     if (!pageGroups)
133         return;
134
135     PageGroupMap::iterator end = pageGroups->end();
136     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
137         if (it->second->hasLocalStorage())
138             it->second->localStorage()->clearOriginForDeletion(origin);
139     }    
140 }
141     
142 void PageGroup::syncLocalStorage()
143 {
144     if (!pageGroups)
145         return;
146
147     PageGroupMap::iterator end = pageGroups->end();
148     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
149         if (it->second->hasLocalStorage())
150             it->second->localStorage()->sync();
151     }
152 }
153
154 unsigned PageGroup::numberOfPageGroups()
155 {
156     if (!pageGroups)
157         return 0;
158
159     return pageGroups->size();
160 }
161
162 void PageGroup::addPage(Page* page)
163 {
164     ASSERT(page);
165     ASSERT(!m_pages.contains(page));
166     m_pages.add(page);
167 }
168
169 void PageGroup::removePage(Page* page)
170 {
171     ASSERT(page);
172     ASSERT(m_pages.contains(page));
173     m_pages.remove(page);
174 }
175
176 bool PageGroup::isLinkVisited(LinkHash visitedLinkHash)
177 {
178 #if PLATFORM(CHROMIUM)
179     // Use Chromium's built-in visited link database.
180     return PlatformSupport::isLinkVisited(visitedLinkHash);
181 #else
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 #endif
189 }
190
191 void PageGroup::addVisitedLinkHash(LinkHash hash)
192 {
193     if (shouldTrackVisitedLinks)
194         addVisitedLink(hash);
195 }
196
197 inline void PageGroup::addVisitedLink(LinkHash hash)
198 {
199     ASSERT(shouldTrackVisitedLinks);
200 #if !PLATFORM(CHROMIUM)
201     if (!m_visitedLinkHashes.add(hash).second)
202         return;
203 #endif
204     Page::visitedStateChanged(this, hash);
205     pageCache()->markPagesForVistedLinkStyleRecalc();
206 }
207
208 void PageGroup::addVisitedLink(const KURL& url)
209 {
210     if (!shouldTrackVisitedLinks)
211         return;
212     ASSERT(!url.isEmpty());
213     addVisitedLink(visitedLinkHash(url.string().characters(), url.string().length()));
214 }
215
216 void PageGroup::addVisitedLink(const UChar* characters, size_t length)
217 {
218     if (!shouldTrackVisitedLinks)
219         return;
220     addVisitedLink(visitedLinkHash(characters, length));
221 }
222
223 void PageGroup::removeVisitedLinks()
224 {
225     m_visitedLinksPopulated = false;
226     if (m_visitedLinkHashes.isEmpty())
227         return;
228     m_visitedLinkHashes.clear();
229     Page::allVisitedStateChanged(this);
230     pageCache()->markPagesForVistedLinkStyleRecalc();
231 }
232
233 void PageGroup::removeAllVisitedLinks()
234 {
235     Page::removeAllVisitedLinks();
236     pageCache()->markPagesForVistedLinkStyleRecalc();
237 }
238
239 void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
240 {
241     if (shouldTrackVisitedLinks == shouldTrack)
242         return;
243     shouldTrackVisitedLinks = shouldTrack;
244     if (!shouldTrackVisitedLinks)
245         removeAllVisitedLinks();
246 }
247
248 StorageNamespace* PageGroup::localStorage()
249 {
250     if (!m_localStorage) {
251         // Need a page in this page group to query the settings for the local storage database path.
252         // Having these parameters attached to the page settings is unfortunate since these settings are
253         // not per-page (and, in fact, we simply grab the settings from some page at random), but
254         // at this point we're stuck with it.
255         Page* page = *m_pages.begin();
256         const String& path = page->settings()->localStorageDatabasePath();
257         unsigned quota = m_groupSettings->localStorageQuotaBytes();
258         m_localStorage = StorageNamespace::localStorageNamespace(path, quota);
259     }
260
261     return m_localStorage.get();
262 }
263
264 void PageGroup::addUserScriptToWorld(DOMWrapperWorld* world, const String& source, const KURL& url,
265                                      PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist,
266                                      UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
267 {
268     ASSERT_ARG(world, world);
269
270     OwnPtr<UserScript> userScript = adoptPtr(new UserScript(source, url, whitelist, blacklist, injectionTime, injectedFrames));
271     if (!m_userScripts)
272         m_userScripts = adoptPtr(new UserScriptMap);
273     OwnPtr<UserScriptVector>& scriptsInWorld = m_userScripts->add(world, nullptr).first->second;
274     if (!scriptsInWorld)
275         scriptsInWorld = adoptPtr(new UserScriptVector);
276     scriptsInWorld->append(userScript.release());
277 }
278
279 void PageGroup::addUserStyleSheetToWorld(DOMWrapperWorld* world, const String& source, const KURL& url,
280                                          PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist,
281                                          UserContentInjectedFrames injectedFrames,
282                                          UserStyleLevel level,
283                                          UserStyleInjectionTime injectionTime)
284 {
285     ASSERT_ARG(world, world);
286
287     OwnPtr<UserStyleSheet> userStyleSheet = adoptPtr(new UserStyleSheet(source, url, whitelist, blacklist, injectedFrames, level));
288     if (!m_userStyleSheets)
289         m_userStyleSheets = adoptPtr(new UserStyleSheetMap);
290     OwnPtr<UserStyleSheetVector>& styleSheetsInWorld = m_userStyleSheets->add(world, nullptr).first->second;
291     if (!styleSheetsInWorld)
292         styleSheetsInWorld = adoptPtr(new UserStyleSheetVector);
293     styleSheetsInWorld->append(userStyleSheet.release());
294
295     if (injectionTime == InjectInExistingDocuments)
296         resetUserStyleCacheInAllFrames();
297 }
298
299 void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld* world, const KURL& url)
300 {
301     ASSERT_ARG(world, world);
302
303     if (!m_userScripts)
304         return;
305
306     UserScriptMap::iterator it = m_userScripts->find(world);
307     if (it == m_userScripts->end())
308         return;
309     
310     UserScriptVector* scripts = it->second.get();
311     for (int i = scripts->size() - 1; i >= 0; --i) {
312         if (scripts->at(i)->url() == url)
313             scripts->remove(i);
314     }
315     
316     if (scripts->isEmpty())
317         m_userScripts->remove(it);
318 }
319
320 void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld* world, const KURL& url)
321 {
322     ASSERT_ARG(world, world);
323
324     if (!m_userStyleSheets)
325         return;
326
327     UserStyleSheetMap::iterator it = m_userStyleSheets->find(world);
328     bool sheetsChanged = false;
329     if (it == m_userStyleSheets->end())
330         return;
331     
332     UserStyleSheetVector* stylesheets = it->second.get();
333     for (int i = stylesheets->size() - 1; i >= 0; --i) {
334         if (stylesheets->at(i)->url() == url) {
335             stylesheets->remove(i);
336             sheetsChanged = true;
337         }
338     }
339         
340     if (!sheetsChanged)
341         return;
342
343     if (stylesheets->isEmpty())
344         m_userStyleSheets->remove(it);
345
346     resetUserStyleCacheInAllFrames();
347 }
348
349 void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld* world)
350 {
351     ASSERT_ARG(world, world);
352
353     if (!m_userScripts)
354         return;
355
356     UserScriptMap::iterator it = m_userScripts->find(world);
357     if (it == m_userScripts->end())
358         return;
359        
360     m_userScripts->remove(it);
361 }
362
363 void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld* world)
364 {
365     ASSERT_ARG(world, world);
366
367     if (!m_userStyleSheets)
368         return;
369     
370     UserStyleSheetMap::iterator it = m_userStyleSheets->find(world);
371     if (it == m_userStyleSheets->end())
372         return;
373     
374     m_userStyleSheets->remove(it);
375
376     resetUserStyleCacheInAllFrames();
377 }
378
379 void PageGroup::removeAllUserContent()
380 {
381     m_userScripts.clear();
382
383     if (m_userStyleSheets) {
384         m_userStyleSheets.clear();
385         resetUserStyleCacheInAllFrames();
386     }
387 }
388
389 void PageGroup::resetUserStyleCacheInAllFrames()
390 {
391     // Clear our cached sheets and have them just reparse.
392     HashSet<Page*>::const_iterator end = m_pages.end();
393     for (HashSet<Page*>::const_iterator it = m_pages.begin(); it != end; ++it) {
394         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
395             frame->document()->updatePageGroupUserSheets();
396     }
397 }
398
399 } // namespace WebCore