Use modern for-loops in WebCore/Modules - 2
[WebKit-https.git] / Source / WebCore / Modules / webdatabase / DatabaseTracker.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2012, 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 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 #include "config.h"
30 #include "DatabaseTracker.h"
31
32 #include "Chrome.h"
33 #include "ChromeClient.h"
34 #include "Database.h"
35 #include "DatabaseBackendBase.h"
36 #include "DatabaseContext.h"
37 #include "DatabaseManager.h"
38 #include "DatabaseManagerClient.h"
39 #include "DatabaseThread.h"
40 #include "FileSystem.h"
41 #include "Logging.h"
42 #include "OriginLock.h"
43 #include "Page.h"
44 #include "SecurityOrigin.h"
45 #include "SecurityOriginHash.h"
46 #include "SQLiteFileSystem.h"
47 #include "SQLiteStatement.h"
48 #include "UUID.h"
49 #include <wtf/MainThread.h>
50 #include <wtf/NeverDestroyed.h>
51 #include <wtf/StdLibExtras.h>
52 #include <wtf/text/CString.h>
53
54 #if PLATFORM(IOS)
55 #include "WebCoreThread.h"
56 #endif
57
58 namespace WebCore {
59
60 std::unique_ptr<DatabaseTracker> DatabaseTracker::trackerWithDatabasePath(const String& databasePath)
61 {
62     return std::unique_ptr<DatabaseTracker>(new DatabaseTracker(databasePath));
63 }
64
65 static DatabaseTracker* staticTracker = 0;
66
67 void DatabaseTracker::initializeTracker(const String& databasePath)
68 {
69     ASSERT(!staticTracker);
70     if (staticTracker)
71         return;
72
73     staticTracker = new DatabaseTracker(databasePath);
74 }
75
76 DatabaseTracker& DatabaseTracker::tracker()
77 {
78     if (!staticTracker)
79         staticTracker = new DatabaseTracker("");
80
81     return *staticTracker;
82 }
83
84 DatabaseTracker::DatabaseTracker(const String& databasePath)
85     : m_client(0)
86 {
87     setDatabaseDirectoryPath(databasePath);
88 }
89
90 void DatabaseTracker::setDatabaseDirectoryPath(const String& path)
91 {
92     MutexLocker lockDatabase(m_databaseGuard);
93     ASSERT(!m_database.isOpen());
94     m_databaseDirectoryPath = path.isolatedCopy();
95 }
96
97 String DatabaseTracker::databaseDirectoryPath() const
98 {
99     return m_databaseDirectoryPath.isolatedCopy();
100 }
101
102 String DatabaseTracker::trackerDatabasePath() const
103 {
104     return SQLiteFileSystem::appendDatabaseFileNameToPath(m_databaseDirectoryPath.isolatedCopy(), "Databases.db");
105 }
106
107 void DatabaseTracker::openTrackerDatabase(TrackerCreationAction createAction)
108 {
109     ASSERT(!m_databaseGuard.tryLock());
110
111     if (m_database.isOpen())
112         return;
113
114     // If createIfDoesNotExist is false, SQLiteFileSystem::ensureDatabaseFileExists()
115     // will return false if the database file does not exist.
116     // If createIfDoesNotExist is true, SQLiteFileSystem::ensureDatabaseFileExists()
117     // will attempt to create the path to the database file if it does not
118     // exists yet. It'll return true if the path already exists, or if it
119     // successfully creates the path. Else, it will return false.
120     String databasePath = trackerDatabasePath();
121     if (!SQLiteFileSystem::ensureDatabaseFileExists(databasePath, createAction == CreateIfDoesNotExist))
122         return;
123
124     if (!m_database.open(databasePath)) {
125         // FIXME: What do do here?
126         LOG_ERROR("Failed to open databasePath %s.", databasePath.ascii().data());
127         return;
128     }
129     m_database.disableThreadingChecks();
130
131     if (!m_database.tableExists("Origins")) {
132         if (!m_database.executeCommand("CREATE TABLE Origins (origin TEXT UNIQUE ON CONFLICT REPLACE, quota INTEGER NOT NULL ON CONFLICT FAIL);")) {
133             // FIXME: and here
134             LOG_ERROR("Failed to create Origins table");
135         }
136     }
137
138     if (!m_database.tableExists("Databases")) {
139         if (!m_database.executeCommand("CREATE TABLE Databases (guid INTEGER PRIMARY KEY AUTOINCREMENT, origin TEXT, name TEXT, displayName TEXT, estimatedSize INTEGER, path TEXT);")) {
140             // FIXME: and here
141             LOG_ERROR("Failed to create Databases table");
142         }
143     }
144 }
145
146 bool DatabaseTracker::hasAdequateQuotaForOrigin(SecurityOrigin* origin, unsigned long estimatedSize, DatabaseError& err)
147 {
148     ASSERT(!m_databaseGuard.tryLock());
149     unsigned long long usage = usageForOrigin(origin);
150
151     // If the database will fit, allow its creation.
152     unsigned long long requirement = usage + std::max<unsigned long long>(1, estimatedSize);
153     if (requirement < usage) {
154         // The estimated size is so big it causes an overflow; don't allow creation.
155         err = DatabaseError::DatabaseSizeOverflowed;
156         return false;
157     }
158     if (requirement <= quotaForOriginNoLock(origin))
159         return true;
160
161     err = DatabaseError::DatabaseSizeExceededQuota;
162     return false;
163 }
164
165 bool DatabaseTracker::canEstablishDatabase(DatabaseContext* context, const String& name, unsigned long estimatedSize, DatabaseError& error)
166 {
167     error = DatabaseError::None;
168
169     MutexLocker lockDatabase(m_databaseGuard);
170     SecurityOrigin* origin = context->securityOrigin();
171
172     if (isDeletingDatabaseOrOriginFor(origin, name)) {
173         error = DatabaseError::DatabaseIsBeingDeleted;
174         return false;
175     }
176
177     recordCreatingDatabase(origin, name);
178
179     // If a database already exists, ignore the passed-in estimated size and say it's OK.
180     if (hasEntryForDatabase(origin, name))
181         return true;
182
183     if (hasAdequateQuotaForOrigin(origin, estimatedSize, error)) {
184         ASSERT(error == DatabaseError::None);
185         return true;
186     }
187
188     // If we get here, then we do not have enough quota for one of the
189     // following reasons as indicated by the set error:
190     //
191     // If the error is DatabaseSizeOverflowed, then this means the requested
192     // estimatedSize if so unreasonably large that it can cause an overflow in
193     // the usage budget computation. In that case, there's nothing more we can
194     // do, and there's no need for a retry. Hence, we should indicate that
195     // we're done with our attempt to create the database.
196     //
197     // If the error is DatabaseSizeExceededQuota, then we'll give the client
198     // a chance to update the quota and call retryCanEstablishDatabase() to try
199     // again. Hence, we don't call doneCreatingDatabase() yet in that case.
200
201     if (error == DatabaseError::DatabaseSizeOverflowed)
202         doneCreatingDatabase(origin, name);
203     else
204         ASSERT(error == DatabaseError::DatabaseSizeExceededQuota);
205
206     return false;
207 }
208
209 // Note: a thought about performance: hasAdequateQuotaForOrigin() was also
210 // called in canEstablishDatabase(), and hence, we're repeating some work within
211 // hasAdequateQuotaForOrigin(). However, retryCanEstablishDatabase() should only
212 // be called in the rare even if canEstablishDatabase() fails. Since it is rare,
213 // we should not bother optimizing it. It is more beneficial to keep
214 // hasAdequateQuotaForOrigin() simple and correct (i.e. bug free), and just
215 // re-use it. Also note that the path for opening a database involves IO, and
216 // hence should not be a performance critical path anyway. 
217 bool DatabaseTracker::retryCanEstablishDatabase(DatabaseContext* context, const String& name, unsigned long estimatedSize, DatabaseError& error)
218 {
219     error = DatabaseError::None;
220
221     MutexLocker lockDatabase(m_databaseGuard);
222     SecurityOrigin* origin = context->securityOrigin();
223
224     // We have already eliminated other types of errors in canEstablishDatabase().
225     // The only reason we're in retryCanEstablishDatabase() is because we gave
226     // the client a chance to update the quota and are rechecking it here.
227     // If we fail this check, the only possible reason this time should be due
228     // to inadequate quota.
229     if (hasAdequateQuotaForOrigin(origin, estimatedSize, error)) {
230         ASSERT(error == DatabaseError::None);
231         return true;
232     }
233
234     ASSERT(error == DatabaseError::DatabaseSizeExceededQuota);
235     doneCreatingDatabase(origin, name);
236
237     return false;
238 }
239
240 bool DatabaseTracker::hasEntryForOriginNoLock(SecurityOrigin* origin)
241 {
242     ASSERT(!m_databaseGuard.tryLock());
243     openTrackerDatabase(DontCreateIfDoesNotExist);
244     if (!m_database.isOpen())
245         return false;
246
247     SQLiteStatement statement(m_database, "SELECT origin FROM Origins where origin=?;");
248     if (statement.prepare() != SQLITE_OK) {
249         LOG_ERROR("Failed to prepare statement.");
250         return false;
251     }
252
253     statement.bindText(1, origin->databaseIdentifier());
254
255     return statement.step() == SQLITE_ROW;
256 }
257
258 bool DatabaseTracker::hasEntryForOrigin(SecurityOrigin* origin)
259 {
260     MutexLocker lockDatabase(m_databaseGuard);
261     return hasEntryForOriginNoLock(origin);
262 }
263
264 bool DatabaseTracker::hasEntryForDatabase(SecurityOrigin* origin, const String& databaseIdentifier)
265 {
266     ASSERT(!m_databaseGuard.tryLock());
267     openTrackerDatabase(DontCreateIfDoesNotExist);
268     if (!m_database.isOpen()) {
269         // No "tracker database". Hence, no entry for the database of interest.
270         return false;
271     }
272
273     // We've got a tracker database. Set up a query to ask for the db of interest:
274     SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?;");
275
276     if (statement.prepare() != SQLITE_OK)
277         return false;
278
279     statement.bindText(1, origin->databaseIdentifier());
280     statement.bindText(2, databaseIdentifier);
281
282     return statement.step() == SQLITE_ROW;
283 }
284
285 unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database)
286 {
287     // The maximum size for a database is the full quota for its origin, minus the current usage within the origin,
288     // plus the current usage of the given database
289     MutexLocker lockDatabase(m_databaseGuard);
290     SecurityOrigin* origin = database->securityOrigin();
291
292     unsigned long long quota = quotaForOriginNoLock(origin);
293     unsigned long long diskUsage = usageForOrigin(origin);
294     unsigned long long databaseFileSize = SQLiteFileSystem::getDatabaseFileSize(database->fileName());
295     ASSERT(databaseFileSize <= diskUsage);
296
297     if (diskUsage > quota)
298         return databaseFileSize;
299
300     // A previous error may have allowed the origin to exceed its quota, or may
301     // have allowed this database to exceed our cached estimate of the origin
302     // disk usage. Don't multiply that error through integer underflow, or the
303     // effective quota will permanently become 2^64.
304     unsigned long long maxSize = quota - diskUsage + databaseFileSize;
305     if (maxSize > quota)
306         maxSize = databaseFileSize;
307     return maxSize;
308 }
309
310 void DatabaseTracker::closeAllDatabases()
311 {
312     Vector<Ref<Database>> openDatabases;
313     {
314         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
315         if (!m_openDatabaseMap)
316             return;
317         for (auto& nameMap : m_openDatabaseMap->values()) {
318             for (auto& set : nameMap->values()) {
319                 for (auto& database : *set)
320                     openDatabases.append(*database);
321             }
322         }
323     }
324     for (auto& database : openDatabases)
325         database->close();
326 }
327
328 void DatabaseTracker::interruptAllDatabasesForContext(const DatabaseContext* context)
329 {
330     Vector<RefPtr<DatabaseBackendBase>> openDatabases;
331     {
332         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
333
334         if (!m_openDatabaseMap)
335             return;
336
337         DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin());
338         if (!nameMap)
339             return;
340
341         for (auto& databaseSet : nameMap->values()) {
342             for (auto& database : *databaseSet) {
343                 if (database->databaseContext() == context)
344                     openDatabases.append(database);
345             }
346         }
347     }
348
349     for (auto& openDatabase : openDatabases)
350         openDatabase->interrupt();
351 }
352
353 String DatabaseTracker::originPath(SecurityOrigin* origin) const
354 {
355     return SQLiteFileSystem::appendDatabaseFileNameToPath(m_databaseDirectoryPath.isolatedCopy(), origin->databaseIdentifier());
356 }
357
358 static String generateDatabaseFileName()
359 {
360     StringBuilder stringBuilder;
361
362     stringBuilder.append(createCanonicalUUIDString());
363     stringBuilder.appendLiteral(".db");
364
365     return stringBuilder.toString();
366 }
367
368 String DatabaseTracker::fullPathForDatabaseNoLock(SecurityOrigin* origin, const String& name, bool createIfNotExists)
369 {
370     ASSERT(!m_databaseGuard.tryLock());
371
372     String originIdentifier = origin->databaseIdentifier();
373     String originPath = this->originPath(origin);
374
375     // Make sure the path for this SecurityOrigin exists
376     if (createIfNotExists && !SQLiteFileSystem::ensureDatabaseDirectoryExists(originPath))
377         return String();
378
379     // See if we have a path for this database yet
380     if (!m_database.isOpen())
381         return String();
382     SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;");
383
384     if (statement.prepare() != SQLITE_OK)
385         return String();
386
387     statement.bindText(1, originIdentifier);
388     statement.bindText(2, name);
389
390     int result = statement.step();
391
392     if (result == SQLITE_ROW)
393         return SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, statement.getColumnText(0));
394     if (!createIfNotExists)
395         return String();
396
397     if (result != SQLITE_DONE) {
398         LOG_ERROR("Failed to retrieve filename from Database Tracker for origin %s, name %s", originIdentifier.ascii().data(), name.ascii().data());
399         return String();
400     }
401     statement.finalize();
402
403     String fileName = generateDatabaseFileName();
404
405     if (!addDatabase(origin, name, fileName))
406         return String();
407
408     // If this origin's quota is being tracked (open handle to a database in this origin), add this new database
409     // to the quota manager now
410     String fullFilePath = SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, fileName);
411
412     return fullFilePath;
413 }
414
415 String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String& name, bool createIfNotExists)
416 {
417     MutexLocker lockDatabase(m_databaseGuard);
418     return fullPathForDatabaseNoLock(origin, name, createIfNotExists).isolatedCopy();
419 }
420
421 void DatabaseTracker::origins(Vector<RefPtr<SecurityOrigin>>& originsResult)
422 {
423     MutexLocker lockDatabase(m_databaseGuard);
424
425     openTrackerDatabase(DontCreateIfDoesNotExist);
426     if (!m_database.isOpen())
427         return;
428
429     SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
430     if (statement.prepare() != SQLITE_OK) {
431         LOG_ERROR("Failed to prepare statement.");
432         return;
433     }
434
435     int result;
436     while ((result = statement.step()) == SQLITE_ROW) {
437         RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(statement.getColumnText(0));
438         originsResult.append(origin->isolatedCopy());
439     }
440     originsResult.shrinkToFit();
441
442     if (result != SQLITE_DONE)
443         LOG_ERROR("Failed to read in all origins from the database.");
444 }
445
446 bool DatabaseTracker::databaseNamesForOriginNoLock(SecurityOrigin* origin, Vector<String>& resultVector)
447 {
448     ASSERT(!m_databaseGuard.tryLock());
449     openTrackerDatabase(DontCreateIfDoesNotExist);
450     if (!m_database.isOpen())
451         return false;
452
453     SQLiteStatement statement(m_database, "SELECT name FROM Databases where origin=?;");
454
455     if (statement.prepare() != SQLITE_OK)
456         return false;
457
458     statement.bindText(1, origin->databaseIdentifier());
459
460     int result;
461     while ((result = statement.step()) == SQLITE_ROW)
462         resultVector.append(statement.getColumnText(0));
463
464     if (result != SQLITE_DONE) {
465         LOG_ERROR("Failed to retrieve all database names for origin %s", origin->databaseIdentifier().ascii().data());
466         return false;
467     }
468
469     return true;
470 }
471
472 bool DatabaseTracker::databaseNamesForOrigin(SecurityOrigin* origin, Vector<String>& resultVector)
473 {
474     Vector<String> temp;
475     {
476         MutexLocker lockDatabase(m_databaseGuard);
477         if (!databaseNamesForOriginNoLock(origin, temp))
478           return false;
479     }
480
481     for (auto& databaseName : temp)
482         resultVector.append(databaseName.isolatedCopy());
483     return true;
484 }
485
486 DatabaseDetails DatabaseTracker::detailsForNameAndOrigin(const String& name, SecurityOrigin* origin)
487 {
488     String originIdentifier = origin->databaseIdentifier();
489     String displayName;
490     int64_t expectedUsage;
491
492     {
493         MutexLocker lockDatabase(m_databaseGuard);
494
495         openTrackerDatabase(DontCreateIfDoesNotExist);
496         if (!m_database.isOpen())
497             return DatabaseDetails();
498         SQLiteStatement statement(m_database, "SELECT displayName, estimatedSize FROM Databases WHERE origin=? AND name=?");
499         if (statement.prepare() != SQLITE_OK)
500             return DatabaseDetails();
501
502         statement.bindText(1, originIdentifier);
503         statement.bindText(2, name);
504
505         int result = statement.step();
506         if (result == SQLITE_DONE)
507             return DatabaseDetails();
508
509         if (result != SQLITE_ROW) {
510             LOG_ERROR("Error retrieving details for database %s in origin %s from tracker database", name.ascii().data(), originIdentifier.ascii().data());
511             return DatabaseDetails();
512         }
513         displayName = statement.getColumnText(0);
514         expectedUsage = statement.getColumnInt64(1);
515     }
516
517     String path = fullPathForDatabase(origin, name, false);
518     if (path.isEmpty())
519         return DatabaseDetails(name, displayName, expectedUsage, 0, 0, 0);
520     return DatabaseDetails(name, displayName, expectedUsage, SQLiteFileSystem::getDatabaseFileSize(path), SQLiteFileSystem::databaseCreationTime(path), SQLiteFileSystem::databaseModificationTime(path));
521 }
522
523 void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& name, const String& displayName, unsigned long estimatedSize)
524 {
525     String originIdentifier = origin->databaseIdentifier();
526     int64_t guid = 0;
527
528     MutexLocker lockDatabase(m_databaseGuard);
529
530     openTrackerDatabase(CreateIfDoesNotExist);
531     if (!m_database.isOpen())
532         return;
533     SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?");
534     if (statement.prepare() != SQLITE_OK)
535         return;
536
537     statement.bindText(1, originIdentifier);
538     statement.bindText(2, name);
539
540     int result = statement.step();
541     if (result == SQLITE_ROW)
542         guid = statement.getColumnInt64(0);
543     statement.finalize();
544
545     if (guid == 0) {
546         if (result != SQLITE_DONE)
547             LOG_ERROR("Error to determing existence of database %s in origin %s in tracker database", name.ascii().data(), originIdentifier.ascii().data());
548         else {
549             // This case should never occur - we should never be setting database details for a database that doesn't already exist in the tracker
550             // But since the tracker file is an external resource not under complete control of our code, it's somewhat invalid to make this an ASSERT case
551             // So we'll print an error instead
552             LOG_ERROR("Could not retrieve guid for database %s in origin %s from the tracker database - it is invalid to set database details on a database that doesn't already exist in the tracker",
553                        name.ascii().data(), originIdentifier.ascii().data());
554         }
555         return;
556     }
557
558     SQLiteStatement updateStatement(m_database, "UPDATE Databases SET displayName=?, estimatedSize=? WHERE guid=?");
559     if (updateStatement.prepare() != SQLITE_OK)
560         return;
561
562     updateStatement.bindText(1, displayName);
563     updateStatement.bindInt64(2, estimatedSize);
564     updateStatement.bindInt64(3, guid);
565
566     if (updateStatement.step() != SQLITE_DONE) {
567         LOG_ERROR("Failed to update details for database %s in origin %s", name.ascii().data(), originIdentifier.ascii().data());
568         return;
569     }
570
571     if (m_client)
572         m_client->dispatchDidModifyDatabase(origin, name);
573 }
574
575 void DatabaseTracker::doneCreatingDatabase(Database* database)
576 {
577     MutexLocker lockDatabase(m_databaseGuard);
578     doneCreatingDatabase(database->securityOrigin(), database->stringIdentifier());
579 }
580
581 void DatabaseTracker::addOpenDatabase(Database* database)
582 {
583     if (!database)
584         return;
585
586     {
587         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
588
589         if (!m_openDatabaseMap)
590             m_openDatabaseMap = std::make_unique<DatabaseOriginMap>();
591
592         String name(database->stringIdentifier());
593         DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin());
594         if (!nameMap) {
595             nameMap = new DatabaseNameMap;
596             m_openDatabaseMap->set(database->securityOrigin()->isolatedCopy(), nameMap);
597         }
598
599         DatabaseSet* databaseSet = nameMap->get(name);
600         if (!databaseSet) {
601             databaseSet = new DatabaseSet;
602             nameMap->set(name.isolatedCopy(), databaseSet);
603         }
604
605         databaseSet->add(database);
606
607         LOG(StorageAPI, "Added open Database %s (%p)\n", database->stringIdentifier().ascii().data(), database);
608     }
609 }
610
611 void DatabaseTracker::removeOpenDatabase(Database* database)
612 {
613     if (!database)
614         return;
615
616     {
617         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
618
619         if (!m_openDatabaseMap) {
620             ASSERT_NOT_REACHED();
621             return;
622         }
623
624         String name(database->stringIdentifier());
625         DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin());
626         if (!nameMap) {
627             ASSERT_NOT_REACHED();
628             return;
629         }
630
631         DatabaseSet* databaseSet = nameMap->get(name);
632         if (!databaseSet) {
633             ASSERT_NOT_REACHED();
634             return;
635         }
636
637         databaseSet->remove(database);
638
639         LOG(StorageAPI, "Removed open Database %s (%p)\n", database->stringIdentifier().ascii().data(), database);
640
641         if (!databaseSet->isEmpty())
642             return;
643
644         nameMap->remove(name);
645         delete databaseSet;
646
647         if (!nameMap->isEmpty())
648             return;
649
650         m_openDatabaseMap->remove(database->securityOrigin());
651         delete nameMap;
652     }
653 }
654
655 void DatabaseTracker::getOpenDatabases(SecurityOrigin* origin, const String& name, HashSet<RefPtr<Database>>* databases)
656 {
657     MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
658     if (!m_openDatabaseMap)
659         return;
660
661     DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);
662     if (!nameMap)
663         return;
664
665     DatabaseSet* databaseSet = nameMap->get(name);
666     if (!databaseSet)
667         return;
668
669     for (auto& database : *databaseSet)
670         databases->add(database);
671 }
672
673 RefPtr<OriginLock> DatabaseTracker::originLockFor(SecurityOrigin* origin)
674 {
675     MutexLocker lockDatabase(m_databaseGuard);
676     String databaseIdentifier = origin->databaseIdentifier();
677
678     // The originLockMap is accessed from multiple DatabaseThreads since
679     // different script contexts can be writing to different databases from
680     // the same origin. Hence, the databaseIdentifier key needs to be an
681     // isolated copy. An isolated copy gives us a value whose refCounting is
682     // thread-safe, since our copy is guarded by the m_databaseGuard mutex.
683     databaseIdentifier = databaseIdentifier.isolatedCopy();
684
685     OriginLockMap::AddResult addResult =
686         m_originLockMap.add(databaseIdentifier, RefPtr<OriginLock>());
687     if (!addResult.isNewEntry)
688         return addResult.iterator->value;
689
690     String path = originPath(origin);
691     RefPtr<OriginLock> lock = adoptRef(*new OriginLock(path));
692     ASSERT(lock);
693     addResult.iterator->value = lock;
694
695     return WTF::move(lock);
696 }
697
698 void DatabaseTracker::deleteOriginLockFor(SecurityOrigin* origin)
699 {
700     ASSERT(!m_databaseGuard.tryLock());
701
702     // There is not always an instance of an OriginLock associated with an origin.
703     // For example, if the OriginLock lock file was created by a previous run of
704     // the browser which has now terminated, and the current browser process
705     // has not executed any database transactions from this origin that would
706     // have created the OriginLock instance in memory. In this case, we will have
707     // a lock file but not an OriginLock instance in memory.
708
709     // This function is only called if we are already deleting all the database
710     // files in this origin. We'll give the OriginLock one chance to do an
711     // orderly clean up first when we remove its ref from the m_originLockMap.
712     // This may or may not be possible depending on whether other threads are
713     // also using the OriginLock at the same time. After that, we will delete the lock file.
714
715     m_originLockMap.remove(origin->databaseIdentifier());
716     OriginLock::deleteLockFile(originPath(origin));
717 }
718
719 unsigned long long DatabaseTracker::usageForOrigin(SecurityOrigin* origin)
720 {
721     String originPath = this->originPath(origin);
722     unsigned long long diskUsage = 0;
723     for (auto& fileName : listDirectory(originPath, ASCIILiteral("*.db"))) {
724         long long size;
725         getFileSize(fileName, size);
726         diskUsage += size;
727     }
728     return diskUsage;
729 }
730
731 unsigned long long DatabaseTracker::quotaForOriginNoLock(SecurityOrigin* origin)
732 {
733     ASSERT(!m_databaseGuard.tryLock());
734     unsigned long long quota = 0;
735
736     openTrackerDatabase(DontCreateIfDoesNotExist);
737     if (!m_database.isOpen())
738         return quota;
739
740     SQLiteStatement statement(m_database, "SELECT quota FROM Origins where origin=?;");
741     if (statement.prepare() != SQLITE_OK) {
742         LOG_ERROR("Failed to prepare statement.");
743         return quota;
744     }
745     statement.bindText(1, origin->databaseIdentifier());
746
747     if (statement.step() == SQLITE_ROW)
748         quota = statement.getColumnInt64(0);
749
750     return quota;
751 }
752
753 unsigned long long DatabaseTracker::quotaForOrigin(SecurityOrigin* origin)
754 {
755     MutexLocker lockDatabase(m_databaseGuard);
756     return quotaForOriginNoLock(origin);
757 }
758
759 void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota)
760 {
761     MutexLocker lockDatabase(m_databaseGuard);
762
763     if (quotaForOriginNoLock(origin) == quota)
764         return;
765
766     openTrackerDatabase(CreateIfDoesNotExist);
767     if (!m_database.isOpen())
768         return;
769     
770 #if PLATFORM(IOS)
771     bool insertedNewOrigin = false;
772 #endif
773
774     bool originEntryExists = hasEntryForOriginNoLock(origin);
775     if (!originEntryExists) {
776         SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
777         if (statement.prepare() != SQLITE_OK) {
778             LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());
779         } else {
780             statement.bindText(1, origin->databaseIdentifier());
781             statement.bindInt64(2, quota);
782
783             if (statement.step() != SQLITE_DONE)
784                 LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());
785 #if PLATFORM(IOS)
786             else
787                 insertedNewOrigin = true;
788 #endif
789         }
790     } else {
791         SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?");
792         bool error = statement.prepare() != SQLITE_OK;
793         if (!error) {
794             statement.bindInt64(1, quota);
795             statement.bindText(2, origin->databaseIdentifier());
796
797             error = !statement.executeCommand();
798         }
799
800         if (error)
801             LOG_ERROR("Failed to set quota %llu in tracker database for origin %s", quota, origin->databaseIdentifier().ascii().data());
802     }
803
804     if (m_client)
805 #if PLATFORM(IOS)
806     {
807         if (insertedNewOrigin)
808             m_client->dispatchDidAddNewOrigin(origin);
809 #endif
810         m_client->dispatchDidModifyOrigin(origin);
811 #if PLATFORM(IOS)
812     }
813 #endif
814 }
815
816 bool DatabaseTracker::addDatabase(SecurityOrigin* origin, const String& name, const String& path)
817 {
818     ASSERT(!m_databaseGuard.tryLock());
819     openTrackerDatabase(CreateIfDoesNotExist);
820     if (!m_database.isOpen())
821         return false;
822
823     // New database should never be added until the origin has been established
824     ASSERT(hasEntryForOriginNoLock(origin));
825
826     SQLiteStatement statement(m_database, "INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);");
827
828     if (statement.prepare() != SQLITE_OK)
829         return false;
830
831     statement.bindText(1, origin->databaseIdentifier());
832     statement.bindText(2, name);
833     statement.bindText(3, path);
834
835     if (!statement.executeCommand()) {
836         LOG_ERROR("Failed to add database %s to origin %s: %s\n", name.ascii().data(), origin->databaseIdentifier().ascii().data(), m_database.lastErrorMsg());
837         return false;
838     }
839
840     if (m_client)
841         m_client->dispatchDidModifyOrigin(origin);
842
843     return true;
844 }
845
846 void DatabaseTracker::deleteAllDatabases()
847 {
848     Vector<RefPtr<SecurityOrigin>> originsCopy;
849     origins(originsCopy);
850
851     for (auto& origin : originsCopy)
852         deleteOrigin(origin.get());
853 }
854
855 void DatabaseTracker::deleteDatabasesModifiedSince(std::chrono::system_clock::time_point time)
856 {
857     Vector<RefPtr<SecurityOrigin>> originsCopy;
858     origins(originsCopy);
859
860     for (auto& origin : originsCopy) {
861         Vector<String> databaseNames;
862         if (!databaseNamesForOrigin(origin.get(), databaseNames))
863             continue;
864
865         for (auto& databaseName : databaseNames) {
866             auto fullPath = fullPathForDatabase(origin.get(), databaseName, false);
867
868             time_t modificationTime;
869             if (!getFileModificationTime(fullPath, modificationTime))
870                 continue;
871
872             if (modificationTime < std::chrono::system_clock::to_time_t(time))
873                 continue;
874
875             deleteDatabase(origin.get(), databaseName);
876         }
877     }
878 }
879
880 // It is the caller's responsibility to make sure that nobody is trying to create, delete, open, or close databases in this origin while the deletion is
881 // taking place.
882 bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin)
883 {
884     Vector<String> databaseNames;
885     {
886         MutexLocker lockDatabase(m_databaseGuard);
887         openTrackerDatabase(DontCreateIfDoesNotExist);
888         if (!m_database.isOpen())
889             return false;
890
891         if (!databaseNamesForOriginNoLock(origin, databaseNames)) {
892             LOG_ERROR("Unable to retrieve list of database names for origin %s", origin->databaseIdentifier().ascii().data());
893             return false;
894         }
895         if (!canDeleteOrigin(origin)) {
896             LOG_ERROR("Tried to delete an origin (%s) while either creating database in it or already deleting it", origin->databaseIdentifier().ascii().data());
897             ASSERT_NOT_REACHED();
898             return false;
899         }
900         recordDeletingOrigin(origin);
901     }
902
903     // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock.
904     for (auto& name : databaseNames) {
905         if (!deleteDatabaseFile(origin, name)) {
906             // Even if the file can't be deleted, we want to try and delete the rest, don't return early here.
907             LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data());
908         }
909     }
910
911     {
912         MutexLocker lockDatabase(m_databaseGuard);
913         deleteOriginLockFor(origin);
914         doneDeletingOrigin(origin);
915
916         SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=?");
917         if (statement.prepare() != SQLITE_OK) {
918             LOG_ERROR("Unable to prepare deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data());
919             return false;
920         }
921
922         statement.bindText(1, origin->databaseIdentifier());
923
924         if (!statement.executeCommand()) {
925             LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data());
926             return false;
927         }
928
929         SQLiteStatement originStatement(m_database, "DELETE FROM Origins WHERE origin=?");
930         if (originStatement.prepare() != SQLITE_OK) {
931             LOG_ERROR("Unable to prepare deletion of origin %s from tracker", origin->databaseIdentifier().ascii().data());
932             return false;
933         }
934
935         originStatement.bindText(1, origin->databaseIdentifier());
936
937         if (!originStatement.executeCommand()) {
938             LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data());
939             return false;
940         }
941
942         SQLiteFileSystem::deleteEmptyDatabaseDirectory(originPath(origin));
943
944         RefPtr<SecurityOrigin> originPossiblyLastReference = origin;
945         bool isEmpty = true;
946
947         openTrackerDatabase(DontCreateIfDoesNotExist);
948         if (m_database.isOpen()) {
949             SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
950             if (statement.prepare() != SQLITE_OK)
951                 LOG_ERROR("Failed to prepare statement.");
952             else if (statement.step() == SQLITE_ROW)
953                 isEmpty = false;
954         }
955
956         // If we removed the last origin, do some additional deletion.
957         if (isEmpty) {
958             if (m_database.isOpen())
959                 m_database.close();
960            SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
961            SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_databaseDirectoryPath);
962         }
963
964         if (m_client) {
965             m_client->dispatchDidModifyOrigin(origin);
966 #if PLATFORM(IOS)
967             m_client->dispatchDidDeleteDatabaseOrigin();
968 #endif
969             for (auto& name : databaseNames)
970                 m_client->dispatchDidModifyDatabase(origin, name);
971         }
972     }
973     return true;
974 }
975
976 bool DatabaseTracker::isDeletingDatabaseOrOriginFor(SecurityOrigin *origin, const String& name)
977 {
978     ASSERT(!m_databaseGuard.tryLock());
979     // Can't create a database while someone else is deleting it; there's a risk of leaving untracked database debris on the disk.
980     return isDeletingDatabase(origin, name) || isDeletingOrigin(origin);
981 }
982
983 void DatabaseTracker::recordCreatingDatabase(SecurityOrigin *origin, const String& name)
984 {
985     ASSERT(!m_databaseGuard.tryLock());
986     NameCountMap* nameMap = m_beingCreated.get(origin);
987     if (!nameMap) {
988         nameMap = new NameCountMap();
989         m_beingCreated.set(origin->isolatedCopy(), nameMap);
990     }
991     long count = nameMap->get(name);
992     nameMap->set(name.isolatedCopy(), count + 1);
993 }
994
995 void DatabaseTracker::doneCreatingDatabase(SecurityOrigin *origin, const String& name)
996 {
997     ASSERT(!m_databaseGuard.tryLock());
998     NameCountMap* nameMap = m_beingCreated.get(origin);
999     ASSERT(nameMap);
1000     if (!nameMap)
1001         return;
1002
1003     long count = nameMap->get(name);
1004     ASSERT(count > 0);
1005     if (count <= 1) {
1006         nameMap->remove(name);
1007         if (nameMap->isEmpty()) {
1008             m_beingCreated.remove(origin);
1009             delete nameMap;
1010         }
1011     } else
1012         nameMap->set(name, count - 1);
1013 }
1014
1015 bool DatabaseTracker::creatingDatabase(SecurityOrigin *origin, const String& name)
1016 {
1017     ASSERT(!m_databaseGuard.tryLock());
1018     NameCountMap* nameMap = m_beingCreated.get(origin);
1019     return nameMap && nameMap->get(name);
1020 }
1021
1022 bool DatabaseTracker::canDeleteDatabase(SecurityOrigin *origin, const String& name)
1023 {
1024     ASSERT(!m_databaseGuard.tryLock());
1025     return !creatingDatabase(origin, name) && !isDeletingDatabase(origin, name);
1026 }
1027
1028 void DatabaseTracker::recordDeletingDatabase(SecurityOrigin *origin, const String& name)
1029 {
1030     ASSERT(!m_databaseGuard.tryLock());
1031     ASSERT(canDeleteDatabase(origin, name));
1032     NameSet* nameSet = m_beingDeleted.get(origin);
1033     if (!nameSet) {
1034         nameSet = new NameSet();
1035         m_beingDeleted.set(origin->isolatedCopy(), nameSet);
1036     }
1037     ASSERT(!nameSet->contains(name));
1038     nameSet->add(name.isolatedCopy());
1039 }
1040
1041 void DatabaseTracker::doneDeletingDatabase(SecurityOrigin *origin, const String& name)
1042 {
1043     ASSERT(!m_databaseGuard.tryLock());
1044     NameSet* nameSet = m_beingDeleted.get(origin);
1045     ASSERT(nameSet);
1046     if (!nameSet)
1047         return;
1048
1049     ASSERT(nameSet->contains(name));
1050     nameSet->remove(name);
1051     if (nameSet->isEmpty()) {
1052         m_beingDeleted.remove(origin);
1053         delete nameSet;
1054     }
1055 }
1056
1057 bool DatabaseTracker::isDeletingDatabase(SecurityOrigin *origin, const String& name)
1058 {
1059     ASSERT(!m_databaseGuard.tryLock());
1060     NameSet* nameSet = m_beingDeleted.get(origin);
1061     return nameSet && nameSet->contains(name);
1062 }
1063
1064 bool DatabaseTracker::canDeleteOrigin(SecurityOrigin *origin)
1065 {
1066     ASSERT(!m_databaseGuard.tryLock());
1067     return !(isDeletingOrigin(origin) || m_beingCreated.get(origin));
1068 }
1069
1070 bool DatabaseTracker::isDeletingOrigin(SecurityOrigin *origin)
1071 {
1072     ASSERT(!m_databaseGuard.tryLock());
1073     return m_originsBeingDeleted.contains(origin);
1074 }
1075
1076 void DatabaseTracker::recordDeletingOrigin(SecurityOrigin *origin)
1077 {
1078     ASSERT(!m_databaseGuard.tryLock());
1079     ASSERT(!isDeletingOrigin(origin));
1080     m_originsBeingDeleted.add(origin->isolatedCopy());
1081 }
1082
1083 void DatabaseTracker::doneDeletingOrigin(SecurityOrigin *origin)
1084 {
1085     ASSERT(!m_databaseGuard.tryLock());
1086     ASSERT(isDeletingOrigin(origin));
1087     m_originsBeingDeleted.remove(origin);
1088 }
1089
1090 bool DatabaseTracker::deleteDatabase(SecurityOrigin* origin, const String& name)
1091 {
1092     {
1093         MutexLocker lockDatabase(m_databaseGuard);
1094         openTrackerDatabase(DontCreateIfDoesNotExist);
1095         if (!m_database.isOpen())
1096             return false;
1097
1098         if (!canDeleteDatabase(origin, name)) {
1099             ASSERT_NOT_REACHED();
1100             return false;
1101         }
1102         recordDeletingDatabase(origin, name);
1103     }
1104
1105     // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock.
1106     if (!deleteDatabaseFile(origin, name)) {
1107         LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data());
1108         MutexLocker lockDatabase(m_databaseGuard);
1109         doneDeletingDatabase(origin, name);
1110         return false;
1111     }
1112
1113     MutexLocker lockDatabase(m_databaseGuard);
1114
1115     SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=? AND name=?");
1116     if (statement.prepare() != SQLITE_OK) {
1117         LOG_ERROR("Unable to prepare deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data());
1118         doneDeletingDatabase(origin, name);
1119         return false;
1120     }
1121
1122     statement.bindText(1, origin->databaseIdentifier());
1123     statement.bindText(2, name);
1124
1125     if (!statement.executeCommand()) {
1126         LOG_ERROR("Unable to execute deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data());
1127         doneDeletingDatabase(origin, name);
1128         return false;
1129     }
1130
1131     if (m_client) {
1132         m_client->dispatchDidModifyOrigin(origin);
1133         m_client->dispatchDidModifyDatabase(origin, name);
1134 #if PLATFORM(IOS)
1135         m_client->dispatchDidDeleteDatabase();
1136 #endif
1137     }
1138     doneDeletingDatabase(origin, name);
1139     
1140     return true;
1141 }
1142
1143 // deleteDatabaseFile has to release locks between looking up the list of databases to close and closing them.  While this is in progress, the caller
1144 // is responsible for making sure no new databases are opened in the file to be deleted.
1145 bool DatabaseTracker::deleteDatabaseFile(SecurityOrigin* origin, const String& name)
1146 {
1147     String fullPath = fullPathForDatabase(origin, name, false);
1148     if (fullPath.isEmpty())
1149         return true;
1150
1151 #ifndef NDEBUG
1152     {
1153         MutexLocker lockDatabase(m_databaseGuard);
1154         ASSERT(isDeletingDatabaseOrOriginFor(origin, name));
1155     }
1156 #endif
1157
1158     Vector<RefPtr<Database>> deletedDatabases;
1159
1160     // Make sure not to hold the any locks when calling
1161     // Database::markAsDeletedAndClose(), since that can cause a deadlock
1162     // during the synchronous DatabaseThread call it triggers.
1163     {
1164         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
1165         if (m_openDatabaseMap) {
1166             // There are some open databases, lets check if they are for this origin.
1167             DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);
1168             if (nameMap && nameMap->size()) {
1169                 // There are some open databases for this origin, let's check
1170                 // if they are this database by name.
1171                 DatabaseSet* databaseSet = nameMap->get(name);
1172                 if (databaseSet && databaseSet->size()) {
1173                     // We have some database open with this name. Mark them as deleted.
1174                     for (auto& database : *databaseSet)
1175                         deletedDatabases.append(database);
1176                 }
1177             }
1178         }
1179     }
1180
1181     for (auto& database : deletedDatabases)
1182         database->markAsDeletedAndClose();
1183
1184 #if !PLATFORM(IOS)
1185     return SQLiteFileSystem::deleteDatabaseFile(fullPath);
1186 #else
1187     // On the phone, other background processes may still be accessing this database.  Deleting the database directly
1188     // would nuke the POSIX file locks, potentially causing Safari/WebApp to corrupt the new db if it's running in the background.
1189     // We'll instead truncate the database file to 0 bytes.  If another process is operating on this same database file after
1190     // the truncation, it should get an error since the database file is no longer valid.  When Safari is launched
1191     // next time, it'll go through the database files and clean up any zero-bytes ones.
1192     SQLiteDatabase database;
1193     if (database.open(fullPath))
1194         return SQLiteFileSystem::truncateDatabaseFile(database.sqlite3Handle());
1195     return false;
1196 #endif
1197 }
1198     
1199 #if PLATFORM(IOS)
1200 void DatabaseTracker::removeDeletedOpenedDatabases()
1201 {
1202     // This is called when another app has deleted a database.  Go through all opened databases in this
1203     // tracker and close any that's no longer being tracked in the database.
1204     
1205     {
1206         // Acquire the lock before calling openTrackerDatabase.
1207         MutexLocker lockDatabase(m_databaseGuard);
1208         openTrackerDatabase(DontCreateIfDoesNotExist);
1209     }
1210
1211     if (!m_database.isOpen())
1212         return;
1213     
1214     // Keep track of which opened databases have been deleted.
1215     Vector<RefPtr<Database> > deletedDatabases;
1216     typedef HashMap<RefPtr<SecurityOrigin>, Vector<String> > DeletedDatabaseMap;
1217     DeletedDatabaseMap deletedDatabaseMap;
1218     
1219     // Make sure not to hold the m_openDatabaseMapGuard mutex when calling
1220     // Database::markAsDeletedAndClose(), since that can cause a deadlock
1221     // during the synchronous DatabaseThread call it triggers.
1222     {
1223         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
1224         if (m_openDatabaseMap) {
1225             for (auto& openDatabase : *m_openDatabaseMap) {
1226                 auto& origin = openDatabase.key;
1227                 DatabaseNameMap* databaseNameMap = openDatabase.value;
1228                 Vector<String> deletedDatabaseNamesForThisOrigin;
1229
1230                 // Loop through all opened databases in this origin.  Get the current database file path of each database and see if
1231                 // it still matches the path stored in the opened database object.
1232                 for (auto& databases : *databaseNameMap) {
1233                     String databaseName = databases.key;
1234                     String databaseFileName;
1235                     SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;");
1236                     if (statement.prepare() == SQLITE_OK) {
1237                         statement.bindText(1, origin->databaseIdentifier());
1238                         statement.bindText(2, databaseName);
1239                         if (statement.step() == SQLITE_ROW)
1240                             databaseFileName = statement.getColumnText(0);
1241                         statement.finalize();
1242                     }
1243                     
1244                     bool foundDeletedDatabase = false;
1245                     for (auto& db : *databases.value) {
1246                         // We are done if this database has already been marked as deleted.
1247                         if (db->deleted())
1248                             continue;
1249                         
1250                         // If this database has been deleted or if its database file no longer matches the current version, this database is no longer valid and it should be marked as deleted.
1251                         if (databaseFileName.isNull() || databaseFileName != pathGetFileName(db->fileName())) {
1252                             deletedDatabases.append(db);
1253                             foundDeletedDatabase = true;
1254                         }
1255                     }
1256                     
1257                     // If the database no longer exists, we should remember to remove it from the OriginQuotaManager later.
1258                     if (foundDeletedDatabase && databaseFileName.isNull())
1259                         deletedDatabaseNamesForThisOrigin.append(databaseName);
1260                 }
1261                 
1262                 if (!deletedDatabaseNamesForThisOrigin.isEmpty())
1263                     deletedDatabaseMap.set(origin, deletedDatabaseNamesForThisOrigin);
1264             }
1265         }
1266     }
1267     
1268     for (auto& deletedDatabase : deletedDatabases)
1269         deletedDatabase->markAsDeletedAndClose();
1270
1271     for (auto& deletedDatabase : deletedDatabaseMap) {
1272         SecurityOrigin* origin = deletedDatabase.key.get();
1273         if (m_client)
1274             m_client->dispatchDidModifyOrigin(origin);
1275         
1276         const Vector<String>& databaseNames = deletedDatabase.value;
1277         for (auto& databaseName : databaseNames) {
1278             if (m_client)
1279                 m_client->dispatchDidModifyDatabase(origin, databaseName);
1280         }        
1281     }
1282 }
1283     
1284 static bool isZeroByteFile(const String& path)
1285 {
1286     long long size = 0;
1287     return getFileSize(path, size) && !size;
1288 }
1289     
1290 bool DatabaseTracker::deleteDatabaseFileIfEmpty(const String& path)
1291 {
1292     if (!isZeroByteFile(path))
1293         return false;
1294     
1295     SQLiteDatabase database;
1296     if (!database.open(path))
1297         return false;
1298     
1299     // Specify that we want the exclusive locking mode, so after the next read,
1300     // we'll be holding the lock to this database file.
1301     SQLiteStatement lockStatement(database, "PRAGMA locking_mode=EXCLUSIVE;");
1302     if (lockStatement.prepare() != SQLITE_OK)
1303         return false;
1304     int result = lockStatement.step();
1305     if (result != SQLITE_ROW && result != SQLITE_DONE)
1306         return false;
1307     lockStatement.finalize();
1308
1309     // Every sqlite database has a sqlite_master table that contains the schema for the database.
1310     // http://www.sqlite.org/faq.html#q7
1311     SQLiteStatement readStatement(database, "SELECT * FROM sqlite_master LIMIT 1;");    
1312     if (readStatement.prepare() != SQLITE_OK)
1313         return false;
1314     // We shouldn't expect any result.
1315     if (readStatement.step() != SQLITE_DONE)
1316         return false;
1317     readStatement.finalize();
1318     
1319     // At this point, we hold the exclusive lock to this file.  Double-check again to make sure
1320     // it's still zero bytes.
1321     if (!isZeroByteFile(path))
1322         return false;
1323     
1324     return SQLiteFileSystem::deleteDatabaseFile(path);
1325 }
1326
1327 Mutex& DatabaseTracker::openDatabaseMutex()
1328 {
1329     static NeverDestroyed<Mutex> mutex;
1330     return mutex;
1331 }
1332
1333 void DatabaseTracker::emptyDatabaseFilesRemovalTaskWillBeScheduled()
1334 {
1335     // Lock the database from opening any database until we are done with scanning the file system for
1336     // zero byte database files to remove.
1337     openDatabaseMutex().lock();
1338 }
1339
1340 void DatabaseTracker::emptyDatabaseFilesRemovalTaskDidFinish()
1341 {
1342     openDatabaseMutex().unlock();
1343 }
1344
1345 void DatabaseTracker::setDatabasesPaused(bool paused)
1346 {
1347     MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
1348     if (!m_openDatabaseMap)
1349         return;
1350
1351     // This walking is - sadly - the only reliable way to get at each open database thread.
1352     // This will be cleaner once <rdar://problem/5680441> or some other DB thread consolidation takes place.
1353     for (auto& databaseNameMap : m_openDatabaseMap->values()) {
1354         for (auto& databaseSet : databaseNameMap->values()) {
1355             for (auto& database : *databaseSet)
1356                 database->databaseContext()->setPaused(paused);
1357         }
1358     }
1359 }
1360
1361 #endif
1362
1363 void DatabaseTracker::setClient(DatabaseManagerClient* client)
1364 {
1365     m_client = client;
1366 }
1367
1368 static Mutex& notificationMutex()
1369 {
1370     static NeverDestroyed<Mutex> mutex;
1371     return mutex;
1372 }
1373
1374 typedef Vector<std::pair<RefPtr<SecurityOrigin>, String>> NotificationQueue;
1375
1376 static NotificationQueue& notificationQueue()
1377 {
1378     static NeverDestroyed<NotificationQueue> queue;
1379     return queue;
1380 }
1381
1382 void DatabaseTracker::scheduleNotifyDatabaseChanged(SecurityOrigin* origin, const String& name)
1383 {
1384     MutexLocker locker(notificationMutex());
1385
1386     notificationQueue().append(std::pair<RefPtr<SecurityOrigin>, String>(origin->isolatedCopy(), name.isolatedCopy()));
1387     scheduleForNotification();
1388 }
1389
1390 static bool notificationScheduled = false;
1391
1392 void DatabaseTracker::scheduleForNotification()
1393 {
1394     ASSERT(!notificationMutex().tryLock());
1395
1396     if (!notificationScheduled) {
1397         callOnMainThread(DatabaseTracker::notifyDatabasesChanged, 0);
1398         notificationScheduled = true;
1399     }
1400 }
1401
1402 void DatabaseTracker::notifyDatabasesChanged(void*)
1403 {
1404     // Note that if DatabaseTracker ever becomes non-singleton, we'll have to amend this notification
1405     // mechanism to include which tracker the notification goes out on as well.
1406     DatabaseTracker& theTracker(tracker());
1407
1408     NotificationQueue notifications;
1409     {
1410         MutexLocker locker(notificationMutex());
1411
1412         notifications.swap(notificationQueue());
1413
1414         notificationScheduled = false;
1415     }
1416
1417     if (!theTracker.m_client)
1418         return;
1419
1420     for (unsigned i = 0; i < notifications.size(); ++i)
1421         theTracker.m_client->dispatchDidModifyDatabase(notifications[i].first.get(), notifications[i].second);
1422 }
1423
1424
1425 } // namespace WebCore