1/*
2 * Copyright (C) 2007, 2008, 2013 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 *
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 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef DatabaseTracker_h
30#define DatabaseTracker_h
31
32#if ENABLE(SQL_DATABASE)
33
34#include "DatabaseDetails.h"
35#include "DatabaseError.h"
36#include "SQLiteDatabase.h"
37#include "SecurityOriginHash.h"
38#include <wtf/HashMap.h>
39#include <wtf/HashSet.h>
40#include <wtf/OwnPtr.h>
41#include <wtf/text/StringHash.h>
42#include <wtf/text/WTFString.h>
43
44namespace WebCore {
45
46class DatabaseBackendBase;
47class DatabaseBackendContext;
48class DatabaseManagerClient;
49class OriginLock;
50class SecurityOrigin;
51
52class DatabaseTracker {
53    WTF_MAKE_NONCOPYABLE(DatabaseTracker); WTF_MAKE_FAST_ALLOCATED;
54public:
55    static void initializeTracker(const String& databasePath);
56
57    static DatabaseTracker& tracker();
58    // This singleton will potentially be used from multiple worker threads and the page's context thread simultaneously.  To keep this safe, it's
59    // currently using 4 locks.  In order to avoid deadlock when taking multiple locks, you must take them in the correct order:
60    // m_databaseGuard before quotaManager if both locks are needed.
61    // m_openDatabaseMapGuard before quotaManager if both locks are needed.
62    // m_databaseGuard and m_openDatabaseMapGuard currently don't overlap.
63    // notificationMutex() is currently independent of the other locks.
64
65    bool canEstablishDatabase(DatabaseBackendContext*, const String& name, unsigned long estimatedSize, DatabaseError&);
66    bool retryCanEstablishDatabase(DatabaseBackendContext*, const String& name, unsigned long estimatedSize, DatabaseError&);
67
68    void setDatabaseDetails(SecurityOrigin*, const String& name, const String& displayName, unsigned long estimatedSize);
69    String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true);
70
71    void addOpenDatabase(DatabaseBackendBase*);
72    void removeOpenDatabase(DatabaseBackendBase*);
73    void getOpenDatabases(SecurityOrigin*, const String& name, HashSet<RefPtr<DatabaseBackendBase> >* databases);
74
75    unsigned long long getMaxSizeForDatabase(const DatabaseBackendBase*);
76
77    void interruptAllDatabasesForContext(const DatabaseBackendContext*);
78
79private:
80    explicit DatabaseTracker(const String& databasePath);
81
82    bool hasAdequateQuotaForOrigin(SecurityOrigin*, unsigned long estimatedSize, DatabaseError&);
83
84public:
85    void setDatabaseDirectoryPath(const String&);
86    String databaseDirectoryPath() const;
87
88    void origins(Vector<RefPtr<SecurityOrigin> >& result);
89    bool databaseNamesForOrigin(SecurityOrigin*, Vector<String>& result);
90
91    DatabaseDetails detailsForNameAndOrigin(const String&, SecurityOrigin*);
92
93    unsigned long long usageForDatabase(const String&, SecurityOrigin*);
94    unsigned long long usageForOrigin(SecurityOrigin*);
95    unsigned long long quotaForOrigin(SecurityOrigin*);
96    void setQuota(SecurityOrigin*, unsigned long long);
97    PassRefPtr<OriginLock> originLockFor(SecurityOrigin*);
98
99    void deleteAllDatabases();
100    bool deleteOrigin(SecurityOrigin*);
101    bool deleteDatabase(SecurityOrigin*, const String& name);
102
103    void setClient(DatabaseManagerClient*);
104
105    // From a secondary thread, must be thread safe with its data
106    void scheduleNotifyDatabaseChanged(SecurityOrigin*, const String& name);
107
108    bool hasEntryForOrigin(SecurityOrigin*);
109
110    void doneCreatingDatabase(DatabaseBackendBase*);
111
112private:
113    bool hasEntryForOriginNoLock(SecurityOrigin* origin);
114    String fullPathForDatabaseNoLock(SecurityOrigin*, const String& name, bool createIfDoesNotExist);
115    bool databaseNamesForOriginNoLock(SecurityOrigin* origin, Vector<String>& resultVector);
116    unsigned long long quotaForOriginNoLock(SecurityOrigin* origin);
117
118    String trackerDatabasePath() const;
119
120    enum TrackerCreationAction {
121        DontCreateIfDoesNotExist,
122        CreateIfDoesNotExist
123    };
124    void openTrackerDatabase(TrackerCreationAction);
125
126    String originPath(SecurityOrigin*) const;
127
128    bool hasEntryForDatabase(SecurityOrigin*, const String& databaseIdentifier);
129
130    bool addDatabase(SecurityOrigin*, const String& name, const String& path);
131
132    bool deleteDatabaseFile(SecurityOrigin*, const String& name);
133
134    void deleteOriginLockFor(SecurityOrigin*);
135
136    typedef HashSet<DatabaseBackendBase*> DatabaseSet;
137    typedef HashMap<String, DatabaseSet*> DatabaseNameMap;
138    typedef HashMap<RefPtr<SecurityOrigin>, DatabaseNameMap*> DatabaseOriginMap;
139
140    Mutex m_openDatabaseMapGuard;
141    mutable OwnPtr<DatabaseOriginMap> m_openDatabaseMap;
142
143    // This lock protects m_database, m_originLockMap, m_databaseDirectoryPath, m_originsBeingDeleted, m_beingCreated, and m_beingDeleted.
144    Mutex m_databaseGuard;
145    SQLiteDatabase m_database;
146
147    typedef HashMap<String, RefPtr<OriginLock> > OriginLockMap;
148    OriginLockMap m_originLockMap;
149
150    String m_databaseDirectoryPath;
151
152    DatabaseManagerClient* m_client;
153
154    typedef HashMap<String, long> NameCountMap;
155    typedef HashMap<RefPtr<SecurityOrigin>, NameCountMap*, SecurityOriginHash> CreateSet;
156    CreateSet m_beingCreated;
157    typedef HashSet<String> NameSet;
158    HashMap<RefPtr<SecurityOrigin>, NameSet*> m_beingDeleted;
159    HashSet<RefPtr<SecurityOrigin> > m_originsBeingDeleted;
160    bool isDeletingDatabaseOrOriginFor(SecurityOrigin*, const String& name);
161    void recordCreatingDatabase(SecurityOrigin*, const String& name);
162    void doneCreatingDatabase(SecurityOrigin*, const String& name);
163    bool creatingDatabase(SecurityOrigin*, const String& name);
164    bool canDeleteDatabase(SecurityOrigin*, const String& name);
165    void recordDeletingDatabase(SecurityOrigin*, const String& name);
166    void doneDeletingDatabase(SecurityOrigin*, const String& name);
167    bool isDeletingDatabase(SecurityOrigin*, const String& name);
168    bool canDeleteOrigin(SecurityOrigin*);
169    bool isDeletingOrigin(SecurityOrigin*);
170    void recordDeletingOrigin(SecurityOrigin*);
171    void doneDeletingOrigin(SecurityOrigin*);
172
173    static void scheduleForNotification();
174    static void notifyDatabasesChanged(void*);
175};
176
177} // namespace WebCore
178
179#endif // ENABLE(SQL_DATABASE)
180
181#endif // DatabaseTracker_h
182