⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 databasetracker.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
unsigned long long DatabaseTracker::usageForDatabase(const String& name, SecurityOrigin* origin){    ASSERT(currentThread() == m_thread);    String path = fullPathForDatabase(origin, name, false);    if (path.isEmpty())        return 0;            long long size;    return getFileSize(path, size) ? size : 0;}void DatabaseTracker::addOpenDatabase(Database* database){    if (!database)        return;    MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);    if (!m_openDatabaseMap)        m_openDatabaseMap.set(new DatabaseOriginMap);    RefPtr<SecurityOrigin> origin(database->securityOriginCopy());    String name(database->stringIdentifier());    DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);    if (!nameMap) {        nameMap = new DatabaseNameMap;        m_openDatabaseMap->set(origin, nameMap);    }    DatabaseSet* databaseSet = nameMap->get(name);    if (!databaseSet) {        databaseSet = new DatabaseSet;        nameMap->set(name, databaseSet);    }    databaseSet->add(database);    LOG(StorageAPI, "Added open Database %s (%p)\n", database->stringIdentifier().ascii().data(), database);}void DatabaseTracker::removeOpenDatabase(Database* database){    if (!database)        return;    MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);    if (!m_openDatabaseMap) {        ASSERT_NOT_REACHED();        return;    }    RefPtr<SecurityOrigin> origin(database->securityOriginCopy());    String name(database->stringIdentifier());    DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);    if (!nameMap) {        ASSERT_NOT_REACHED();        return;    }    DatabaseSet* databaseSet = nameMap->get(name);    if (!databaseSet) {        ASSERT_NOT_REACHED();        return;    }    databaseSet->remove(database);    LOG(StorageAPI, "Removed open Database %s (%p)\n", database->stringIdentifier().ascii().data(), database);    if (!databaseSet->isEmpty())        return;    nameMap->remove(name);    delete databaseSet;    if (!nameMap->isEmpty())        return;    m_openDatabaseMap->remove(origin);    delete nameMap;}unsigned long long DatabaseTracker::usageForOrigin(SecurityOrigin* origin){    ASSERT(currentThread() == m_thread);    Locker<OriginQuotaManager> locker(originQuotaManager());    // Use the OriginQuotaManager mechanism to calculate the usage    if (originQuotaManager().tracksOrigin(origin))        return originQuotaManager().diskUsage(origin);        // If the OriginQuotaManager doesn't track this origin already, prime it to do so    originQuotaManager().trackOrigin(origin);        Vector<String> names;    databaseNamesForOrigin(origin, names);    for (unsigned i = 0; i < names.size(); ++i)        originQuotaManager().addDatabase(origin, names[i], fullPathForDatabase(origin, names[i], false));        if (!originQuotaManager().tracksOrigin(origin))        return 0;    return originQuotaManager().diskUsage(origin);}unsigned long long DatabaseTracker::quotaForOrigin(SecurityOrigin* origin){    ASSERT(currentThread() == m_thread || m_quotaMap);    populateOrigins();    MutexLocker lockQuotaMap(m_quotaMapGuard);    return m_quotaMap->get(origin);}void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota){    ASSERT(currentThread() == m_thread);    if (quotaForOrigin(origin) == quota)        return;    openTrackerDatabase(true);    if (!m_database.isOpen())        return;    {        MutexLocker lockQuotaMap(m_quotaMapGuard);        if (!m_quotaMap->contains(origin)) {            SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");            if (statement.prepare() != SQLResultOk) {                LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());            } else {                statement.bindText(1, origin->databaseIdentifier());                statement.bindInt64(2, quota);                if (statement.step() != SQLResultDone)                    LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data());            }        } else {            SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?");                    bool error = statement.prepare() != SQLResultOk;            if (!error) {                statement.bindInt64(1, quota);                statement.bindText(2, origin->databaseIdentifier());                error = !statement.executeCommand();            }            if (error)                LOG_ERROR("Failed to set quota %llu in tracker database for origin %s", quota, origin->databaseIdentifier().ascii().data());        }        // FIXME: Is it really OK to update the quota in memory if we failed to update it on disk?        m_quotaMap->set(origin, quota);    }    if (m_client)        m_client->dispatchDidModifyOrigin(origin);}bool DatabaseTracker::addDatabase(SecurityOrigin* origin, const String& name, const String& path){    ASSERT(currentThread() == m_thread);    openTrackerDatabase(true);    if (!m_database.isOpen())        return false;            // New database should never be added until the origin has been established    ASSERT(hasEntryForOrigin(origin));    SQLiteStatement statement(m_database, "INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);");    if (statement.prepare() != SQLResultOk)        return false;    statement.bindText(1, origin->databaseIdentifier());    statement.bindText(2, name);    statement.bindText(3, path);    if (!statement.executeCommand()) {        LOG_ERROR("Failed to add database %s to origin %s: %s\n", name.ascii().data(), origin->databaseIdentifier().ascii().data(), m_database.lastErrorMsg());        return false;    }        if (m_client)        m_client->dispatchDidModifyOrigin(origin);        return true;}void DatabaseTracker::deleteAllDatabases(){    ASSERT(currentThread() == m_thread);    Vector<RefPtr<SecurityOrigin> > originsCopy;    origins(originsCopy);    for (unsigned i = 0; i < originsCopy.size(); ++i)        deleteOrigin(originsCopy[i].get());}void DatabaseTracker::deleteOrigin(SecurityOrigin* origin){    ASSERT(currentThread() == m_thread);    openTrackerDatabase(false);    if (!m_database.isOpen())        return;    Vector<String> databaseNames;    if (!databaseNamesForOrigin(origin, databaseNames)) {        LOG_ERROR("Unable to retrieve list of database names for origin %s", origin->databaseIdentifier().ascii().data());        return;    }        for (unsigned i = 0; i < databaseNames.size(); ++i) {        if (!deleteDatabaseFile(origin, databaseNames[i])) {            LOG_ERROR("Unable to delete file for database %s in origin %s", databaseNames[i].ascii().data(), origin->databaseIdentifier().ascii().data());            return;        }    }        SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=?");    if (statement.prepare() != SQLResultOk) {        LOG_ERROR("Unable to prepare deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data());        return;    }            statement.bindText(1, origin->databaseIdentifier());        if (!statement.executeCommand()) {        LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data());        return;    }        SQLiteStatement originStatement(m_database, "DELETE FROM Origins WHERE origin=?");    if (originStatement.prepare() != SQLResultOk) {        LOG_ERROR("Unable to prepare deletion of origin %s from tracker", origin->databaseIdentifier().ascii().data());        return;    }    originStatement.bindText(1, origin->databaseIdentifier());        if (!originStatement.executeCommand()) {        LOG_ERROR("Unable to execute deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data());        return;    }    deleteEmptyDirectory(originPath(origin));    RefPtr<SecurityOrigin> originPossiblyLastReference = origin;    {        MutexLocker lockQuotaMap(m_quotaMapGuard);        m_quotaMap->remove(origin);        Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager());        originQuotaManager().removeOrigin(origin);        // If we removed the last origin, do some additional deletion.        if (m_quotaMap->isEmpty()) {            if (m_database.isOpen())                m_database.close();            deleteFile(trackerDatabasePath());            deleteEmptyDirectory(m_databaseDirectoryPath);        }    }    if (m_client) {        m_client->dispatchDidModifyOrigin(origin);        for (unsigned i = 0; i < databaseNames.size(); ++i)            m_client->dispatchDidModifyDatabase(origin, databaseNames[i]);    }}void DatabaseTracker::deleteDatabase(SecurityOrigin* origin, const String& name){    ASSERT(currentThread() == m_thread);    openTrackerDatabase(false);    if (!m_database.isOpen())        return;    if (!deleteDatabaseFile(origin, name)) {        LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data());        return;    }        SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=? AND name=?");    if (statement.prepare() != SQLResultOk) {        LOG_ERROR("Unable to prepare deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data());        return;    }            statement.bindText(1, origin->databaseIdentifier());    statement.bindText(2, name);        if (!statement.executeCommand()) {        LOG_ERROR("Unable to execute deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data());        return;    }        {        Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager());        originQuotaManager().removeDatabase(origin, name);    }        if (m_client) {        m_client->dispatchDidModifyOrigin(origin);        m_client->dispatchDidModifyDatabase(origin, name);    }}bool DatabaseTracker::deleteDatabaseFile(SecurityOrigin* origin, const String& name){    ASSERT(currentThread() == m_thread);    String fullPath = fullPathForDatabase(origin, name, false);    if (fullPath.isEmpty())        return true;    Vector<RefPtr<Database> > deletedDatabases;    // Make sure not to hold the m_openDatabaseMapGuard mutex when calling    // Database::markAsDeletedAndClose(), since that can cause a deadlock    // during the synchronous DatabaseThread call it triggers.    {        MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);        if (m_openDatabaseMap) {            // There are some open databases, lets check if they are for this origin.            DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin);            if (nameMap && nameMap->size()) {                // There are some open databases for this origin, lets check                // if they are this database by name.                DatabaseSet* databaseSet = nameMap->get(name);                if (databaseSet && databaseSet->size()) {                    // We have some database open with this name. Mark them as deleted.                    DatabaseSet::const_iterator end = databaseSet->end();                    for (DatabaseSet::const_iterator it = databaseSet->begin(); it != end; ++it)                        deletedDatabases.append(*it);                }            }        }    }    for (unsigned i = 0; i < deletedDatabases.size(); ++i)        deletedDatabases[i]->markAsDeletedAndClose();    return deleteFile(fullPath);}void DatabaseTracker::setClient(DatabaseTrackerClient* client){    ASSERT(currentThread() == m_thread);    m_client = client;}static Mutex& notificationMutex(){    DEFINE_STATIC_LOCAL(Mutex, mutex, ());    return mutex;}typedef Vector<pair<SecurityOrigin*, String> > NotificationQueue;static NotificationQueue& notificationQueue(){    DEFINE_STATIC_LOCAL(NotificationQueue, queue, ());    return queue;}void DatabaseTracker::scheduleNotifyDatabaseChanged(SecurityOrigin* origin, const String& name){    MutexLocker locker(notificationMutex());    notificationQueue().append(pair<SecurityOrigin*, String>(origin, name.copy()));    scheduleForNotification();}static bool notificationScheduled = false;void DatabaseTracker::scheduleForNotification(){    ASSERT(!notificationMutex().tryLock());    if (!notificationScheduled) {        callOnMainThread(DatabaseTracker::notifyDatabasesChanged, 0);        notificationScheduled = true;    }}void DatabaseTracker::notifyDatabasesChanged(void*){    // Note that if DatabaseTracker ever becomes non-singleton, we'll have to amend this notification    // mechanism to include which tracker the notification goes out on as well.    DatabaseTracker& theTracker(tracker());    NotificationQueue notifications;    {        MutexLocker locker(notificationMutex());        notifications.swap(notificationQueue());        notificationScheduled = false;    }    if (!theTracker.m_client)        return;    for (unsigned i = 0; i < notifications.size(); ++i)        theTracker.m_client->dispatchDidModifyDatabase(notifications[i].first, notifications[i].second);}} // namespace WebCore

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -