summaryrefslogtreecommitdiffstats
path: root/WebCore/loader/icon/IconDatabase.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/loader/icon/IconDatabase.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_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.cpp120
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());