📄 icondatabase.cpp
字号:
MutexLocker locker(m_pendingReadingLock); m_iconsPendingReading.remove(iconRecord.get()); } // And mark this mapping to be added to the database if (!m_privateBrowsingEnabled) { MutexLocker locker(m_pendingSyncLock); m_pageURLsPendingSync.set(pageURL, pageRecord->snapshot()); // If the icon is on its last ref, mark it for deletion if (iconRecord && iconRecord->hasOneRef()) m_iconsPendingSync.set(iconRecord->iconURL(), iconRecord->snapshot(true)); } } // Since this mapping is new, send the notification out - but not if we're on the sync thread because that implies this mapping // comes from the initial import which we don't want notifications for if (!IS_ICON_SYNC_THREAD()) { // Start the timer to commit this change - or further delay the timer if it was already started scheduleOrDeferSyncTimer(); LOG(IconDatabase, "Dispatching notification that we changed an icon mapping for url %s", urlForLogging(pageURL).ascii().data()); AutodrainedPool pool; m_client->dispatchDidAddIconForPageURL(pageURL); }}IconLoadDecision IconDatabase::loadDecisionForIconURL(const String& iconURL, DocumentLoader* notificationDocumentLoader){ ASSERT_NOT_SYNC_THREAD(); if (!isOpen() || iconURL.isEmpty()) return IconLoadNo; // If we have a IconRecord, it should also have its timeStamp marked because there is only two times when we create the IconRecord: // 1 - When we read the icon urls from disk, getting the timeStamp at the same time // 2 - When we get a new icon from the loader, in which case the timestamp is set at that time { MutexLocker locker(m_urlAndIconLock); if (IconRecord* icon = m_iconURLToRecordMap.get(iconURL)) { LOG(IconDatabase, "Found expiration time on a present icon based on existing IconRecord"); return (int)currentTime() - icon->getTimestamp() > iconExpirationTime ? IconLoadYes : IconLoadNo; } } // If we don't have a record for it, but we *have* imported all iconURLs from disk, then we should load it now MutexLocker readingLocker(m_pendingReadingLock); if (m_iconURLImportComplete) return IconLoadYes; // 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); return IconLoadUnknown;}bool IconDatabase::iconDataKnownForIconURL(const String& iconURL){ ASSERT_NOT_SYNC_THREAD(); MutexLocker locker(m_urlAndIconLock); if (IconRecord* icon = m_iconURLToRecordMap.get(iconURL)) return icon->imageDataStatus() != ImageDataStatusUnknown; return false;}void IconDatabase::setEnabled(bool enabled){ ASSERT_NOT_SYNC_THREAD(); if (!enabled && isOpen()) close(); m_isEnabled = enabled;}bool IconDatabase::isEnabled() const{ ASSERT_NOT_SYNC_THREAD(); return m_isEnabled;}void IconDatabase::setPrivateBrowsingEnabled(bool flag){ m_privateBrowsingEnabled = flag;}bool IconDatabase::isPrivateBrowsingEnabled() const{ return m_privateBrowsingEnabled;}void IconDatabase::delayDatabaseCleanup(){ ++databaseCleanupCounter; if (databaseCleanupCounter == 1) LOG(IconDatabase, "Database cleanup is now DISABLED");}void IconDatabase::allowDatabaseCleanup(){ if (--databaseCleanupCounter < 0) databaseCleanupCounter = 0; if (databaseCleanupCounter == 0) LOG(IconDatabase, "Database cleanup is now ENABLED");}void IconDatabase::checkIntegrityBeforeOpening(){ checkIntegrityOnOpen = true;}size_t IconDatabase::pageURLMappingCount(){ MutexLocker locker(m_urlAndIconLock); return m_pageURLToRecordMap.size();}size_t IconDatabase::retainedPageURLCount(){ MutexLocker locker(m_urlAndIconLock); return m_retainedPageURLs.size();}size_t IconDatabase::iconRecordCount(){ MutexLocker locker(m_urlAndIconLock); return m_iconURLToRecordMap.size();}size_t IconDatabase::iconRecordCountWithData(){ MutexLocker locker(m_urlAndIconLock); size_t result = 0; HashMap<String, IconRecord*>::iterator i = m_iconURLToRecordMap.begin(); HashMap<String, IconRecord*>::iterator end = m_iconURLToRecordMap.end(); for (; i != end; ++i) result += ((*i).second->imageDataStatus() == ImageDataStatusPresent); return result;}IconDatabase::IconDatabase() : m_syncThreadRunning(false) , m_defaultIconRecord(0) , m_isEnabled(false) , m_privateBrowsingEnabled(false) , m_threadTerminationRequested(false) , m_removeIconsRequested(false) , m_iconURLImportComplete(false) , m_initialPruningComplete(false) , m_client(defaultClient()) , m_imported(false) , m_isImportedSet(false){#if PLATFORM(DARWIN) ASSERT(pthread_main_np());#endif}IconDatabase::~IconDatabase(){ ASSERT_NOT_REACHED();}void IconDatabase::notifyPendingLoadDecisionsOnMainThread(void* context){ static_cast<IconDatabase*>(context)->notifyPendingLoadDecisions();}void IconDatabase::notifyPendingLoadDecisions(){ ASSERT_NOT_SYNC_THREAD(); // This method should only be called upon completion of the initial url import from the database ASSERT(m_iconURLImportComplete); LOG(IconDatabase, "Notifying all DocumentLoaders that were waiting on a load decision for thier icons"); HashSet<RefPtr<DocumentLoader> >::iterator i = m_loadersPendingDecision.begin(); HashSet<RefPtr<DocumentLoader> >::iterator end = m_loadersPendingDecision.end(); for (; i != end; ++i) if ((*i)->refCount() > 1) (*i)->iconLoadDecisionAvailable(); m_loadersPendingDecision.clear();}void IconDatabase::wakeSyncThread(){ MutexLocker locker(m_syncLock); m_syncCondition.signal();}void IconDatabase::scheduleOrDeferSyncTimer(){ ASSERT_NOT_SYNC_THREAD(); if (!m_syncTimer) m_syncTimer.set(new Timer<IconDatabase>(this, &IconDatabase::syncTimerFired)); m_syncTimer->startOneShot(updateTimerDelay);}void IconDatabase::syncTimerFired(Timer<IconDatabase>*){ ASSERT_NOT_SYNC_THREAD(); wakeSyncThread();}// ******************// *** Any Thread ***// ******************bool IconDatabase::isOpen() const{ MutexLocker locker(m_syncLock); return m_syncDB.isOpen();}String IconDatabase::databasePath() const{ MutexLocker locker(m_syncLock); return m_completeDatabasePath.copy();}String IconDatabase::defaultDatabaseFilename(){ DEFINE_STATIC_LOCAL(String, defaultDatabaseFilename, ("WebpageIcons.db")); return defaultDatabaseFilename.copy();}// Unlike getOrCreatePageURLRecord(), getOrCreateIconRecord() does not mark the icon as "interested in import"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; 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 notificationPageURLRecord* IconDatabase::getOrCreatePageURLRecord(const String& pageURL){ // Clients of getOrCreatePageURLRecord() are required to acquire the m_urlAndIconLock before calling this method ASSERT(!m_urlAndIconLock.tryLock()); if (pageURL.isEmpty()) return 0; PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURL); MutexLocker locker(m_pendingReadingLock); if (!m_iconURLImportComplete) { // If the initial import of all URLs hasn't completed and we have no page record, we assume we *might* know about this later and create a record for it if (!pageRecord) { LOG(IconDatabase, "Creating new PageURLRecord for pageURL %s", urlForLogging(pageURL).ascii().data()); pageRecord = new PageURLRecord(pageURL); m_pageURLToRecordMap.set(pageURL, pageRecord); } // If the pageRecord for this page does not have an iconRecord attached to it, then it is a new pageRecord still awaiting the initial import // Mark the URL as "interested in the result of the import" then bail if (!pageRecord->iconRecord()) { m_pageURLsPendingImport.add(pageURL); return 0; } } // We've done the initial import of all URLs known in the database. If this record doesn't exist now, it never will return pageRecord;}// ************************// *** Sync Thread Only ***// ************************void IconDatabase::importIconURLForPageURL(const String& iconURL, const String& pageURL){ ASSERT_ICON_SYNC_THREAD(); // This function is only for setting actual existing url mappings so assert that neither of these URLs are empty ASSERT(!iconURL.isEmpty() && !pageURL.isEmpty()); setIconURLForPageURLInSQLDatabase(iconURL, pageURL); }void IconDatabase::importIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL){ ASSERT_ICON_SYNC_THREAD(); ASSERT(!iconURL.isEmpty()); writeIconSnapshotToSQLDatabase(IconSnapshot(iconURL, (int)currentTime(), data.get()));}bool IconDatabase::shouldStopThreadActivity() const{ ASSERT_ICON_SYNC_THREAD();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -