WebCore:
[WebKit-https.git] / 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 "ChromeClient.h"
30 #include "Document.h"
31 #include "Page.h"
32 #include "Settings.h"
33
34 #if ENABLE(DOM_STORAGE)
35 #include "LocalStorage.h"
36 #include "StorageArea.h"
37 #endif
38
39 namespace WebCore {
40
41 static unsigned getUniqueIdentifier()
42 {
43     static unsigned currentIdentifier = 0;
44     return ++currentIdentifier;
45 }
46
47 // --------
48
49 static bool shouldTrackVisitedLinks;
50
51 PageGroup::PageGroup(const String& name)
52     : m_name(name)
53     , m_visitedLinksPopulated(false)
54     , m_identifier(getUniqueIdentifier())
55 {
56 }
57
58 PageGroup::PageGroup(Page* page)
59     : m_visitedLinksPopulated(false)
60     , m_identifier(getUniqueIdentifier())
61 {
62     ASSERT(page);
63     m_pages.add(page);
64 }
65
66 typedef HashMap<String, PageGroup*> PageGroupMap;
67 static PageGroupMap* pageGroups = 0;
68
69 PageGroup* PageGroup::pageGroup(const String& groupName)
70 {
71     ASSERT(!groupName.isEmpty());
72     
73     if (!pageGroups)
74         pageGroups = new PageGroupMap;
75
76     pair<PageGroupMap::iterator, bool> result = pageGroups->add(groupName, 0);
77
78     if (result.second) {
79         ASSERT(!result.first->second);
80         result.first->second = new PageGroup(groupName);
81     }
82
83     ASSERT(result.first->second);
84     return result.first->second;
85 }
86
87 void PageGroup::closeLocalStorage()
88 {
89     if (!pageGroups)
90         return;
91
92     PageGroupMap::iterator end = pageGroups->end();
93
94     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
95         if (LocalStorage* localStorage = it->second->localStorage())
96             localStorage->close();
97     }
98 }
99
100 void PageGroup::addPage(Page* page)
101 {
102     ASSERT(page);
103     ASSERT(!m_pages.contains(page));
104     m_pages.add(page);
105 #if ENABLE(DOM_STORAGE)
106     if (!m_localStorage)
107         m_localStorage = LocalStorage::create(this, page->settings()->localStorageDatabasePath());
108 #endif
109 }
110
111 void PageGroup::removePage(Page* page)
112 {
113     ASSERT(page);
114     ASSERT(m_pages.contains(page));
115     m_pages.remove(page);
116 }
117
118 bool PageGroup::isLinkVisited(unsigned visitedLinkHash)
119 {
120     if (!m_visitedLinksPopulated) {
121         m_visitedLinksPopulated = true;
122         ASSERT(!m_pages.isEmpty());
123         (*m_pages.begin())->chrome()->client()->populateVisitedLinks();
124     }
125     return m_visitedLinkHashes.contains(visitedLinkHash);
126 }
127
128 inline void PageGroup::addVisitedLink(unsigned stringHash)
129 {
130     ASSERT(shouldTrackVisitedLinks);
131     unsigned visitedLinkHash = AlreadyHashed::avoidDeletedValue(stringHash);
132     if (!m_visitedLinkHashes.add(visitedLinkHash).second)
133         return;
134     Page::visitedStateChanged(this, visitedLinkHash);
135 }
136
137 void PageGroup::addVisitedLink(const KURL& url)
138 {
139     if (!shouldTrackVisitedLinks)
140         return;
141     ASSERT(!url.isEmpty());
142     addVisitedLink(url.string().impl()->hash());
143 }
144
145 void PageGroup::addVisitedLink(const UChar* characters, size_t length)
146 {
147     if (!shouldTrackVisitedLinks)
148         return;
149     addVisitedLink(StringImpl::computeHash(characters, length));
150 }
151
152 void PageGroup::removeVisitedLinks()
153 {
154     m_visitedLinksPopulated = false;
155     if (m_visitedLinkHashes.isEmpty())
156         return;
157     m_visitedLinkHashes.clear();
158     Page::allVisitedStateChanged(this);
159 }
160
161 void PageGroup::removeAllVisitedLinks()
162 {
163     Page::removeAllVisitedLinks();
164 }
165
166 void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
167 {
168     if (shouldTrackVisitedLinks == shouldTrack)
169         return;
170     shouldTrackVisitedLinks = shouldTrack;
171     if (!shouldTrackVisitedLinks)
172         removeAllVisitedLinks();
173 }
174
175 #if ENABLE(DOM_STORAGE)
176 LocalStorage* PageGroup::localStorage()
177 {
178     return m_localStorage.get();
179 }
180 #endif
181
182 } // namespace WebCore