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

📄 database.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1.  Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer. * 2.  Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution. * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of *     its contributors may be used to endorse or promote products derived *     from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "Database.h"#include "ChangeVersionWrapper.h"#include "CString.h"#include "DatabaseAuthorizer.h"#include "DatabaseTask.h"#include "DatabaseThread.h"#include "DatabaseTracker.h"#include "Document.h"#include "ExceptionCode.h"#include "FileSystem.h"#include "Frame.h"#include "InspectorController.h"#include "Logging.h"#include "NotImplemented.h"#include "Page.h"#include "OriginQuotaManager.h"#include "SQLiteDatabase.h"#include "SQLiteStatement.h"#include "SQLResultSet.h"#include <wtf/MainThread.h>#include <wtf/StdLibExtras.h>#if USE(JSC)#include "JSDOMWindow.h"#include <runtime/InitializeThreading.h>#endifnamespace WebCore {static Mutex& guidMutex(){    // Note: We don't have to use AtomicallyInitializedStatic here because    // this function is called once in the constructor on the main thread    // before any other threads that call this function are used.    DEFINE_STATIC_LOCAL(Mutex, mutex, ());    return mutex;}typedef HashMap<int, String> GuidVersionMap;static GuidVersionMap& guidToVersionMap(){    DEFINE_STATIC_LOCAL(GuidVersionMap, map, ());    return map;}typedef HashMap<int, HashSet<Database*>*> GuidDatabaseMap;static GuidDatabaseMap& guidToDatabaseMap(){    DEFINE_STATIC_LOCAL(GuidDatabaseMap, map, ());    return map;}const String& Database::databaseInfoTableName(){    DEFINE_STATIC_LOCAL(String, name, ("__WebKitDatabaseInfoTable__"));    return name;}static const String& databaseVersionKey(){    DEFINE_STATIC_LOCAL(String, key, ("WebKitDatabaseVersionKey"));    return key;}static int guidForOriginAndName(const String& origin, const String& name);PassRefPtr<Database> Database::openDatabase(Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e){    if (!DatabaseTracker::tracker().canEstablishDatabase(document, name, displayName, estimatedSize)) {        // FIXME: There should be an exception raised here in addition to returning a null Database object.  The question has been raised with the WHATWG.        LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), document->securityOrigin()->toString().ascii().data());        return 0;    }        RefPtr<Database> database = adoptRef(new Database(document, name, expectedVersion));    if (!database->openAndVerifyVersion(e)) {       LOG(StorageAPI, "Failed to open and verify version (expected %s) of database %s", expectedVersion.ascii().data(), database->databaseDebugName().ascii().data());       return 0;    }        DatabaseTracker::tracker().setDatabaseDetails(document->securityOrigin(), name, displayName, estimatedSize);    document->setHasOpenDatabases();    if (Page* page = document->frame()->page())        page->inspectorController()->didOpenDatabase(database.get(), document->securityOrigin()->host(), name, expectedVersion);    return database;}Database::Database(Document* document, const String& name, const String& expectedVersion)    : m_transactionInProgress(false)    , m_document(document)    , m_name(name.copy())    , m_guid(0)    , m_expectedVersion(expectedVersion)    , m_deleted(false)    , m_stopped(false){    ASSERT(document);    m_securityOrigin = document->securityOrigin();    if (m_name.isNull())        m_name = "";#if USE(JSC)    JSC::initializeThreading();    // Database code violates the normal JSCore contract by calling jsUnprotect from a secondary thread, and thus needs additional locking.    JSDOMWindow::commonJSGlobalData()->heap.setGCProtectNeedsLocking();#endif    m_guid = guidForOriginAndName(m_securityOrigin->toString(), name);    {        MutexLocker locker(guidMutex());        HashSet<Database*>* hashSet = guidToDatabaseMap().get(m_guid);        if (!hashSet) {            hashSet = new HashSet<Database*>;            guidToDatabaseMap().set(m_guid, hashSet);        }        hashSet->add(this);    }    ASSERT(m_document->databaseThread());    m_filename = DatabaseTracker::tracker().fullPathForDatabase(m_securityOrigin.get(), m_name);    DatabaseTracker::tracker().addOpenDatabase(this);    m_document->addOpenDatabase(this);}Database::~Database(){    {        MutexLocker locker(guidMutex());        HashSet<Database*>* hashSet = guidToDatabaseMap().get(m_guid);        ASSERT(hashSet);        ASSERT(hashSet->contains(this));        hashSet->remove(this);        if (hashSet->isEmpty()) {            guidToDatabaseMap().remove(m_guid);            delete hashSet;            guidToVersionMap().remove(m_guid);        }    }    if (m_document->databaseThread())        m_document->databaseThread()->unscheduleDatabaseTasks(this);    DatabaseTracker::tracker().removeOpenDatabase(this);    m_document->removeOpenDatabase(this);}bool Database::openAndVerifyVersion(ExceptionCode& e){    if (!m_document->databaseThread())        return false;    m_databaseAuthorizer = DatabaseAuthorizer::create();    RefPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this);    task->lockForSynchronousScheduling();    m_document->databaseThread()->scheduleImmediateTask(task);    task->waitForSynchronousCompletion();    ASSERT(task->isComplete());    e = task->exceptionCode();    return task->openSuccessful();}static bool retrieveTextResultFromDatabase(SQLiteDatabase& db, const String& query, String& resultString){    SQLiteStatement statement(db, query);    int result = statement.prepare();    if (result != SQLResultOk) {        LOG_ERROR("Error (%i) preparing statement to read text result from database (%s)", result, query.ascii().data());        return false;    }    result = statement.step();    if (result == SQLResultRow) {        resultString = statement.getColumnText(0);        return true;    } else if (result == SQLResultDone) {        resultString = String();        return true;    } else {        LOG_ERROR("Error (%i) reading text result from database (%s)", result, query.ascii().data());        return false;    }}bool Database::getVersionFromDatabase(String& version){    DEFINE_STATIC_LOCAL(String, getVersionQuery, ("SELECT value FROM " + databaseInfoTableName() + " WHERE key = '" + databaseVersionKey() + "';"));    m_databaseAuthorizer->disable();    bool result = retrieveTextResultFromDatabase(m_sqliteDatabase, getVersionQuery.copy(), version);    if (!result)        LOG_ERROR("Failed to retrieve version from database %s", databaseDebugName().ascii().data());    m_databaseAuthorizer->enable();    return result;}static bool setTextValueInDatabase(SQLiteDatabase& db, const String& query, const String& value){    SQLiteStatement statement(db, query);    int result = statement.prepare();    if (result != SQLResultOk) {        LOG_ERROR("Failed to prepare statement to set value in database (%s)", query.ascii().data());        return false;    }    statement.bindText(1, value);    result = statement.step();    if (result != SQLResultDone) {        LOG_ERROR("Failed to step statement to set value in database (%s)", query.ascii().data());        return false;    }    return true;}bool Database::setVersionInDatabase(const String& version){    DEFINE_STATIC_LOCAL(String, setVersionQuery, ("INSERT INTO " + databaseInfoTableName() + " (key, value) VALUES ('" + databaseVersionKey() + "', ?);"));    m_databaseAuthorizer->disable();    bool result = setTextValueInDatabase(m_sqliteDatabase, setVersionQuery.copy(), version);    if (!result)        LOG_ERROR("Failed to set version %s in database (%s)", version.ascii().data(), setVersionQuery.ascii().data());    m_databaseAuthorizer->enable();    return result;}bool Database::versionMatchesExpected() const{    if (!m_expectedVersion.isEmpty()) {        MutexLocker locker(guidMutex());        return m_expectedVersion == guidToVersionMap().get(m_guid);    }        return true;}void Database::markAsDeletedAndClose(){    if (m_deleted || !m_document->databaseThread())        return;    LOG(StorageAPI, "Marking %s (%p) as deleted", stringIdentifier().ascii().data(), this);    m_deleted = true;    if (m_document->databaseThread()->terminationRequested()) {        LOG(StorageAPI, "Database handle %p is on a terminated DatabaseThread, cannot be marked for normal closure\n", this);        return;    }

⌨️ 快捷键说明

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