2007-11-12 Justin Haygood <jhaygood@reaktix.com>
[WebKit-https.git] / WebCore / loader / icon / IconDatabase.h
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26  
27 #ifndef IconDatabase_h
28 #define IconDatabase_h
29
30 #if ENABLE(ICONDATABASE)
31 #include "SQLiteDatabase.h"
32 #endif
33
34 #include "StringHash.h"
35 #if ENABLE(ICONDATABASE)
36 #include "Threading.h"
37 #endif
38 #include "Timer.h"
39 #include <wtf/HashSet.h>
40 #include <wtf/Noncopyable.h>
41 #include <wtf/OwnPtr.h>
42
43 namespace WebCore { 
44
45 class DocumentLoader;
46 class Image;
47 class IntSize;
48 class IconDatabaseClient;
49 class IconRecord;
50 class IconSnapshot;
51 class KURL;
52 class PageURLRecord;
53 class PageURLSnapshot;
54 class SharedBuffer;
55
56 #if ENABLE(ICONDATABASE)
57 class SQLTransaction;
58 #endif
59
60 enum IconLoadDecision {
61     IconLoadYes,
62     IconLoadNo,
63     IconLoadUnknown
64 };
65
66 class IconDatabase : Noncopyable {
67
68 // *** Main Thread Only ***
69 public:
70     void setClient(IconDatabaseClient*);
71
72     bool open(const String& path);
73     void close();
74             
75     void removeAllIcons();
76
77     Image* iconForPageURL(const String&, const IntSize&, bool cache = true);
78     void readIconForPageURLFromDisk(const String&);
79     String iconURLForPageURL(const String&);
80     Image* defaultIcon(const IntSize&);
81
82     void retainIconForPageURL(const String&);
83     void releaseIconForPageURL(const String&);
84
85     void setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&);
86     void setIconURLForPageURL(const String& iconURL, const String& pageURL);
87
88     IconLoadDecision loadDecisionForIconURL(const String&, DocumentLoader*);
89     bool iconDataKnownForIconURL(const String&);
90     
91     void setEnabled(bool enabled);
92     bool isEnabled() const;
93     
94     void setPrivateBrowsingEnabled(bool flag);
95     bool isPrivateBrowsingEnabled() const;
96     
97     static void delayDatabaseCleanup();
98     static void allowDatabaseCleanup();
99     static void checkIntegrityBeforeOpening();
100         
101     // Support for WebCoreStatistics in WebKit
102     size_t pageURLMappingCount();
103     size_t retainedPageURLCount();
104     size_t iconRecordCount();
105     size_t iconRecordCountWithData();
106
107 private:
108     IconDatabase();
109     ~IconDatabase();
110     friend IconDatabase* iconDatabase();
111
112 #if ENABLE(ICONDATABASE)
113     // This is called on the main thread via the callOnMainThread() function which currently
114     // doesn't have any way to allow it to be an instance method, which it should be
115     static void notifyPendingLoadDecisions();
116     
117     void notifyPendingLoadDecisionsInternal();
118
119     void wakeSyncThread();
120     void scheduleOrDeferSyncTimer();
121     OwnPtr<Timer<IconDatabase> > m_syncTimer;
122     void syncTimerFired(Timer<IconDatabase>*);
123     
124     ThreadIdentifier m_syncThread;
125     bool m_syncThreadRunning;
126     
127     HashSet<RefPtr<DocumentLoader> > m_loadersPendingDecision;
128
129     IconRecord* m_defaultIconRecord;
130 #endif // ENABLE(ICONDATABASE)
131
132 // *** Any Thread ***
133 public:
134     bool isOpen() const;
135     String databasePath() const;
136     static String defaultDatabaseFilename();
137
138 private:
139 #if ENABLE(ICONDATABASE)
140     IconRecord* getOrCreateIconRecord(const String& iconURL);
141     PageURLRecord* getOrCreatePageURLRecord(const String& pageURL);
142     
143     bool m_isEnabled;
144     bool m_privateBrowsingEnabled;
145     
146     mutable Mutex m_syncLock;
147     ThreadCondition m_syncCondition;
148     String m_databaseDirectory;
149     // Holding m_syncLock is required when accessing m_completeDatabasePath
150     String m_completeDatabasePath;
151     
152     bool m_threadTerminationRequested;
153     bool m_removeIconsRequested;
154     bool m_iconURLImportComplete;
155     
156     Mutex m_urlAndIconLock;
157     // Holding m_urlAndIconLock is required when accessing any of the following data structures or the objects they contain
158     HashMap<String, IconRecord*> m_iconURLToRecordMap;
159     HashMap<String, PageURLRecord*> m_pageURLToRecordMap;
160     HashSet<String> m_retainedPageURLs;
161
162     Mutex m_pendingSyncLock;
163     // Holding m_pendingSyncLock is required when accessing any of the following data structures
164     HashMap<String, PageURLSnapshot> m_pageURLsPendingSync;
165     HashMap<String, IconSnapshot> m_iconsPendingSync;
166     
167     Mutex m_pendingReadingLock;    
168     // Holding m_pendingSyncLock is required when accessing any of the following data structures - when dealing with IconRecord*s, holding m_urlAndIconLock is also required
169     HashSet<String> m_pageURLsPendingImport;
170     HashSet<String> m_pageURLsInterestedInIcons;
171     HashSet<IconRecord*> m_iconsPendingReading;
172
173 // *** Sync Thread Only ***
174 public:
175     // Should be used only on the sync thread and only by the Safari 2 Icons import procedure
176     void importIconURLForPageURL(const String& iconURL, const String& pageURL);
177     void importIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL);
178     
179     bool shouldStopThreadActivity() const;
180
181 private:    
182     static void* iconDatabaseSyncThreadStart(void *);
183     void* iconDatabaseSyncThread();
184     
185     // The following block of methods are called exclusively by the sync thread to manage i/o to and from the database
186     // Each method should periodically monitor m_threadTerminationRequested when it makes sense to return early on shutdown
187     void performOpenInitialization();
188     bool checkIntegrity();
189     void performURLImport();
190     void* syncThreadMainLoop();
191     bool readFromDatabase();
192     bool writeToDatabase();
193     void pruneUnretainedIcons();
194     void checkForDanglingPageURLs(bool pruneIfFound);
195     void removeAllIconsOnThread();
196     void deleteAllPreparedStatements();
197     void* cleanupSyncThread();
198
199     // Record (on disk) whether or not Safari 2-style icons were imported (once per dataabse)
200     bool imported();
201     void setImported(bool);
202     
203     bool m_initialPruningComplete;
204         
205     void setIconURLForPageURLInSQLDatabase(const String&, const String&);
206     void setIconIDForPageURLInSQLDatabase(int64_t, const String&);
207     void removePageURLFromSQLDatabase(const String& pageURL);
208     int64_t getIconIDForIconURLFromSQLDatabase(const String& iconURL);
209     int64_t addIconURLToSQLDatabase(const String&);
210     PassRefPtr<SharedBuffer> getImageDataForIconURLFromSQLDatabase(const String& iconURL);
211     void removeIconFromSQLDatabase(const String& iconURL);
212     void writeIconSnapshotToSQLDatabase(const IconSnapshot&);    
213     
214     // The client is set by the main thread before the thread starts, and from then on is only used by the sync thread
215     IconDatabaseClient* m_client;
216     
217     SQLiteDatabase m_syncDB;
218     
219     // Track whether the "Safari 2" import is complete and/or set in the database
220     bool m_imported;
221     bool m_isImportedSet;
222     
223     OwnPtr<SQLiteStatement> m_setIconIDForPageURLStatement;
224     OwnPtr<SQLiteStatement> m_removePageURLStatement;
225     OwnPtr<SQLiteStatement> m_getIconIDForIconURLStatement;
226     OwnPtr<SQLiteStatement> m_getImageDataForIconURLStatement;
227     OwnPtr<SQLiteStatement> m_addIconToIconInfoStatement;
228     OwnPtr<SQLiteStatement> m_addIconToIconDataStatement;
229     OwnPtr<SQLiteStatement> m_getImageDataStatement;
230     OwnPtr<SQLiteStatement> m_deletePageURLsForIconURLStatement;
231     OwnPtr<SQLiteStatement> m_deleteIconFromIconInfoStatement;
232     OwnPtr<SQLiteStatement> m_deleteIconFromIconDataStatement;
233     OwnPtr<SQLiteStatement> m_updateIconInfoStatement;
234     OwnPtr<SQLiteStatement> m_updateIconDataStatement;
235     OwnPtr<SQLiteStatement> m_setIconInfoStatement;
236     OwnPtr<SQLiteStatement> m_setIconDataStatement;
237 #endif // ENABLE(ICONDATABASE)
238 };
239
240 // Function to obtain the global icon database.
241 IconDatabase* iconDatabase();
242
243 } // namespace WebCore
244
245 #endif