1/*
2 * Copyright (C) 2006, 2007, 2008, 2009 Apple 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#include "IconDatabaseBase.h"
31#include "Timer.h"
32#include <wtf/HashCountedSet.h>
33#include <wtf/HashMap.h>
34#include <wtf/HashSet.h>
35#include <wtf/Noncopyable.h>
36#include <wtf/OwnPtr.h>
37#include <wtf/PassOwnPtr.h>
38#include <wtf/text/StringHash.h>
39#include <wtf/text/WTFString.h>
40
41#if ENABLE(ICONDATABASE)
42#include "SQLiteDatabase.h"
43#include <wtf/Threading.h>
44#endif // ENABLE(ICONDATABASE)
45
46namespace WebCore {
47
48class DocumentLoader;
49class Image;
50class IntSize;
51class IconDatabaseClient;
52class IconRecord;
53class IconSnapshot;
54class KURL;
55class PageURLRecord;
56class PageURLSnapshot;
57class SharedBuffer;
58
59#if ENABLE(ICONDATABASE)
60class SQLTransaction;
61#endif
62
63#if !ENABLE(ICONDATABASE)
64// For builds with IconDatabase disabled, they'll just use a default derivation of IconDatabaseBase. Which does nothing.
65class IconDatabase : public IconDatabaseBase {
66public:
67    static PassOwnPtr<IconDatabase> create() { return adoptPtr(new IconDatabase); }
68    static void delayDatabaseCleanup() { }
69    static void allowDatabaseCleanup() { }
70    static void checkIntegrityBeforeOpening() { }
71    static String defaultDatabaseFilename() { return "WebpageIcons.db"; }
72};
73#else
74
75class IconDatabase : public IconDatabaseBase {
76    WTF_MAKE_FAST_ALLOCATED;
77
78// *** Main Thread Only ***
79public:
80    static PassOwnPtr<IconDatabase> create() { return adoptPtr(new IconDatabase); }
81    ~IconDatabase();
82
83    virtual void setClient(IconDatabaseClient*);
84
85    virtual bool open(const String& directory, const String& filename);
86    virtual void close();
87
88    virtual void removeAllIcons();
89
90    void readIconForPageURLFromDisk(const String&);
91
92    virtual Image* defaultIcon(const IntSize&);
93
94    virtual void retainIconForPageURL(const String&);
95    virtual void releaseIconForPageURL(const String&);
96    virtual void setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&);
97    virtual void setIconURLForPageURL(const String& iconURL, const String& pageURL);
98
99    virtual Image* synchronousIconForPageURL(const String&, const IntSize&);
100    virtual PassNativeImagePtr synchronousNativeIconForPageURL(const String& pageURLOriginal, const IntSize&);
101    virtual String synchronousIconURLForPageURL(const String&);
102    virtual bool synchronousIconDataKnownForIconURL(const String&);
103    virtual IconLoadDecision synchronousLoadDecisionForIconURL(const String&, DocumentLoader*);
104
105    virtual void setEnabled(bool);
106    virtual bool isEnabled() const;
107
108    virtual void setPrivateBrowsingEnabled(bool flag);
109    bool isPrivateBrowsingEnabled() const;
110
111    static void delayDatabaseCleanup();
112    static void allowDatabaseCleanup();
113    static void checkIntegrityBeforeOpening();
114
115    // Support for WebCoreStatistics in WebKit
116    virtual size_t pageURLMappingCount();
117    virtual size_t retainedPageURLCount();
118    virtual size_t iconRecordCount();
119    virtual size_t iconRecordCountWithData();
120
121private:
122    IconDatabase();
123    friend IconDatabaseBase& iconDatabase();
124
125    static void notifyPendingLoadDecisionsOnMainThread(void*);
126    void notifyPendingLoadDecisions();
127
128    void wakeSyncThread();
129    void scheduleOrDeferSyncTimer();
130    void syncTimerFired(Timer<IconDatabase>*);
131
132    Timer<IconDatabase> m_syncTimer;
133    ThreadIdentifier m_syncThread;
134    bool m_syncThreadRunning;
135
136    HashSet<RefPtr<DocumentLoader> > m_loadersPendingDecision;
137
138    RefPtr<IconRecord> m_defaultIconRecord;
139
140    static void performScheduleOrDeferSyncTimerOnMainThread(void*);
141    void performScheduleOrDeferSyncTimer();
142
143    bool m_scheduleOrDeferSyncTimerRequested;
144
145// *** Any Thread ***
146public:
147    virtual bool isOpen() const;
148    virtual String databasePath() const;
149    static String defaultDatabaseFilename();
150
151private:
152    PassRefPtr<IconRecord> getOrCreateIconRecord(const String& iconURL);
153    PageURLRecord* getOrCreatePageURLRecord(const String& pageURL);
154
155    bool m_isEnabled;
156    bool m_privateBrowsingEnabled;
157
158    mutable Mutex m_syncLock;
159    ThreadCondition m_syncCondition;
160    String m_databaseDirectory;
161    // Holding m_syncLock is required when accessing m_completeDatabasePath
162    String m_completeDatabasePath;
163
164    bool m_threadTerminationRequested;
165    bool m_removeIconsRequested;
166    bool m_iconURLImportComplete;
167    bool m_syncThreadHasWorkToDo;
168    bool m_disabledSuddenTerminationForSyncThread;
169
170    Mutex m_urlAndIconLock;
171    // Holding m_urlAndIconLock is required when accessing any of the following data structures or the objects they contain
172    HashMap<String, IconRecord*> m_iconURLToRecordMap;
173    HashMap<String, PageURLRecord*> m_pageURLToRecordMap;
174    HashSet<String> m_retainedPageURLs;
175
176    Mutex m_pendingSyncLock;
177    // Holding m_pendingSyncLock is required when accessing any of the following data structures
178    HashMap<String, PageURLSnapshot> m_pageURLsPendingSync;
179    HashMap<String, IconSnapshot> m_iconsPendingSync;
180
181    Mutex m_pendingReadingLock;
182    // Holding m_pendingSyncLock is required when accessing any of the following data structures - when dealing with IconRecord*s, holding m_urlAndIconLock is also required
183    HashSet<String> m_pageURLsPendingImport;
184    HashSet<String> m_pageURLsInterestedInIcons;
185    HashSet<IconRecord*> m_iconsPendingReading;
186
187    Mutex m_urlsToRetainOrReleaseLock;
188    // Holding m_urlsToRetainOrReleaseLock is required when accessing any of the following data structures.
189    HashCountedSet<String> m_urlsToRetain;
190    HashCountedSet<String> m_urlsToRelease;
191    bool m_retainOrReleaseIconRequested;
192
193// *** Sync Thread Only ***
194public:
195    virtual bool shouldStopThreadActivity() const;
196
197private:
198    static void iconDatabaseSyncThreadStart(void *);
199    void iconDatabaseSyncThread();
200
201    // The following block of methods are called exclusively by the sync thread to manage i/o to and from the database
202    // Each method should periodically monitor m_threadTerminationRequested when it makes sense to return early on shutdown
203    void performOpenInitialization();
204    bool checkIntegrity();
205    void performURLImport();
206    void syncThreadMainLoop();
207    bool readFromDatabase();
208    bool writeToDatabase();
209    void pruneUnretainedIcons();
210    void checkForDanglingPageURLs(bool pruneIfFound);
211    void removeAllIconsOnThread();
212    void deleteAllPreparedStatements();
213    void* cleanupSyncThread();
214    void performRetainIconForPageURL(const String&, int retainCount);
215    void performReleaseIconForPageURL(const String&, int releaseCount);
216
217    bool wasExcludedFromBackup();
218    void setWasExcludedFromBackup();
219
220    bool m_initialPruningComplete;
221
222    void setIconURLForPageURLInSQLDatabase(const String&, const String&);
223    void setIconIDForPageURLInSQLDatabase(int64_t, const String&);
224    void removePageURLFromSQLDatabase(const String& pageURL);
225    int64_t getIconIDForIconURLFromSQLDatabase(const String& iconURL);
226    int64_t addIconURLToSQLDatabase(const String&);
227    PassRefPtr<SharedBuffer> getImageDataForIconURLFromSQLDatabase(const String& iconURL);
228    void removeIconFromSQLDatabase(const String& iconURL);
229    void writeIconSnapshotToSQLDatabase(const IconSnapshot&);
230
231    void performPendingRetainAndReleaseOperations();
232
233    // Methods to dispatch client callbacks on the main thread
234    void dispatchDidImportIconURLForPageURLOnMainThread(const String&);
235    void dispatchDidImportIconDataForPageURLOnMainThread(const String&);
236    void dispatchDidRemoveAllIconsOnMainThread();
237    void dispatchDidFinishURLImportOnMainThread();
238
239    // The client is set by the main thread before the thread starts, and from then on is only used by the sync thread
240    IconDatabaseClient* m_client;
241
242    SQLiteDatabase m_syncDB;
243
244    OwnPtr<SQLiteStatement> m_setIconIDForPageURLStatement;
245    OwnPtr<SQLiteStatement> m_removePageURLStatement;
246    OwnPtr<SQLiteStatement> m_getIconIDForIconURLStatement;
247    OwnPtr<SQLiteStatement> m_getImageDataForIconURLStatement;
248    OwnPtr<SQLiteStatement> m_addIconToIconInfoStatement;
249    OwnPtr<SQLiteStatement> m_addIconToIconDataStatement;
250    OwnPtr<SQLiteStatement> m_getImageDataStatement;
251    OwnPtr<SQLiteStatement> m_deletePageURLsForIconURLStatement;
252    OwnPtr<SQLiteStatement> m_deleteIconFromIconInfoStatement;
253    OwnPtr<SQLiteStatement> m_deleteIconFromIconDataStatement;
254    OwnPtr<SQLiteStatement> m_updateIconInfoStatement;
255    OwnPtr<SQLiteStatement> m_updateIconDataStatement;
256    OwnPtr<SQLiteStatement> m_setIconInfoStatement;
257    OwnPtr<SQLiteStatement> m_setIconDataStatement;
258};
259
260#endif // !ENABLE(ICONDATABASE)
261
262} // namespace WebCore
263
264#endif // IconDatabase_h
265