2008-05-10 Adele Peterson <adele@apple.com>
[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     addPage(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 ENABLE(DOM_STORAGE)
90     if (!pageGroups)
91         return;
92
93     PageGroupMap::iterator end = pageGroups->end();
94
95     for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
96         if (LocalStorage* localStorage = it->second->localStorage())
97             localStorage->close();
98     }
99 #endif
100 }
101
102 void PageGroup::addPage(Page* page)
103 {
104     ASSERT(page);
105     ASSERT(!m_pages.contains(page));
106     m_pages.add(page);
107 #if ENABLE(DOM_STORAGE)
108     if (!m_localStorage)
109         m_localStorage = LocalStorage::create(this, page->settings()->localStorageDatabasePath());
110 #endif
111 }
112
113 void PageGroup::removePage(Page* page)
114 {
115     ASSERT(page);
116     ASSERT(m_pages.contains(page));
117     m_pages.remove(page);
118 }
119
120 bool PageGroup::isLinkVisited(unsigned visitedLinkHash)
121 {
122     if (!m_visitedLinksPopulated) {
123         m_visitedLinksPopulated = true;
124         ASSERT(!m_pages.isEmpty());
125         (*m_pages.begin())->chrome()->client()->populateVisitedLinks();
126     }
127     return m_visitedLinkHashes.contains(visitedLinkHash);
128 }
129
130 inline void PageGroup::addVisitedLink(unsigned stringHash)
131 {
132     ASSERT(shouldTrackVisitedLinks);
133     unsigned visitedLinkHash = AlreadyHashed::avoidDeletedValue(stringHash);
134     if (!m_visitedLinkHashes.add(visitedLinkHash).second)
135         return;
136     Page::visitedStateChanged(this, visitedLinkHash);
137 }
138
139 void PageGroup::addVisitedLink(const KURL& url)
140 {
141     if (!shouldTrackVisitedLinks)
142         return;
143     ASSERT(!url.isEmpty());
144     addVisitedLink(url.string().impl()->hash());
145 }
146
147 void PageGroup::addVisitedLink(const UChar* characters, size_t length)
148 {
149     if (!shouldTrackVisitedLinks)
150         return;
151     addVisitedLink(StringImpl::computeHash(characters, length));
152 }
153
154 void PageGroup::removeVisitedLinks()
155 {
156     m_visitedLinksPopulated = false;
157     if (m_visitedLinkHashes.isEmpty())
158         return;
159     m_visitedLinkHashes.clear();
160     Page::allVisitedStateChanged(this);
161 }
162
163 void PageGroup::removeAllVisitedLinks()
164 {
165     Page::removeAllVisitedLinks();
166 }
167
168 void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
169 {
170     if (shouldTrackVisitedLinks == shouldTrack)
171         return;
172     shouldTrackVisitedLinks = shouldTrack;
173     if (!shouldTrackVisitedLinks)
174         removeAllVisitedLinks();
175 }
176
177 #if ENABLE(DOM_STORAGE)
178 LocalStorage* PageGroup::localStorage()
179 {
180     return m_localStorage.get();
181 }
182 #endif
183
184 } // namespace WebCore