diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
commit | 1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch) | |
tree | 4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/loader/icon/IconDatabase.cpp | |
parent | 9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff) | |
download | external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/loader/icon/IconDatabase.cpp')
-rw-r--r-- | WebCore/loader/icon/IconDatabase.cpp | 120 |
1 files changed, 77 insertions, 43 deletions
diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp index 79250b8..a47fb08 100644 --- a/WebCore/loader/icon/IconDatabase.cpp +++ b/WebCore/loader/icon/IconDatabase.cpp @@ -41,6 +41,8 @@ #include "SQLiteStatement.h" #include "SQLiteTransaction.h" #include "SystemTime.h" +#include <runtime/InitializeThreading.h> +#include <wtf/MainThread.h> #if PLATFORM(WIN_OS) #include <windows.h> @@ -63,6 +65,10 @@ #define IS_ICON_SYNC_THREAD() (m_syncThread == currentThread()) #define ASSERT_ICON_SYNC_THREAD() ASSERT(IS_ICON_SYNC_THREAD()) +#if PLATFORM(QT) +#define CAN_THEME_URL_ICON +#endif + namespace WebCore { static IconDatabase* sharedIconDatabase = 0; @@ -101,7 +107,7 @@ static IconDatabaseClient* defaultClient() IconDatabase* iconDatabase() { if (!sharedIconDatabase) { - initializeThreading(); + JSC::initializeThreading(); sharedIconDatabase = new IconDatabase; } return sharedIconDatabase; @@ -144,7 +150,7 @@ bool IconDatabase::open(const String& databasePath) // 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 m_syncLock.lock(); - m_syncThread = createThread(IconDatabase::iconDatabaseSyncThreadStart, this); + m_syncThread = createThread(IconDatabase::iconDatabaseSyncThreadStart, this, "WebCore::IconDatabase"); m_syncLock.unlock(); if (!m_syncThread) return false; @@ -220,16 +226,14 @@ void IconDatabase::removeAllIcons() wakeSyncThread(); } -Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize& size, bool cache) +Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize& size) { ASSERT_NOT_SYNC_THREAD(); - - ASSERT(!pageURLOriginal.isNull()); - // pageURLOriginal can not be stored without being deep copied first. + // pageURLOriginal cannot be stored without being deep copied first. // We should go our of our way to only copy it if we have to store it - if (!isOpen()) + if (!isOpen() || pageURLOriginal.isEmpty()) return defaultIcon(size); MutexLocker locker(m_urlAndIconLock); @@ -335,10 +339,14 @@ String IconDatabase::iconURLForPageURL(const String& pageURLOriginal) return pageRecord->iconRecord() ? pageRecord->iconRecord()->iconURL().copy() : String(); } -Image* IconDatabase::defaultIcon(const IntSize& size) +#ifdef CAN_THEME_URL_ICON +static inline void loadDefaultIconRecord(IconRecord* defaultIconRecord) +{ + defaultIconRecord->loadImageFromResource("urlIcon"); +} +#else +static inline void loadDefaultIconRecord(IconRecord* defaultIconRecord) { - ASSERT_NOT_SYNC_THREAD(); - static const unsigned char defaultIconData[] = { 0x4D, 0x4D, 0x00, 0x2A, 0x00, 0x00, 0x03, 0x32, 0x80, 0x00, 0x20, 0x50, 0x38, 0x24, 0x16, 0x0D, 0x07, 0x84, 0x42, 0x61, 0x50, 0xB8, 0x64, 0x08, 0x18, 0x0D, 0x0A, 0x0B, 0x84, 0xA2, 0xA1, 0xE2, 0x08, 0x5E, 0x39, 0x28, 0xAF, 0x48, 0x24, 0xD3, 0x53, 0x9A, 0x37, 0x1D, 0x18, 0x0E, 0x8A, 0x4B, 0xD1, 0x38, 0xB0, 0x7C, 0x82, 0x07, 0x03, 0x82, 0xA2, 0xE8, 0x6C, 0x2C, 0x03, 0x2F, 0x02, 0x82, 0x41, 0xA1, 0xE2, 0xF8, 0xC8, 0x84, 0x68, 0x6D, 0x1C, 0x11, 0x0A, 0xB7, 0xFA, 0x91, @@ -377,11 +385,19 @@ Image* IconDatabase::defaultIcon(const IntSize& size) 0x00, 0x00, 0x01, 0x52, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0A, 0xFC, 0x80, 0x00, 0x00, 0x27, 0x10, 0x00, 0x0A, 0xFC, 0x80, 0x00, 0x00, 0x27, 0x10 }; - static RefPtr<SharedBuffer> defaultIconBuffer(new SharedBuffer(defaultIconData, sizeof(defaultIconData))); + static RefPtr<SharedBuffer> defaultIconBuffer(SharedBuffer::create(defaultIconData, sizeof(defaultIconData))); + defaultIconRecord->setImageData(defaultIconBuffer); +} +#endif + +Image* IconDatabase::defaultIcon(const IntSize& size) +{ + ASSERT_NOT_SYNC_THREAD(); + if (!m_defaultIconRecord) { - m_defaultIconRecord = new IconRecord("urlIcon"); - m_defaultIconRecord->setImageData(defaultIconBuffer); + m_defaultIconRecord = IconRecord::create("urlIcon"); + loadDefaultIconRecord(m_defaultIconRecord.get()); } return m_defaultIconRecord->image(size); @@ -518,10 +534,10 @@ void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> dataOriginal, MutexLocker locker(m_urlAndIconLock); // If this icon was pending a read, remove it from that set because this new data should override what is on disk - IconRecord* icon = m_iconURLToRecordMap.get(iconURL); + RefPtr<IconRecord> icon = m_iconURLToRecordMap.get(iconURL); if (icon) { MutexLocker locker(m_pendingReadingLock); - m_iconsPendingReading.remove(icon); + m_iconsPendingReading.remove(icon.get()); } else icon = getOrCreateIconRecord(iconURL); @@ -537,6 +553,12 @@ void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> dataOriginal, MutexLocker locker(m_pendingSyncLock); m_iconsPendingSync.set(iconURL, icon->snapshot()); } + + if (icon->hasOneRef()) { + ASSERT(icon->retainingPageURLs().isEmpty()); + LOG(IconDatabase, "Icon for icon url %s is about to be destroyed - removing mapping for it", urlForLogging(icon->iconURL()).ascii().data()); + m_iconURLToRecordMap.remove(icon->iconURL()); + } } // Send notification out regarding all PageURLs that retain this icon @@ -593,8 +615,7 @@ void IconDatabase::setIconURLForPageURL(const String& iconURLOriginal, const Str RefPtr<IconRecord> iconRecord = pageRecord->iconRecord(); // Otherwise, set the new icon record for this page - IconRecord* newIconRecord = getOrCreateIconRecord(iconURL); - pageRecord->setIconRecord(newIconRecord); + pageRecord->setIconRecord(getOrCreateIconRecord(iconURL)); // If the current icon has only a single ref left, it is about to get wiped out. // Remove it from the in-memory records and don't bother reading it in from disk anymore @@ -611,7 +632,7 @@ void IconDatabase::setIconURLForPageURL(const String& iconURLOriginal, const Str MutexLocker locker(m_pendingSyncLock); m_pageURLsPendingSync.set(pageURL, pageRecord->snapshot()); - // If the icon is on it's last ref, mark it for deletion + // If the icon is on its last ref, mark it for deletion if (iconRecord && iconRecord->hasOneRef()) m_iconsPendingSync.set(iconRecord->iconURL(), iconRecord->snapshot(true)); } @@ -839,18 +860,18 @@ String IconDatabase::defaultDatabaseFilename() } // Unlike getOrCreatePageURLRecord(), getOrCreateIconRecord() does not mark the icon as "interested in import" -IconRecord* IconDatabase::getOrCreateIconRecord(const String& iconURL) +PassRefPtr<IconRecord> IconDatabase::getOrCreateIconRecord(const String& iconURL) { // Clients of getOrCreateIconRecord() are required to acquire the m_urlAndIconLock before calling this method ASSERT(!m_urlAndIconLock.tryLock()); if (IconRecord* icon = m_iconURLToRecordMap.get(iconURL)) return icon; - - IconRecord* newIcon = new IconRecord(iconURL); - m_iconURLToRecordMap.set(iconURL, newIcon); - - return newIcon; + + RefPtr<IconRecord> newIcon = IconRecord::create(iconURL); + m_iconURLToRecordMap.set(iconURL, newIcon.get()); + + return newIcon.release(); } // This method retrieves the existing PageURLRecord, or creates a new one and marks it as "interested in the import" for later notification @@ -1205,8 +1226,8 @@ void IconDatabase::performURLImport() IconRecord* currentIcon = pageRecord->iconRecord(); if (!currentIcon || currentIcon->iconURL() != iconURL) { - currentIcon = getOrCreateIconRecord(iconURL); - pageRecord->setIconRecord(currentIcon); + pageRecord->setIconRecord(getOrCreateIconRecord(iconURL)); + currentIcon = pageRecord->iconRecord(); } // Regardless, the time stamp from disk still takes precedence. Until we read this icon from disk, we didn't think we'd seen it before @@ -1335,6 +1356,18 @@ void* IconDatabase::syncThreadMainLoop() bool didAnyWork = true; while (didAnyWork) { +#ifdef ANDROID_FIX + // We should write the pending icons to the database before trying + // to read any requested icons to ensure that a requested icon has + // the correct data. + bool didWrite = writeToDatabase(); + if (shouldStopThreadActivity()) + break; + + didAnyWork = readFromDatabase(); + if (shouldStopThreadActivity()) + break; +#else didAnyWork = readFromDatabase(); if (shouldStopThreadActivity()) break; @@ -1342,6 +1375,8 @@ void* IconDatabase::syncThreadMainLoop() bool didWrite = writeToDatabase(); if (shouldStopThreadActivity()) break; +#endif + // Prune unretained icons after the first time we sync anything out to the database // This way, pruning won't be the only operation we perform to the database by itself @@ -1536,22 +1571,20 @@ bool IconDatabase::writeToDatabase() } for (unsigned i = 0; i < pageSnapshots.size(); ++i) { - String iconURL = pageSnapshots[i].iconURL; - // If the icon URL is empty, this page is meant to be deleted // ASSERTs are sanity checks to make sure the mappings exist if they should and don't if they shouldn't if (pageSnapshots[i].iconURL.isEmpty()) removePageURLFromSQLDatabase(pageSnapshots[i].pageURL); - else { + else setIconURLForPageURLInSQLDatabase(pageSnapshots[i].iconURL, pageSnapshots[i].pageURL); - } LOG(IconDatabase, "Committed IconURL for PageURL %s to database", urlForLogging(pageSnapshots[i].pageURL).ascii().data()); } syncTransaction.commit(); // Check to make sure there are no dangling PageURLs - If there are, we want to output one log message but not spam the console potentially every few seconds - checkForDanglingPageURLs(false); + if (didAnyWork) + checkForDanglingPageURLs(false); LOG(IconDatabase, "Updating the database took %.4f seconds", currentTime() - timeStamp); @@ -1638,19 +1671,21 @@ void IconDatabase::pruneUnretainedIcons() void IconDatabase::checkForDanglingPageURLs(bool pruneIfFound) { ASSERT_ICON_SYNC_THREAD(); - - // We don't want to keep performing this check and reporting this error if it has already found danglers so we keep track + + // This check can be relatively expensive so we don't do it in a release build unless the caller has asked us to prune any dangling + // entries. We also don't want to keep performing this check and reporting this error if it has already found danglers before so we + // keep track of whether we've found any. We skip the check in the release build pretending to have already found danglers already. +#ifndef NDEBUG + static bool danglersFound = true; +#else static bool danglersFound = false; - - // However, if the caller wants us to prune the danglers, we will reset this flag and prune every time - if (pruneIfFound) - danglersFound = false; - - if (!danglersFound && SQLiteStatement(m_syncDB, "SELECT url FROM PageURL WHERE PageURL.iconID NOT IN (SELECT iconID FROM IconInfo) LIMIT 1;").returnsAtLeastOneResult()) { +#endif + + if ((pruneIfFound || !danglersFound) && SQLiteStatement(m_syncDB, "SELECT url FROM PageURL WHERE PageURL.iconID NOT IN (SELECT iconID FROM IconInfo) LIMIT 1;").returnsAtLeastOneResult()) { danglersFound = true; - LOG_ERROR("Dangling PageURL entries found"); + LOG(IconDatabase, "Dangling PageURL entries found"); if (pruneIfFound && !m_syncDB.executeCommand("DELETE FROM PageURL WHERE iconID NOT IN (SELECT iconID FROM IconInfo);")) - LOG_ERROR("Unable to prune dangling PageURLs"); + LOG(IconDatabase, "Unable to prune dangling PageURLs"); } } @@ -1905,8 +1940,7 @@ PassRefPtr<SharedBuffer> IconDatabase::getImageDataForIconURLFromSQLDatabase(con if (result == SQLResultRow) { Vector<char> data; m_getImageDataForIconURLStatement->getColumnBlobAsVector(0, data); - imageData = new SharedBuffer; - imageData->append(data.data(), data.size()); + imageData = SharedBuffer::create(data.data(), data.size()); } else if (result != SQLResultDone) LOG_ERROR("getImageDataForIconURLFromSQLDatabase failed for url %s", urlForLogging(iconURL).ascii().data()); |