summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/loader/icon/IconDatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/loader/icon/IconDatabase.cpp')
-rw-r--r--Source/WebCore/loader/icon/IconDatabase.cpp184
1 files changed, 157 insertions, 27 deletions
diff --git a/Source/WebCore/loader/icon/IconDatabase.cpp b/Source/WebCore/loader/icon/IconDatabase.cpp
index 26f3bb7..e5578e0 100644
--- a/Source/WebCore/loader/icon/IconDatabase.cpp
+++ b/Source/WebCore/loader/icon/IconDatabase.cpp
@@ -58,7 +58,6 @@
namespace WebCore {
-static IconDatabase* sharedIconDatabase = 0;
static int databaseCleanupCounter = 0;
// This version number is in the DB and marks the current generation of the schema
@@ -85,21 +84,22 @@ static String urlForLogging(const String& url)
}
#endif
+class DefaultIconDatabaseClient : public IconDatabaseClient {
+public:
+ virtual bool performImport() { return true; }
+ virtual void didImportIconURLForPageURL(const String&) { }
+ virtual void didImportIconDataForPageURL(const String&) { }
+ virtual void didChangeIconForPageURL(const String&) { }
+ virtual void didRemoveAllIcons() { }
+ virtual void didFinishURLImport() { }
+};
+
static IconDatabaseClient* defaultClient()
{
- static IconDatabaseClient* defaultClient = new IconDatabaseClient();
+ static IconDatabaseClient* defaultClient = new DefaultIconDatabaseClient();
return defaultClient;
}
-IconDatabase& iconDatabase()
-{
- if (!sharedIconDatabase) {
- ScriptController::initializeThreading();
- sharedIconDatabase = new IconDatabase;
- }
- return *sharedIconDatabase;
-}
-
// ************************
// *** Main Thread Only ***
// ************************
@@ -117,7 +117,7 @@ void IconDatabase::setClient(IconDatabaseClient* client)
m_client = client;
}
-bool IconDatabase::open(const String& databasePath)
+bool IconDatabase::open(const String& directory, const String& filename)
{
ASSERT_NOT_SYNC_THREAD();
@@ -129,10 +129,10 @@ bool IconDatabase::open(const String& databasePath)
return false;
}
- m_databaseDirectory = databasePath.crossThreadString();
+ m_databaseDirectory = directory.crossThreadString();
// Formulate the full path for the database file
- m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, defaultDatabaseFilename());
+ m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, filename);
// Lock here as well as first thing in the thread so the thread doesn't actually commence until the createThread() call
// completes and m_syncThreadRunning is properly set
@@ -217,7 +217,7 @@ void IconDatabase::removeAllIcons()
wakeSyncThread();
}
-Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize& size)
+Image* IconDatabase::synchronousIconForPageURL(const String& pageURLOriginal, const IntSize& size)
{
ASSERT_NOT_SYNC_THREAD();
@@ -301,10 +301,10 @@ void IconDatabase::readIconForPageURLFromDisk(const String& pageURL)
// The effect of asking for an Icon for a pageURL automatically queues it to be read from disk
// if it hasn't already been set in memory. The special IntSize (0, 0) is a special way of telling
// that method "I don't care about the actual Image, i just want you to make sure you're getting it from disk.
- iconForPageURL(pageURL, IntSize(0,0));
+ synchronousIconForPageURL(pageURL, IntSize(0, 0));
}
-String IconDatabase::iconURLForPageURL(const String& pageURLOriginal)
+String IconDatabase::synchronousIconURLForPageURL(const String& pageURLOriginal)
{
ASSERT_NOT_SYNC_THREAD();
@@ -565,7 +565,7 @@ void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> dataOriginal,
for (unsigned i = 0; i < pageURLs.size(); ++i) {
LOG(IconDatabase, "Dispatching notification that retaining pageURL %s has a new icon", urlForLogging(pageURLs[i]).ascii().data());
- m_client->dispatchDidAddIconForPageURL(pageURLs[i]);
+ m_client->didChangeIconForPageURL(pageURLs[i]);
pool.cycle();
}
@@ -637,11 +637,11 @@ void IconDatabase::setIconURLForPageURL(const String& iconURLOriginal, const Str
LOG(IconDatabase, "Dispatching notification that we changed an icon mapping for url %s", urlForLogging(pageURL).ascii().data());
AutodrainedPool pool;
- m_client->dispatchDidAddIconForPageURL(pageURL);
+ m_client->didChangeIconForPageURL(pageURL);
}
}
-IconLoadDecision IconDatabase::loadDecisionForIconURL(const String& iconURL, DocumentLoader* notificationDocumentLoader)
+IconLoadDecision IconDatabase::synchronousLoadDecisionForIconURL(const String& iconURL, DocumentLoader* notificationDocumentLoader)
{
ASSERT_NOT_SYNC_THREAD();
@@ -667,12 +667,13 @@ IconLoadDecision IconDatabase::loadDecisionForIconURL(const String& iconURL, Doc
// Otherwise - since we refuse to perform I/O on the main thread to find out for sure - we return the answer that says
// "You might be asked to load this later, so flag that"
LOG(IconDatabase, "Don't know if we should load %s or not - adding %p to the set of document loaders waiting on a decision", iconURL.ascii().data(), notificationDocumentLoader);
- m_loadersPendingDecision.add(notificationDocumentLoader);
+ if (notificationDocumentLoader)
+ m_loadersPendingDecision.add(notificationDocumentLoader);
return IconLoadUnknown;
}
-bool IconDatabase::iconDataKnownForIconURL(const String& iconURL)
+bool IconDatabase::synchronousIconDataKnownForIconURL(const String& iconURL)
{
ASSERT_NOT_SYNC_THREAD();
@@ -775,6 +776,7 @@ IconDatabase::IconDatabase()
, m_imported(false)
, m_isImportedSet(false)
{
+ LOG(IconDatabase, "Creating IconDatabase %p", this);
ASSERT(isMainThread());
}
@@ -1257,7 +1259,7 @@ void IconDatabase::performURLImport()
{
MutexLocker locker(m_pendingReadingLock);
if (m_pageURLsPendingImport.contains(pageURL)) {
- m_client->dispatchDidAddIconForPageURL(pageURL);
+ dispatchDidImportIconURLForPageURLOnMainThread(pageURL);
m_pageURLsPendingImport.remove(pageURL);
pool.cycle();
@@ -1292,7 +1294,6 @@ void IconDatabase::performURLImport()
// Loop through the urls pending import
// Remove unretained ones if database cleanup is allowed
// Keep a set of ones that are retained and pending notification
-
{
MutexLocker locker(m_urlAndIconLock);
@@ -1331,13 +1332,16 @@ void IconDatabase::performURLImport()
// Now that we don't hold any locks, perform the actual notifications
for (unsigned i = 0; i < urlsToNotify.size(); ++i) {
LOG(IconDatabase, "Notifying icon info known for pageURL %s", urlsToNotify[i].ascii().data());
- m_client->dispatchDidAddIconForPageURL(urlsToNotify[i]);
+ dispatchDidImportIconURLForPageURLOnMainThread(urlsToNotify[i]);
if (shouldStopThreadActivity())
return;
pool.cycle();
}
+ // Notify the client that the URL import is complete in case it's managing its own pending notifications.
+ dispatchDidFinishURLImportOnMainThread();
+
// Notify all DocumentLoaders that were waiting for an icon load decision on the main thread
callOnMainThread(notifyPendingLoadDecisionsOnMainThread, this);
}
@@ -1540,7 +1544,7 @@ bool IconDatabase::readFromDatabase()
HashSet<String>::iterator end = urlsToNotify.end();
for (unsigned iteration = 0; iter != end; ++iter, ++iteration) {
LOG(IconDatabase, "Notifying icon received for pageURL %s", urlForLogging(*iter).ascii().data());
- m_client->dispatchDidAddIconForPageURL(*iter);
+ dispatchDidImportIconDataForPageURLOnMainThread(*iter);
if (shouldStopThreadActivity())
return didAnyWork;
@@ -1738,7 +1742,7 @@ void IconDatabase::removeAllIconsOnThread()
createDatabaseTables(m_syncDB);
LOG(IconDatabase, "Dispatching notification that we removed all icons");
- m_client->dispatchDidRemoveAllIcons();
+ dispatchDidRemoveAllIconsOnMainThread();
}
void IconDatabase::deleteAllPreparedStatements()
@@ -2111,6 +2115,132 @@ void IconDatabase::setWasExcludedFromBackup()
SQLiteStatement(m_syncDB, "INSERT INTO IconDatabaseInfo (key, value) VALUES ('ExcludedFromBackup', 1)").executeCommand();
}
+class ClientWorkItem {
+public:
+ ClientWorkItem(IconDatabaseClient* client)
+ : m_client(client)
+ { }
+ virtual void performWork() = 0;
+ virtual ~ClientWorkItem() { }
+
+protected:
+ IconDatabaseClient* m_client;
+};
+
+class ImportedIconURLForPageURLWorkItem : public ClientWorkItem {
+public:
+ ImportedIconURLForPageURLWorkItem(IconDatabaseClient* client, const String& pageURL)
+ : ClientWorkItem(client)
+ , m_pageURL(new String(pageURL.threadsafeCopy()))
+ { }
+
+ virtual ~ImportedIconURLForPageURLWorkItem()
+ {
+ delete m_pageURL;
+ }
+
+ virtual void performWork()
+ {
+ ASSERT(m_client);
+ m_client->didImportIconURLForPageURL(*m_pageURL);
+ m_client = 0;
+ }
+
+private:
+ String* m_pageURL;
+};
+
+class ImportedIconDataForPageURLWorkItem : public ClientWorkItem {
+public:
+ ImportedIconDataForPageURLWorkItem(IconDatabaseClient* client, const String& pageURL)
+ : ClientWorkItem(client)
+ , m_pageURL(new String(pageURL.threadsafeCopy()))
+ { }
+
+ virtual ~ImportedIconDataForPageURLWorkItem()
+ {
+ delete m_pageURL;
+ }
+
+ virtual void performWork()
+ {
+ ASSERT(m_client);
+ m_client->didImportIconDataForPageURL(*m_pageURL);
+ m_client = 0;
+ }
+
+private:
+ String* m_pageURL;
+};
+
+class RemovedAllIconsWorkItem : public ClientWorkItem {
+public:
+ RemovedAllIconsWorkItem(IconDatabaseClient* client)
+ : ClientWorkItem(client)
+ { }
+
+ virtual void performWork()
+ {
+ ASSERT(m_client);
+ m_client->didRemoveAllIcons();
+ m_client = 0;
+ }
+};
+
+class FinishedURLImport : public ClientWorkItem {
+public:
+ FinishedURLImport(IconDatabaseClient* client)
+ : ClientWorkItem(client)
+ { }
+
+ virtual void performWork()
+ {
+ ASSERT(m_client);
+ m_client->didFinishURLImport();
+ m_client = 0;
+ }
+};
+
+static void performWorkItem(void* context)
+{
+ ClientWorkItem* item = static_cast<ClientWorkItem*>(context);
+ item->performWork();
+ delete item;
+}
+
+void IconDatabase::dispatchDidImportIconURLForPageURLOnMainThread(const String& pageURL)
+{
+ ASSERT_ICON_SYNC_THREAD();
+
+ ImportedIconURLForPageURLWorkItem* work = new ImportedIconURLForPageURLWorkItem(m_client, pageURL);
+ callOnMainThread(performWorkItem, work);
+}
+
+void IconDatabase::dispatchDidImportIconDataForPageURLOnMainThread(const String& pageURL)
+{
+ ASSERT_ICON_SYNC_THREAD();
+
+ ImportedIconDataForPageURLWorkItem* work = new ImportedIconDataForPageURLWorkItem(m_client, pageURL);
+ callOnMainThread(performWorkItem, work);
+}
+
+void IconDatabase::dispatchDidRemoveAllIconsOnMainThread()
+{
+ ASSERT_ICON_SYNC_THREAD();
+
+ RemovedAllIconsWorkItem* work = new RemovedAllIconsWorkItem(m_client);
+ callOnMainThread(performWorkItem, work);
+}
+
+void IconDatabase::dispatchDidFinishURLImportOnMainThread()
+{
+ ASSERT_ICON_SYNC_THREAD();
+
+ FinishedURLImport* work = new FinishedURLImport(m_client);
+ callOnMainThread(performWorkItem, work);
+}
+
+
} // namespace WebCore
#endif // ENABLE(ICONDATABASE)