JavaScriptCore:
authorbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2007 22:50:08 +0000 (22:50 +0000)
committerbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2007 22:50:08 +0000 (22:50 +0000)
2007-10-19  Brady Eidson  <beidson@apple.com>

        Reviewed by Sam

        Queue -> Deque! and small style tweaks

        * JavaScriptCore.vcproj/WTF/WTF.vcproj:
        * JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
        * wtf/Deque.h: Added.
        (WTF::DequeNode::DequeNode):
        (WTF::Deque::Deque):
        (WTF::Deque::~Deque):
        (WTF::Deque::size):
        (WTF::Deque::isEmpty):
        (WTF::Deque::append):
        (WTF::Deque::prepend):
        (WTF::Deque::first):
        (WTF::Deque::last):
        (WTF::Deque::removeFirst):
        (WTF::Deque::clear):
        * wtf/Queue.h: Removed.

2007-10-19  Brady Eidson <beidson@apple.com>

        Reviewed by Oliver

        Added a simple LinkedList based Queue to wtf
        We can make a better, more sophisticated an efficient one later, but have
        needed one for some time, now!

        * JavaScriptCore.xcodeproj/project.pbxproj:
        * wtf/Queue.h: Added.
        (WTF::QueueNode::QueueNode):
        (WTF::Queue::Queue):
        (WTF::Queue::~Queue):
        (WTF::Queue::size):
        (WTF::Queue::isEmpty):
        (WTF::Queue::append):
        (WTF::Queue::prepend):
        (WTF::Queue::first):
        (WTF::Queue::last):
        (WTF::Queue::removeFirst):
        (WTF::Queue::clear):

WebCore:
2007-10-19  Brady Eidson  <beidson@apple.com>
        Reviewed by Anders

        Windows specific changes, as well as renaming Queue -> Deque

        * ForwardingHeaders/wtf/Deque.h: Added.
        * ForwardingHeaders/wtf/Queue.h: Removed.
        * platform/win/FileSystemWin.cpp:
        (WebCore::fileSize):
        (WebCore::fileExists):
        (WebCore::deleteFile):
        (WebCore::pathByAppendingComponent):
        (WebCore::fileSystemRepresentation):
        (WebCore::makeAllDirectories):
        (WebCore::homeDirectoryPath):
        * storage/Database.h:
        * storage/DatabaseThread.cpp:
        (WebCore::DatabaseThread::documentGoingAway):
        (WebCore::DatabaseThread::databaseGoingAway):
        (WebCore::DatabaseThread::dispatchNextTaskIdentifier):
        (WebCore::DatabaseThread::scheduleTask):
        (WebCore::DatabaseThread::scheduleImmediateTask):
        * storage/DatabaseThread.h:

2007-10-19  Brady Eidson <beidson@apple.com>

        Reviewed by Tim and Anders

        Preliminary support for HTML5 local database storage (http://www.whatwg.org/specs/web-apps/current-work/)

        The specification is still in flux but the fundamentals are pretty solid and we can start using and testing
        this implementation even while filing bugs to track changes in the spec as it becomes more final

        There are some implementation details in this patch that seem unused or useless, but they remain in place
        while the spec is in flux and might go one way or another.

        * platform/Logging.cpp: Add StorageAPI logging channel
        * platform/Logging.h:

        * storage/Database.cpp: Added.
        (WebCore::Database::databaseInfoTableName):
        (WebCore::databaseVersionKey):
        (WebCore::Database::openDatabase): C++ version of the window.openDatabase() javascript API
        (WebCore::Database::Database):
        (WebCore::Database::~Database):
        (WebCore::Database::openAndVerifyVersion):
        (WebCore::retrieveTextResultFromDatabase):
        (WebCore::Database::getVersionFromDatabase):
        (WebCore::setTextValueInDatabase):
        (WebCore::Database::setVersionInDatabase):
        (WebCore::Database::databaseThreadGoingAway): May be removed in the future
        (WebCore::Database::disableAuthorizer): For internal (WebInspector) use to get around the authorizer's restrictions
        (WebCore::Database::enableAuthorizer):
        (WebCore::Database::guidForOriginAndName): Candidate for refactoring and/or moving to the database tracker.
          The GUID for each database identifier is currently for tracking the database version, but might be rescoped in the future
        (WebCore::Database::resetAuthorizer):
        (WebCore::Database::performPolicyChecks): Currently, the only post-executeSql policy check planned is the origin size usage
        (WebCore::Database::scheduleDatabaseCallback):
        (WebCore::Database::performOpenAndVerify):
        (WebCore::Database::performChangeVersion):
        (WebCore::Database::performExecuteSql):
        (WebCore::Database::performCloseTransaction):
        (WebCore::Database::performGetTableNames):
        (WebCore::Database::version): C++ version of the javascript API
        (WebCore::Database::changeVersion): Ditto
        (WebCore::Database::executeSql): Ditto
        (WebCore::Database::closeTransaction): Ditto
        (WebCore::Database::tableNames): For internal (WebInspector) use
        (WebCore::Database::deliverAllPendingCallbacks):
        (WebCore::Database::deliverPendingCallbacks):
        * storage/Database.h: Added.
        (WebCore::Database::databaseDebugName): For debug logging purposes
        * storage/Database.idl: Added.

        * storage/DatabaseAuthorizer.cpp: Added.
          The DatabaseAuthorizer is used to both prevent the script from doing "illegal" things in sql as well as
          tracking when effects certain sql statements might have (such as increasing the size of the database)
        (WebCore::DatabaseAuthorizer::DatabaseAuthorizer):
        (WebCore::DatabaseAuthorizer::reset):
        (WebCore::DatabaseAuthorizer::createTable):
        (WebCore::DatabaseAuthorizer::createTempTable):
        (WebCore::DatabaseAuthorizer::dropTable):
        (WebCore::DatabaseAuthorizer::dropTempTable):
        (WebCore::DatabaseAuthorizer::allowAlterTable):
        (WebCore::DatabaseAuthorizer::createIndex):
        (WebCore::DatabaseAuthorizer::createTempIndex):
        (WebCore::DatabaseAuthorizer::dropIndex):
        (WebCore::DatabaseAuthorizer::dropTempIndex):
        (WebCore::DatabaseAuthorizer::createTrigger):
        (WebCore::DatabaseAuthorizer::createTempTrigger):
        (WebCore::DatabaseAuthorizer::dropTrigger):
        (WebCore::DatabaseAuthorizer::dropTempTrigger):
        (WebCore::DatabaseAuthorizer::createVTable):
        (WebCore::DatabaseAuthorizer::dropVTable):
        (WebCore::DatabaseAuthorizer::allowDelete):
        (WebCore::DatabaseAuthorizer::allowInsert):
        (WebCore::DatabaseAuthorizer::allowUpdate):
        (WebCore::DatabaseAuthorizer::allowRead):
        (WebCore::DatabaseAuthorizer::allowAnalyze):
        (WebCore::DatabaseAuthorizer::allowPragma):
        (WebCore::DatabaseAuthorizer::allowAttach):
        (WebCore::DatabaseAuthorizer::allowDetach):
        (WebCore::DatabaseAuthorizer::allowFunction):
        (WebCore::DatabaseAuthorizer::disable):
        (WebCore::DatabaseAuthorizer::enable):
        (WebCore::DatabaseAuthorizer::denyBasedOnTableName): Don't allow access to the __WebKit meta info table as
          it should be invisible to scripts
        * storage/DatabaseAuthorizer.h: Added.
        (WebCore::DatabaseAuthorizer::lastActionWasInsert):
        (WebCore::DatabaseAuthorizer::lastActionIncreasedSize):

        * storage/DatabaseCallback.cpp: Added.
          Generic item to queue up for callbacks on the main thread for database activities that take place on
          a secondary thread
        (WebCore::DatabaseChangeVersionCallback::DatabaseChangeVersionCallback):
        (WebCore::DatabaseChangeVersionCallback::performCallback):
        (WebCore::DatabaseExecuteSqlCallback::DatabaseExecuteSqlCallback):
        (WebCore::DatabaseExecuteSqlCallback::performCallback):
        * storage/DatabaseCallback.h: Added.
        (WebCore::DatabaseCallback::~DatabaseCallback):
        (WebCore::DatabaseChangeVersionCallback::~DatabaseChangeVersionCallback):
        (WebCore::DatabaseExecuteSqlCallback::~DatabaseExecuteSqlCallback):

        * storage/DatabaseTask.h: Added.
          Generic work-item to be queued up on the background database thread
        (WebCore::DatabaseTask::isComplete):
        (WebCore::DatabaseOpenTask::exceptionCode):
        (WebCore::DatabaseOpenTask::openSuccessful):
        (WebCore::DatabaseTableNamesTask::tableNames):
        * storage/DatabaseTask.cpp: Added.
        (WebCore::DatabaseTask::DatabaseTask):
        (WebCore::DatabaseTask::~DatabaseTask):
        (WebCore::DatabaseTask::performTask):
        (WebCore::DatabaseTask::lockForSynchronousScheduling): Used when the main thread needs this task accomplished
          synchronously
        (WebCore::DatabaseTask::waitForSynchronousCompletion):

        (WebCore::DatabaseOpenTask::DatabaseOpenTask):
        (WebCore::DatabaseOpenTask::doPerformTask):

        (WebCore::DatabaseExecuteSqlTask::DatabaseExecuteSqlTask):
        (WebCore::DatabaseExecuteSqlTask::doPerformTask):

        (WebCore::DatabaseChangeVersionTask::DatabaseChangeVersionTask):
        (WebCore::DatabaseChangeVersionTask::doPerformTask):

        (WebCore::DatabaseTableNamesTask::DatabaseTableNamesTask):
        (WebCore::DatabaseTableNamesTask::doPerformTask):

        * storage/DatabaseThread.cpp: Added.
          The current design is that each Document will have its own DatabaseThread.  This makes scripts on each
          individual document more response at the cost of adding more threads and potentially creating concurrency
          issues when the same database is open twice from two different documents
        (WebCore::DatabaseThread::DatabaseThread):
        (WebCore::DatabaseThread::~DatabaseThread):
        (WebCore::DatabaseThread::start):
        (WebCore::DatabaseThread::documentGoingAway): Called to shut the thread down when the document is destroyed
        (WebCore::DatabaseThread::databaseGoingAway): Remove all pending tasks for this database
        (WebCore::DatabaseThread::databaseThreadStart):
        (WebCore::DatabaseThread::databaseThread):
        (WebCore::DatabaseThread::dispatchNextTaskIdentifier):
        (WebCore::DatabaseThread::scheduleTask):
        (WebCore::DatabaseThread::scheduleImmediateTask): Schedule a task that gets to "cut to the front of the line" when
          the main thread requires a task be performed synchronously
        (WebCore::DatabaseThread::wakeWorkThread):
        * storage/DatabaseThread.h: Added.

        * storage/DatabaseTracker.cpp: Added.
          The DatabaseTracker is the master management of all databases.  It will keep track of the filename for a given
          unique database, keep track of the total disk usage per-origin, and policys per database/origin
        (WebCore::DatabaseTracker::setDatabasePath):
        (WebCore::DatabaseTracker::databasePath):
        (WebCore::DatabaseTracker::tracker):
        (WebCore::DatabaseTracker::DatabaseTracker):
        (WebCore::DatabaseTracker::fullPathForDatabase):
        (WebCore::DatabaseTracker::populateOrigins):
        (WebCore::DatabaseTracker::origins):
        (WebCore::DatabaseTracker::databaseNamesForOrigin):
        (WebCore::DatabaseTracker::addDatabase):
        (WebCore::DatabaseTracker::deleteAllDatabases):
        (WebCore::DatabaseTracker::deleteAllDatabasesForOrigin):
        * storage/DatabaseTracker.h: Added.

        * storage/SQLCallback.h: Added. C++ version of the javascript executeSql() callback
        (WebCore::SQLCallback::~SQLCallback):
        * storage/SQLCallback.idl: Added.

        * storage/SQLResultSet.cpp: Added. C++ version of the javascript SQLResultSet object
        (WebCore::SQLResultSet::SQLResultSet):
        (WebCore::SQLResultSet::insertId):
        (WebCore::SQLResultSet::rowsAffected):
        (WebCore::SQLResultSet::errorCode):
        (WebCore::SQLResultSet::error):
        (WebCore::SQLResultSet::rows):
        (WebCore::SQLResultSet::setInsertId):
        (WebCore::SQLResultSet::setRowsAffected):
        (WebCore::SQLResultSet::setErrorCode):
        (WebCore::SQLResultSet::setErrorMessage):
        * storage/SQLResultSet.h: Added.
        * storage/SQLResultSet.idl: Added.

        * storage/SQLResultSetRowList.cpp: Added. C++ version of the javascript SQLResultSetRowList object
        (WebCore::SQLResultSetRowList::length):
        * storage/SQLResultSetRowList.h: Added.
        (WebCore::SQLResultSetRowList::columnNames):
        (WebCore::SQLResultSetRowList::values):
        (WebCore::SQLResultSetRowList::addColumn):
        (WebCore::SQLResultSetRowList::addResult):
        * storage/SQLResultSetRowList.idl: Added.

        * storage/VersionChangeCallback.h: Added. C++ version of the javascript changeVersion() callback
        (WebCore::VersionChangeCallback::~VersionChangeCallback):
        * storage/VersionChangeCallback.idl: Added.

2007-10-19  Brady Eidson <beidson@apple.com>

        Reviewed by Oliver + Same

        Forwarding header for the new wtf/Queue.h

        * ForwardingHeaders/wtf/Queue.h: Added.

2007-10-19  Anders Carlsson <beidson@apple.com>

        Reviewed by Sam Weinig

        Most of the Javascript binding support for the Storage API

        * bindings/js/JSCustomSQLCallback.cpp: Added.
        (WebCore::JSCustomSQLCallback::JSCustomSQLCallback):
        (WebCore::JSCustomSQLCallback::handleEvent):
        * bindings/js/JSCustomSQLCallback.h: Added.
Add JSCustomSQLCallback which is an SQLCallback implementation that dispatches
handleEvent to a JS function or a JS object with a handleEvent function.

        * bindings/js/JSCustomVersionChangeCallback.cpp: Added.
        (WebCore::JSCustomVersionChangeCallback::JSCustomVersionChangeCallback):
        (WebCore::JSCustomVersionChangeCallback::handleEvent):
        * bindings/js/JSCustomVersionChangeCallback.h: Added.
Add JSCustomSQLCallback which is an SQLCallback implementation that dispatches
handleEvent to a JS function or a JS object with a handleEvent function.

        * bindings/js/JSDatabaseCustom.cpp: Added.
        (WebCore::JSDatabase::executeSql):
Custom implementation of executeSql that takes an array of parameters.

        (WebCore::JSDatabase::changeVersion):
Custom implementation of changeVersion.

        * bindings/js/JSSQLResultSetRowListCustom.cpp: Added.
        (WebCore::JSSQLResultSetRowList::item):
Custom method that returns a JS object that corresponds to a given row in the database.

        * bindings/scripts/CodeGeneratorJS.pm:

        * page/DOMWindow.cpp:
        (WebCore::DOMWindow::openDatabase):
        * page/DOMWindow.h:
        * page/DOMWindow.idl:
Add openDatabase implementation.

2007-10-19  Brady Eidson <beidson@apple.com>

        Reviewed by Oliver

        Added tons of utility to the FileSystem abstractions, including moving
        some stuff over from IconDatabase

        * platform/FileSystem.h:

        * platform/cf/FileSystemCF.cpp: Added.
        (WebCore::fileSystemRepresentation):

        * platform/mac/FileSystemMac.mm:

        * platform/posix/FileSystemPOSIX.cpp: Added.
        (WebCore::fileExists):
        (WebCore::deleteFile):
        (WebCore::fileSize):
        (WebCore::pathByAppendingComponent):
        (WebCore::makeAllDirectories):

2007-10-19  Timothy Hatcher  <timothy@apple.com>

        Reviewed by Adam Roben

        Preliminary Web Inspector support for the Storage API
        (This patch does not include the support artwork)

        * page/InspectorController.cpp:
        (WebCore::InspectorDatabaseResource::InspectorDatabaseResource):
        (WebCore::InspectorDatabaseResource::setScriptObject):
        (WebCore::databaseTableNames): Return the table names for a Database object.
        (WebCore::InspectorController::setWindowVisible):
        (WebCore::InspectorController::windowScriptObjectAvailable):
        (WebCore::InspectorController::populateScriptResources):
        (WebCore::InspectorController::addDatabaseScriptResource): Add the script object for the database.
        (WebCore::InspectorController::removeDatabaseScriptResource): Remove the script object for the database.
        (WebCore::InspectorController::clearDatabaseScriptResources): Remove all the database resources.
        (WebCore::InspectorController::didCommitLoad): Call clearDatabaseScriptResources().
        (WebCore::InspectorController::didOpenDatabase): Make a new InspectorDatabaseResource and add it to m_databaseResources.
        * page/InspectorController.h:
        * page/inspector/Database.js: Added.
        * page/inspector/DatabasePanel.js: Added.
        * page/inspector/ResourceCategory.js: Make resource categories assume less about the resource.
        * page/inspector/inspector.css: Add styles for the database panel.
        * page/inspector/inspector.html: Include DatabasePanel.js
        * page/inspector/inspector.js: Support for adding and removing Database resources.

2007-10-19  Brady Eidson <beidson@apple.com>

        Reviewed by Tim Hatcher

        Added support for Chrome prompts required by the Storage API

        * page/Chrome.cpp:
        (WebCore::Chrome::runDatabaseSizeLimitPrompt):
        * page/Chrome.h:
        * page/ChromeClient.h:
        * platform/graphics/svg/SVGImageEmptyClients.h:

2007-10-19  Brady Eidson <beidson@apple.com>

        Contributions and Review by Anders

        Various SQLite tweaks in preparation for the storage API

        * loader/icon/SQLDatabase.cpp:
        (WebCore::SQLDatabase::~SQLDatabase):
        (WebCore::SQLDatabase::authorizerFunction): Static callback from sqlite for authorizer functions
        (WebCore::SQLDatabase::setAuthorizer):
        (WebCore::SQLDatabase::lock):
        (WebCore::SQLDatabase::unlock):
        * loader/icon/SQLDatabase.h:

        * loader/icon/SQLStatement.cpp:
        (WebCore::SQLStatement::prepare): Switch to prepare16_v2
        (WebCore::SQLStatement::bindDouble): Added
        (WebCore::SQLStatement::bindValue): Bind a wrapped SQLValue object (described later)
        (WebCore::SQLStatement::bindParameterCount): Accessor to the sqlite3 API for validating statements
        * loader/icon/SQLStatement.h:
        (WebCore::SQLStatement::isPrepared):

        * platform/sql/SQLAuthorizer.cpp: Added.  Fully virtual interface to implement your own SQLite authorizer
        * platform/sql/SQLAuthorizer.h: Added.
        (WebCore::SQLAuthorizer::~SQLAuthorizer):
        (WebCore::SQLAuthorizer::createTable):
        (WebCore::SQLAuthorizer::createTempTable):
        (WebCore::SQLAuthorizer::dropTable):
        (WebCore::SQLAuthorizer::dropTempTable):
        (WebCore::SQLAuthorizer::allowAlterTable):
        (WebCore::SQLAuthorizer::createIndex):
        (WebCore::SQLAuthorizer::createTempIndex):
        (WebCore::SQLAuthorizer::dropIndex):
        (WebCore::SQLAuthorizer::dropTempIndex):
        (WebCore::SQLAuthorizer::createTrigger):
        (WebCore::SQLAuthorizer::createTempTrigger):
        (WebCore::SQLAuthorizer::dropTrigger):
        (WebCore::SQLAuthorizer::dropTempTrigger):
        (WebCore::SQLAuthorizer::createView):
        (WebCore::SQLAuthorizer::createTempView):
        (WebCore::SQLAuthorizer::dropView):
        (WebCore::SQLAuthorizer::dropTempView):
        (WebCore::SQLAuthorizer::createVTable):
        (WebCore::SQLAuthorizer::dropVTable):
        (WebCore::SQLAuthorizer::allowDelete):
        (WebCore::SQLAuthorizer::allowInsert):
        (WebCore::SQLAuthorizer::allowUpdate):
        (WebCore::SQLAuthorizer::allowTransaction):
        (WebCore::SQLAuthorizer::allowSelect):
        (WebCore::SQLAuthorizer::allowRead):
        (WebCore::SQLAuthorizer::allowAttach):
        (WebCore::SQLAuthorizer::allowDetach):
        (WebCore::SQLAuthorizer::allowReindex):
        (WebCore::SQLAuthorizer::allowAnalyze):
        (WebCore::SQLAuthorizer::allowFunction):

        * platform/sql/SQLValue.cpp: Added.  Contains a value for a SQLite database that can be one of a few types.
          For now, just a String or a double
        (WebCore::SQLValue::SQLValue):
        (WebCore::SQLValue::string):
        (WebCore::SQLValue::number):
        * platform/sql/SQLValue.h: Added.
        (WebCore::SQLValue::):
        (WebCore::SQLValue::SQLValue):
        (WebCore::SQLValue::type):

2007-10-19  Brady Eidson <beidson@apple.com>

        Reviewed by Maciej

        Changed IconDatabase over to use new FileSystem apis

        * loader/icon/IconDatabase.cpp:
        (WebCore::IconDatabase::open):

WebKit:

        Reviewed by Tim Hatcher

        Added support for Chrome prompts required by the Storage API
        Added support API for future managing of databases from the WebKit client
        Added preference and initialization for the databases path

        * Misc/WebDatabaseManager.h: Added.  WebDatabaseManager is how a WebKit application can list and
          remove the current available databases
        * Misc/WebDatabaseManager.mm: Added.
        (+[WebDatabaseManager origins]):
        (+[WebDatabaseManager databasesWithOrigin:]):
        (+[WebDatabaseManager deleteAllDatabases]):
        (+[WebDatabaseManager deleteAllDatabasesWithOrigin:]):
        (+[WebDatabaseManager deleteDatabaseWithOrigin:named:]):
        (WebKitSetWebDatabasesPathIfNecessary): Setup the database path
        * Misc/WebDatabaseManagerPrivate.h: Added.

        * WebCoreSupport/WebChromeClient.h: Support for calling the delegate to run the prompt for
          an origin exceeding its size limit
        * WebCoreSupport/WebChromeClient.mm:
        (WebChromeClient::runDatabaseSizeLimitPrompt):
        * WebKit.xcodeproj/project.pbxproj:
        * WebView/WebUIDelegate.h:

        * WebView/WebView.mm:
        (-[WebView _commonInitializationWithFrameName:groupName:]): Setup the database path
        * WebView/WebViewInternal.h:

WebKitSite:

        Reviewed by Tim Hatcher

        Sample database API usage

        * misc/DatabaseExample.html: Added.

WebKit/win:

        Reviewed by Anders

        Keep windows building with new Chrome additions

        * WebChromeClient.cpp:
        * WebChromeClient.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@26787 268f45cc-cd09-0410-ab3c-d52691b4dbfc

103 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/wtf/Deque.h [new file with mode: 0644]
WebCore/ChangeLog
WebCore/DerivedSources.make
WebCore/ForwardingHeaders/wtf/Deque.h [new file with mode: 0644]
WebCore/WebCore.base.exp
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSCustomSQLCallback.cpp [new file with mode: 0644]
WebCore/bindings/js/JSCustomSQLCallback.h [new file with mode: 0644]
WebCore/bindings/js/JSCustomVersionChangeCallback.cpp [new file with mode: 0644]
WebCore/bindings/js/JSCustomVersionChangeCallback.h [new file with mode: 0644]
WebCore/bindings/js/JSDatabaseCustom.cpp [new file with mode: 0644]
WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp [new file with mode: 0644]
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/loader/icon/IconDatabase.cpp
WebCore/loader/icon/SQLDatabase.cpp
WebCore/loader/icon/SQLDatabase.h
WebCore/loader/icon/SQLStatement.cpp
WebCore/loader/icon/SQLStatement.h
WebCore/page/Chrome.cpp
WebCore/page/Chrome.h
WebCore/page/ChromeClient.h
WebCore/page/DOMWindow.cpp
WebCore/page/DOMWindow.h
WebCore/page/DOMWindow.idl
WebCore/page/InspectorController.cpp
WebCore/page/InspectorController.h
WebCore/page/inspector/Database.js [new file with mode: 0644]
WebCore/page/inspector/DatabasePanel.js [new file with mode: 0644]
WebCore/page/inspector/Images/alternateTableRows.png [new file with mode: 0644]
WebCore/page/inspector/Images/database.png [new file with mode: 0644]
WebCore/page/inspector/Images/databaseBrowserViewButton.png [new file with mode: 0644]
WebCore/page/inspector/Images/databaseQueryViewButton.png [new file with mode: 0644]
WebCore/page/inspector/Images/domViewButton.png
WebCore/page/inspector/Images/glossyHeader.png [new file with mode: 0644]
WebCore/page/inspector/Images/glossyHeaderPressed.png [new file with mode: 0644]
WebCore/page/inspector/Images/popupArrowsBlack.png [new file with mode: 0644]
WebCore/page/inspector/Images/reload.png [new file with mode: 0644]
WebCore/page/inspector/Images/sourceViewButton.png
WebCore/page/inspector/Images/toolbarPopup.png [new file with mode: 0644]
WebCore/page/inspector/Images/toolbarPopupInactive.png [new file with mode: 0644]
WebCore/page/inspector/Images/toolbarPopupPressed.png [new file with mode: 0644]
WebCore/page/inspector/Images/toolbarPopupPressedInactive.png [new file with mode: 0644]
WebCore/page/inspector/ResourceCategory.js
WebCore/page/inspector/inspector.css
WebCore/page/inspector/inspector.html
WebCore/page/inspector/inspector.js
WebCore/platform/FileSystem.h
WebCore/platform/Logging.cpp
WebCore/platform/Logging.h
WebCore/platform/SecurityOrigin.cpp
WebCore/platform/SecurityOrigin.h
WebCore/platform/cf/FileSystemCF.cpp [new file with mode: 0644]
WebCore/platform/graphics/svg/SVGImageEmptyClients.h
WebCore/platform/mac/FileSystemMac.mm
WebCore/platform/posix/FileSystemPOSIX.cpp [new file with mode: 0644]
WebCore/platform/sql/SQLAuthorizer.cpp [new file with mode: 0644]
WebCore/platform/sql/SQLAuthorizer.h [new file with mode: 0644]
WebCore/platform/sql/SQLValue.cpp [new file with mode: 0644]
WebCore/platform/sql/SQLValue.h [new file with mode: 0644]
WebCore/platform/win/FileSystemWin.cpp
WebCore/storage/Database.cpp [new file with mode: 0644]
WebCore/storage/Database.h [new file with mode: 0644]
WebCore/storage/Database.idl [new file with mode: 0644]
WebCore/storage/DatabaseAuthorizer.cpp [new file with mode: 0644]
WebCore/storage/DatabaseAuthorizer.h [new file with mode: 0644]
WebCore/storage/DatabaseCallback.cpp [new file with mode: 0644]
WebCore/storage/DatabaseCallback.h [new file with mode: 0644]
WebCore/storage/DatabaseTask.cpp [new file with mode: 0644]
WebCore/storage/DatabaseTask.h [new file with mode: 0644]
WebCore/storage/DatabaseThread.cpp [new file with mode: 0644]
WebCore/storage/DatabaseThread.h [new file with mode: 0644]
WebCore/storage/DatabaseTracker.cpp [new file with mode: 0644]
WebCore/storage/DatabaseTracker.h [new file with mode: 0644]
WebCore/storage/SQLCallback.h [new file with mode: 0644]
WebCore/storage/SQLCallback.idl [new file with mode: 0644]
WebCore/storage/SQLResultSet.cpp [new file with mode: 0644]
WebCore/storage/SQLResultSet.h [new file with mode: 0644]
WebCore/storage/SQLResultSet.idl [new file with mode: 0644]
WebCore/storage/SQLResultSetRowList.cpp [new file with mode: 0644]
WebCore/storage/SQLResultSetRowList.h [new file with mode: 0644]
WebCore/storage/SQLResultSetRowList.idl [new file with mode: 0644]
WebCore/storage/VersionChangeCallback.h [new file with mode: 0644]
WebCore/storage/VersionChangeCallback.idl [new file with mode: 0644]
WebKit/ChangeLog
WebKit/Misc/WebDatabaseManager.h [new file with mode: 0644]
WebKit/Misc/WebDatabaseManager.mm [new file with mode: 0644]
WebKit/Misc/WebDatabaseManagerPrivate.h [new file with mode: 0644]
WebKit/WebCoreSupport/WebChromeClient.h
WebKit/WebCoreSupport/WebChromeClient.mm
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/WebView/WebUIDelegatePrivate.h
WebKit/WebView/WebView.mm
WebKit/win/ChangeLog
WebKit/win/WebChromeClient.cpp
WebKit/win/WebChromeClient.h
WebKitSite/ChangeLog
WebKitSite/misc/DatabaseExample.html [new file with mode: 0644]

index c419ed7..565925f 100644 (file)
@@ -1,3 +1,48 @@
+2007-10-19  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Sam
+
+        Queue -> Deque! and small style tweaks
+
+        * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+        * JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+        * wtf/Deque.h: Added.
+        (WTF::DequeNode::DequeNode):
+        (WTF::Deque::Deque):
+        (WTF::Deque::~Deque):
+        (WTF::Deque::size):
+        (WTF::Deque::isEmpty):
+        (WTF::Deque::append):
+        (WTF::Deque::prepend):
+        (WTF::Deque::first):
+        (WTF::Deque::last):
+        (WTF::Deque::removeFirst):
+        (WTF::Deque::clear):
+        * wtf/Queue.h: Removed.
+
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Reviewed by Oliver
+
+        Added a simple LinkedList based Queue to wtf
+        We can make a better, more sophisticated an efficient one later, but have
+        needed one for some time, now!
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * wtf/Queue.h: Added.
+        (WTF::QueueNode::QueueNode):
+        (WTF::Queue::Queue):
+        (WTF::Queue::~Queue):
+        (WTF::Queue::size):
+        (WTF::Queue::isEmpty):
+        (WTF::Queue::append):
+        (WTF::Queue::prepend):
+        (WTF::Queue::first):
+        (WTF::Queue::last):
+        (WTF::Queue::removeFirst):
+        (WTF::Queue::clear):
+
 2007-10-19  Nikolas Zimmermann  <zimmermann@kde.org>
 
         Reviewed by Anders.
index e58b82d..babc57e 100644 (file)
                        >\r
                </File>\r
                <File\r
+                       RelativePath="..\..\wtf\Deque.h"\r
+                       >\r
+               </File>\r
+               <File\r
                        RelativePath="..\..\wtf\FastMalloc.cpp"\r
                        >\r
                </File>\r
index cc0978b..f85113b 100644 (file)
@@ -80,6 +80,7 @@
                14BD5A360A3E91F600BAF59C /* JavaScriptCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BD5A2F0A3E91F600BAF59C /* JavaScriptCore.h */; settings = {ATTRIBUTES = (Public, ); }; };
                14F137830A3A765B00F26F90 /* context.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F137820A3A765B00F26F90 /* context.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1CAF34890A6C421700ABE06E /* WebScriptObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAF34880A6C421700ABE06E /* WebScriptObject.h */; };
+               5186111E0CC824900081412B /* Deque.h in Headers */ = {isa = PBXBuildFile; fileRef = 5186111D0CC824830081412B /* Deque.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51F648D70BB4E2CA0033D760 /* RetainPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F648D60BB4E2CA0033D760 /* RetainPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5DBD18AC0C54018700C15EAE /* CollectorHeapIntrospector.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBD18AA0C54018700C15EAE /* CollectorHeapIntrospector.h */; };
                5DBD18B00C5401A700C15EAE /* MallocZoneSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */; };
                5182A53B06012C3000CBD2F2 /* c_class.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = c_class.h; path = bindings/c/c_class.h; sourceTree = "<group>"; tabWidth = 8; };
                51856D8F0562EE95008B9D83 /* jni_utility.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jni_utility.cpp; path = bindings/jni/jni_utility.cpp; sourceTree = "<group>"; tabWidth = 8; };
                51856D900562EE95008B9D83 /* jni_utility.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = jni_utility.h; path = bindings/jni/jni_utility.h; sourceTree = "<group>"; tabWidth = 8; };
+               5186111D0CC824830081412B /* Deque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deque.h; sourceTree = "<group>"; };
                518CF93605C72271003CF905 /* objc_class.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = objc_class.h; path = bindings/objc/objc_class.h; sourceTree = "<group>"; tabWidth = 8; };
                518CF93705C72271003CF905 /* objc_class.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = objc_class.mm; path = bindings/objc/objc_class.mm; sourceTree = "<group>"; tabWidth = 8; };
                518CF93805C72271003CF905 /* objc_runtime.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = objc_runtime.mm; path = bindings/objc/objc_runtime.mm; sourceTree = "<group>"; tabWidth = 8; };
                                938C4F690CA06BC700D9310A /* ASCIICType.h */,
                                65E217B808E7EECC0023E5F6 /* Assertions.cpp */,
                                65E217B708E7EECC0023E5F6 /* Assertions.h */,
+                               5186111D0CC824830081412B /* Deque.h */,
                                938C4F6B0CA06BCE00D9310A /* DisallowCType.h */,
                                65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */,
                                65E217BA08E7EECC0023E5F6 /* FastMalloc.h */,
                                95C18D490C90E82600E72F73 /* JSRetainPtr.h in Headers */,
                                938C4F6A0CA06BC700D9310A /* ASCIICType.h in Headers */,
                                938C4F6C0CA06BCE00D9310A /* DisallowCType.h in Headers */,
+                               5186111E0CC824900081412B /* Deque.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/JavaScriptCore/wtf/Deque.h b/JavaScriptCore/wtf/Deque.h
new file mode 100644 (file)
index 0000000..c09ef42
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+#ifndef WTF_Deque_h
+#define WTF_Deque_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace WTF {
+
+    template<typename T>
+    class DequeNode {
+    public:
+        DequeNode(const T& item) : m_value(item), m_next(0) { }
+
+        T m_value;
+        DequeNode* m_next;
+    };
+
+    template<typename T>
+    class Deque : Noncopyable {
+    public:
+        Deque()
+            : m_size(0)
+            , m_first(0)
+            , m_last(0)
+        {
+        }
+
+        ~Deque()
+        {
+            clear();
+        }
+
+        size_t size() const { return m_size; }
+        bool isEmpty() const { return !size(); }
+
+        void append(const T& item)
+        {
+            DequeNode<T>* newNode = new DequeNode<T>(item);
+            if (m_last)
+                m_last->m_next = newNode;
+            m_last = newNode;
+            if (!m_first)
+                m_first = newNode;
+            ++m_size;
+        }
+
+        void prepend(const T& item)
+        {
+            DequeNode<T>* newNode = new DequeNode<T>(item);
+            newNode->m_next = m_first;
+            m_first = newNode;
+            if (!m_last)
+                m_last = newNode;
+            ++m_size;
+        }
+
+        T& first() { ASSERT(m_first); return m_first->m_value; }
+        const T& first() const { ASSERT(m_first); return m_first->m_value; }
+        T& last() { ASSERT(m_last); return m_last->m_value; }
+        const T& last() const { ASSERT(m_last); return m_last->m_value; }
+
+        void removeFirst() 
+        {
+            ASSERT(m_first);
+            if (DequeNode<T>* n = m_first) {
+                m_first = m_first->m_next;
+                if (n == m_last)
+                    m_last = 0;
+
+                m_size--;
+                delete n;
+            }
+        }
+
+        void clear() 
+        {
+            DequeNode<T>* n = m_first;
+            m_first = 0;
+            m_last = 0;
+            m_size = 0;
+            while (n) {
+                DequeNode<T>* next = n->m_next;
+                delete n;
+                n = next;
+            }
+        }
+
+    private:
+        size_t m_size;
+        DequeNode<T>* m_first;
+        DequeNode<T>* m_last;
+
+    };
+
+} // namespace WTF
+
+using WTF::Deque;
+
+#endif // WTF_Deque_h
index 289aaf7..8cc8c9c 100644 (file)
@@ -1,3 +1,399 @@
+2007-10-19  Brady Eidson  <beidson@apple.com>
+        Reviewed by Anders
+
+        Windows specific changes, as well as renaming Queue -> Deque
+
+        * ForwardingHeaders/wtf/Deque.h: Added.
+        * ForwardingHeaders/wtf/Queue.h: Removed.
+        * platform/win/FileSystemWin.cpp:
+        (WebCore::fileSize):
+        (WebCore::fileExists):
+        (WebCore::deleteFile):
+        (WebCore::pathByAppendingComponent):
+        (WebCore::fileSystemRepresentation):
+        (WebCore::makeAllDirectories):
+        (WebCore::homeDirectoryPath):
+        * storage/Database.h:
+        * storage/DatabaseThread.cpp:
+        (WebCore::DatabaseThread::documentGoingAway):
+        (WebCore::DatabaseThread::databaseGoingAway):
+        (WebCore::DatabaseThread::dispatchNextTaskIdentifier):
+        (WebCore::DatabaseThread::scheduleTask):
+        (WebCore::DatabaseThread::scheduleImmediateTask):
+        * storage/DatabaseThread.h:
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Reviewed by Tim and Anders
+
+        Preliminary support for HTML5 local database storage (http://www.whatwg.org/specs/web-apps/current-work/)
+
+        The specification is still in flux but the fundamentals are pretty solid and we can start using and testing 
+        this implementation even while filing bugs to track changes in the spec as it becomes more final
+
+        There are some implementation details in this patch that seem unused or useless, but they remain in place 
+        while the spec is in flux and might go one way or another.
+
+        * platform/Logging.cpp: Add StorageAPI logging channel
+        * platform/Logging.h:
+
+        * storage/Database.cpp: Added.
+        (WebCore::Database::databaseInfoTableName):
+        (WebCore::databaseVersionKey):
+        (WebCore::Database::openDatabase): C++ version of the window.openDatabase() javascript API
+        (WebCore::Database::Database):
+        (WebCore::Database::~Database):
+        (WebCore::Database::openAndVerifyVersion):
+        (WebCore::retrieveTextResultFromDatabase):
+        (WebCore::Database::getVersionFromDatabase):
+        (WebCore::setTextValueInDatabase):
+        (WebCore::Database::setVersionInDatabase):
+        (WebCore::Database::databaseThreadGoingAway): May be removed in the future
+        (WebCore::Database::disableAuthorizer): For internal (WebInspector) use to get around the authorizer's restrictions
+        (WebCore::Database::enableAuthorizer):
+        (WebCore::Database::guidForOriginAndName): Candidate for refactoring and/or moving to the database tracker.  
+          The GUID for each database identifier is currently for tracking the database version, but might be rescoped in the future
+        (WebCore::Database::resetAuthorizer):
+        (WebCore::Database::performPolicyChecks): Currently, the only post-executeSql policy check planned is the origin size usage 
+        (WebCore::Database::scheduleDatabaseCallback):
+        (WebCore::Database::performOpenAndVerify): 
+        (WebCore::Database::performChangeVersion):
+        (WebCore::Database::performExecuteSql):
+        (WebCore::Database::performCloseTransaction):
+        (WebCore::Database::performGetTableNames):
+        (WebCore::Database::version): C++ version of the javascript API
+        (WebCore::Database::changeVersion): Ditto
+        (WebCore::Database::executeSql): Ditto
+        (WebCore::Database::closeTransaction): Ditto
+        (WebCore::Database::tableNames): For internal (WebInspector) use
+        (WebCore::Database::deliverAllPendingCallbacks):
+        (WebCore::Database::deliverPendingCallbacks):
+        * storage/Database.h: Added.
+        (WebCore::Database::databaseDebugName): For debug logging purposes
+        * storage/Database.idl: Added.
+
+        * storage/DatabaseAuthorizer.cpp: Added.
+          The DatabaseAuthorizer is used to both prevent the script from doing "illegal" things in sql as well as
+          tracking when effects certain sql statements might have (such as increasing the size of the database)
+        (WebCore::DatabaseAuthorizer::DatabaseAuthorizer):
+        (WebCore::DatabaseAuthorizer::reset):
+        (WebCore::DatabaseAuthorizer::createTable):
+        (WebCore::DatabaseAuthorizer::createTempTable):
+        (WebCore::DatabaseAuthorizer::dropTable):
+        (WebCore::DatabaseAuthorizer::dropTempTable):
+        (WebCore::DatabaseAuthorizer::allowAlterTable):
+        (WebCore::DatabaseAuthorizer::createIndex):
+        (WebCore::DatabaseAuthorizer::createTempIndex):
+        (WebCore::DatabaseAuthorizer::dropIndex):
+        (WebCore::DatabaseAuthorizer::dropTempIndex):
+        (WebCore::DatabaseAuthorizer::createTrigger):
+        (WebCore::DatabaseAuthorizer::createTempTrigger):
+        (WebCore::DatabaseAuthorizer::dropTrigger):
+        (WebCore::DatabaseAuthorizer::dropTempTrigger):
+        (WebCore::DatabaseAuthorizer::createVTable):
+        (WebCore::DatabaseAuthorizer::dropVTable):
+        (WebCore::DatabaseAuthorizer::allowDelete):
+        (WebCore::DatabaseAuthorizer::allowInsert):
+        (WebCore::DatabaseAuthorizer::allowUpdate):
+        (WebCore::DatabaseAuthorizer::allowRead):
+        (WebCore::DatabaseAuthorizer::allowAnalyze):
+        (WebCore::DatabaseAuthorizer::allowPragma):
+        (WebCore::DatabaseAuthorizer::allowAttach):
+        (WebCore::DatabaseAuthorizer::allowDetach):
+        (WebCore::DatabaseAuthorizer::allowFunction):
+        (WebCore::DatabaseAuthorizer::disable):
+        (WebCore::DatabaseAuthorizer::enable):
+        (WebCore::DatabaseAuthorizer::denyBasedOnTableName): Don't allow access to the __WebKit meta info table as
+          it should be invisible to scripts
+        * storage/DatabaseAuthorizer.h: Added.
+        (WebCore::DatabaseAuthorizer::lastActionWasInsert):
+        (WebCore::DatabaseAuthorizer::lastActionIncreasedSize):
+
+        * storage/DatabaseCallback.cpp: Added.
+          Generic item to queue up for callbacks on the main thread for database activities that take place on 
+          a secondary thread
+        (WebCore::DatabaseChangeVersionCallback::DatabaseChangeVersionCallback):
+        (WebCore::DatabaseChangeVersionCallback::performCallback):
+        (WebCore::DatabaseExecuteSqlCallback::DatabaseExecuteSqlCallback):
+        (WebCore::DatabaseExecuteSqlCallback::performCallback):
+        * storage/DatabaseCallback.h: Added.
+        (WebCore::DatabaseCallback::~DatabaseCallback):
+        (WebCore::DatabaseChangeVersionCallback::~DatabaseChangeVersionCallback):
+        (WebCore::DatabaseExecuteSqlCallback::~DatabaseExecuteSqlCallback):
+
+        * storage/DatabaseTask.h: Added.
+          Generic work-item to be queued up on the background database thread
+        (WebCore::DatabaseTask::isComplete):
+        (WebCore::DatabaseOpenTask::exceptionCode):
+        (WebCore::DatabaseOpenTask::openSuccessful):
+        (WebCore::DatabaseTableNamesTask::tableNames):
+        * storage/DatabaseTask.cpp: Added.
+        (WebCore::DatabaseTask::DatabaseTask):
+        (WebCore::DatabaseTask::~DatabaseTask):
+        (WebCore::DatabaseTask::performTask):
+        (WebCore::DatabaseTask::lockForSynchronousScheduling): Used when the main thread needs this task accomplished 
+          synchronously
+        (WebCore::DatabaseTask::waitForSynchronousCompletion):
+
+        (WebCore::DatabaseOpenTask::DatabaseOpenTask):
+        (WebCore::DatabaseOpenTask::doPerformTask):
+
+        (WebCore::DatabaseExecuteSqlTask::DatabaseExecuteSqlTask):
+        (WebCore::DatabaseExecuteSqlTask::doPerformTask):
+
+        (WebCore::DatabaseChangeVersionTask::DatabaseChangeVersionTask):
+        (WebCore::DatabaseChangeVersionTask::doPerformTask):
+
+        (WebCore::DatabaseTableNamesTask::DatabaseTableNamesTask):
+        (WebCore::DatabaseTableNamesTask::doPerformTask):
+
+        * storage/DatabaseThread.cpp: Added.
+          The current design is that each Document will have its own DatabaseThread.  This makes scripts on each
+          individual document more response at the cost of adding more threads and potentially creating concurrency
+          issues when the same database is open twice from two different documents
+        (WebCore::DatabaseThread::DatabaseThread):
+        (WebCore::DatabaseThread::~DatabaseThread):
+        (WebCore::DatabaseThread::start):
+        (WebCore::DatabaseThread::documentGoingAway): Called to shut the thread down when the document is destroyed
+        (WebCore::DatabaseThread::databaseGoingAway): Remove all pending tasks for this database
+        (WebCore::DatabaseThread::databaseThreadStart):
+        (WebCore::DatabaseThread::databaseThread):
+        (WebCore::DatabaseThread::dispatchNextTaskIdentifier):
+        (WebCore::DatabaseThread::scheduleTask):
+        (WebCore::DatabaseThread::scheduleImmediateTask): Schedule a task that gets to "cut to the front of the line" when
+          the main thread requires a task be performed synchronously
+        (WebCore::DatabaseThread::wakeWorkThread):
+        * storage/DatabaseThread.h: Added.
+
+        * storage/DatabaseTracker.cpp: Added.
+          The DatabaseTracker is the master management of all databases.  It will keep track of the filename for a given
+          unique database, keep track of the total disk usage per-origin, and policys per database/origin
+        (WebCore::DatabaseTracker::setDatabasePath):
+        (WebCore::DatabaseTracker::databasePath):
+        (WebCore::DatabaseTracker::tracker):
+        (WebCore::DatabaseTracker::DatabaseTracker):
+        (WebCore::DatabaseTracker::fullPathForDatabase):
+        (WebCore::DatabaseTracker::populateOrigins):
+        (WebCore::DatabaseTracker::origins):
+        (WebCore::DatabaseTracker::databaseNamesForOrigin):
+        (WebCore::DatabaseTracker::addDatabase):
+        (WebCore::DatabaseTracker::deleteAllDatabases):
+        (WebCore::DatabaseTracker::deleteAllDatabasesForOrigin):
+        * storage/DatabaseTracker.h: Added.
+
+        * storage/SQLCallback.h: Added. C++ version of the javascript executeSql() callback
+        (WebCore::SQLCallback::~SQLCallback):
+        * storage/SQLCallback.idl: Added.
+
+        * storage/SQLResultSet.cpp: Added. C++ version of the javascript SQLResultSet object
+        (WebCore::SQLResultSet::SQLResultSet):
+        (WebCore::SQLResultSet::insertId):
+        (WebCore::SQLResultSet::rowsAffected):
+        (WebCore::SQLResultSet::errorCode):
+        (WebCore::SQLResultSet::error):
+        (WebCore::SQLResultSet::rows):
+        (WebCore::SQLResultSet::setInsertId):
+        (WebCore::SQLResultSet::setRowsAffected):
+        (WebCore::SQLResultSet::setErrorCode):
+        (WebCore::SQLResultSet::setErrorMessage):
+        * storage/SQLResultSet.h: Added.
+        * storage/SQLResultSet.idl: Added.
+
+        * storage/SQLResultSetRowList.cpp: Added. C++ version of the javascript SQLResultSetRowList object
+        (WebCore::SQLResultSetRowList::length):
+        * storage/SQLResultSetRowList.h: Added.
+        (WebCore::SQLResultSetRowList::columnNames):
+        (WebCore::SQLResultSetRowList::values):
+        (WebCore::SQLResultSetRowList::addColumn):
+        (WebCore::SQLResultSetRowList::addResult):
+        * storage/SQLResultSetRowList.idl: Added.
+
+        * storage/VersionChangeCallback.h: Added. C++ version of the javascript changeVersion() callback
+        (WebCore::VersionChangeCallback::~VersionChangeCallback):
+        * storage/VersionChangeCallback.idl: Added.
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Reviewed by Oliver + Same
+
+        Forwarding header for the new wtf/Queue.h
+
+        * ForwardingHeaders/wtf/Queue.h: Added.
+
+2007-10-19  Anders Carlsson <beidson@apple.com>
+
+        Reviewed by Sam Weinig
+
+        Most of the Javascript binding support for the Storage API
+
+        * bindings/js/JSCustomSQLCallback.cpp: Added.
+        (WebCore::JSCustomSQLCallback::JSCustomSQLCallback):
+        (WebCore::JSCustomSQLCallback::handleEvent):
+        * bindings/js/JSCustomSQLCallback.h: Added.
+                Add JSCustomSQLCallback which is an SQLCallback implementation that dispatches
+                handleEvent to a JS function or a JS object with a handleEvent function.
+
+        * bindings/js/JSCustomVersionChangeCallback.cpp: Added.
+        (WebCore::JSCustomVersionChangeCallback::JSCustomVersionChangeCallback):
+        (WebCore::JSCustomVersionChangeCallback::handleEvent):
+        * bindings/js/JSCustomVersionChangeCallback.h: Added.
+                Add JSCustomSQLCallback which is an SQLCallback implementation that dispatches
+                handleEvent to a JS function or a JS object with a handleEvent function.
+
+        * bindings/js/JSDatabaseCustom.cpp: Added.
+        (WebCore::JSDatabase::executeSql):
+                Custom implementation of executeSql that takes an array of parameters.
+                
+        (WebCore::JSDatabase::changeVersion):
+                Custom implementation of changeVersion.
+                
+        * bindings/js/JSSQLResultSetRowListCustom.cpp: Added.
+        (WebCore::JSSQLResultSetRowList::item):
+                Custom method that returns a JS object that corresponds to a given row in the database.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::openDatabase):
+        * page/DOMWindow.h:
+        * page/DOMWindow.idl:
+                Add openDatabase implementation.
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Reviewed by Oliver
+
+        Added tons of utility to the FileSystem abstractions, including moving
+        some stuff over from IconDatabase
+
+        * platform/FileSystem.h:
+
+        * platform/cf/FileSystemCF.cpp: Added.
+        (WebCore::fileSystemRepresentation):
+
+        * platform/mac/FileSystemMac.mm:
+
+        * platform/posix/FileSystemPOSIX.cpp: Added.
+        (WebCore::fileExists):
+        (WebCore::deleteFile):
+        (WebCore::fileSize):
+        (WebCore::pathByAppendingComponent):
+        (WebCore::makeAllDirectories):
+
+2007-10-19  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Adam Roben
+
+        Preliminary Web Inspector support for the Storage API
+        (This patch does not include the support artwork)
+
+        * page/InspectorController.cpp:
+        (WebCore::InspectorDatabaseResource::InspectorDatabaseResource):
+        (WebCore::InspectorDatabaseResource::setScriptObject):
+        (WebCore::databaseTableNames): Return the table names for a Database object.
+        (WebCore::InspectorController::setWindowVisible):
+        (WebCore::InspectorController::windowScriptObjectAvailable):
+        (WebCore::InspectorController::populateScriptResources):
+        (WebCore::InspectorController::addDatabaseScriptResource): Add the script object for the database.
+        (WebCore::InspectorController::removeDatabaseScriptResource): Remove the script object for the database.
+        (WebCore::InspectorController::clearDatabaseScriptResources): Remove all the database resources.
+        (WebCore::InspectorController::didCommitLoad): Call clearDatabaseScriptResources().
+        (WebCore::InspectorController::didOpenDatabase): Make a new InspectorDatabaseResource and add it to m_databaseResources.
+        * page/InspectorController.h:
+        * page/inspector/Database.js: Added.
+        * page/inspector/DatabasePanel.js: Added.
+        * page/inspector/ResourceCategory.js: Make resource categories assume less about the resource.
+        * page/inspector/inspector.css: Add styles for the database panel.
+        * page/inspector/inspector.html: Include DatabasePanel.js
+        * page/inspector/inspector.js: Support for adding and removing Database resources.
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Reviewed by Tim Hatcher
+
+        Added support for Chrome prompts required by the Storage API
+
+        * page/Chrome.cpp:
+        (WebCore::Chrome::runDatabaseSizeLimitPrompt):
+        * page/Chrome.h:
+        * page/ChromeClient.h:
+        * platform/graphics/svg/SVGImageEmptyClients.h:
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Contributions and Review by Anders
+
+        Various SQLite tweaks in preparation for the storage API
+
+        * loader/icon/SQLDatabase.cpp:
+        (WebCore::SQLDatabase::~SQLDatabase):
+        (WebCore::SQLDatabase::authorizerFunction): Static callback from sqlite for authorizer functions
+        (WebCore::SQLDatabase::setAuthorizer):
+        (WebCore::SQLDatabase::lock):
+        (WebCore::SQLDatabase::unlock):
+        * loader/icon/SQLDatabase.h:
+
+        * loader/icon/SQLStatement.cpp:
+        (WebCore::SQLStatement::prepare): Switch to prepare16_v2
+        (WebCore::SQLStatement::bindDouble): Added
+        (WebCore::SQLStatement::bindValue): Bind a wrapped SQLValue object (described later)
+        (WebCore::SQLStatement::bindParameterCount): Accessor to the sqlite3 API for validating statements
+        * loader/icon/SQLStatement.h:
+        (WebCore::SQLStatement::isPrepared):
+
+        * platform/sql/SQLAuthorizer.cpp: Added.  Fully virtual interface to implement your own SQLite authorizer
+        * platform/sql/SQLAuthorizer.h: Added.
+        (WebCore::SQLAuthorizer::~SQLAuthorizer):
+        (WebCore::SQLAuthorizer::createTable):
+        (WebCore::SQLAuthorizer::createTempTable):
+        (WebCore::SQLAuthorizer::dropTable):
+        (WebCore::SQLAuthorizer::dropTempTable):
+        (WebCore::SQLAuthorizer::allowAlterTable):
+        (WebCore::SQLAuthorizer::createIndex):
+        (WebCore::SQLAuthorizer::createTempIndex):
+        (WebCore::SQLAuthorizer::dropIndex):
+        (WebCore::SQLAuthorizer::dropTempIndex):
+        (WebCore::SQLAuthorizer::createTrigger):
+        (WebCore::SQLAuthorizer::createTempTrigger):
+        (WebCore::SQLAuthorizer::dropTrigger):
+        (WebCore::SQLAuthorizer::dropTempTrigger):
+        (WebCore::SQLAuthorizer::createView):
+        (WebCore::SQLAuthorizer::createTempView):
+        (WebCore::SQLAuthorizer::dropView):
+        (WebCore::SQLAuthorizer::dropTempView):
+        (WebCore::SQLAuthorizer::createVTable):
+        (WebCore::SQLAuthorizer::dropVTable):
+        (WebCore::SQLAuthorizer::allowDelete):
+        (WebCore::SQLAuthorizer::allowInsert):
+        (WebCore::SQLAuthorizer::allowUpdate):
+        (WebCore::SQLAuthorizer::allowTransaction):
+        (WebCore::SQLAuthorizer::allowSelect):
+        (WebCore::SQLAuthorizer::allowRead):
+        (WebCore::SQLAuthorizer::allowAttach):
+        (WebCore::SQLAuthorizer::allowDetach):
+        (WebCore::SQLAuthorizer::allowReindex):
+        (WebCore::SQLAuthorizer::allowAnalyze):
+        (WebCore::SQLAuthorizer::allowFunction):
+
+        * platform/sql/SQLValue.cpp: Added.  Contains a value for a SQLite database that can be one of a few types.  
+          For now, just a String or a double
+        (WebCore::SQLValue::SQLValue):
+        (WebCore::SQLValue::string):
+        (WebCore::SQLValue::number):
+        * platform/sql/SQLValue.h: Added.
+        (WebCore::SQLValue::):
+        (WebCore::SQLValue::SQLValue):
+        (WebCore::SQLValue::type):
+
+2007-10-19  Brady Eidson <beidson@apple.com>
+
+        Reviewed by Maciej
+
+        Changed IconDatabase over to use new FileSystem apis
+
+        * loader/icon/IconDatabase.cpp:
+        (WebCore::IconDatabase::open):
+
 2007-10-19  David Hyatt  <hyatt@apple.com>
 
         Fix for ebay parser crash.
index 36ed2ad..df67b7d 100644 (file)
@@ -33,6 +33,7 @@ VPATH = \
     $(WebCore)/dom \
     $(WebCore)/html \
     $(WebCore)/page \
+    $(WebCore)/storage \
     $(WebCore)/xml \
     $(WebCore)/ksvg2/svg \
     $(WebCore)/ksvg2/events \
@@ -321,6 +322,7 @@ all : \
     JSComment.h \
     JSCounter.h \
     JSCSSStyleDeclaration.h \
+    JSDatabase.h \
     JSDOMExceptionConstructor.lut.h \
     JSDOMImplementation.h \
     JSDOMParser.h \
@@ -411,6 +413,9 @@ all : \
     JSRange.h \
     JSRangeException.h \
     JSRect.h \
+    JSSQLCallback.h \
+    JSSQLResultSet.h \
+    JSSQLResultSetRowList.h \
     JSSVGAElement.h \
     JSSVGAngle.h \
     JSSVGAnimatedAngle.h \
@@ -543,6 +548,7 @@ all : \
     JSTextEvent.h \
     JSTreeWalker.h \
     JSUIEvent.h \
+    JSVersionChangeCallback.h \
     JSXPathEvaluator.h \
     JSXPathExpression.h \
     JSXPathNSResolver.h \
diff --git a/WebCore/ForwardingHeaders/wtf/Deque.h b/WebCore/ForwardingHeaders/wtf/Deque.h
new file mode 100644 (file)
index 0000000..81bd70a
--- /dev/null
@@ -0,0 +1 @@
+#include <JavaScriptCore/Deque.h>
index f13ae6e..9115d88 100644 (file)
@@ -287,6 +287,13 @@ __ZN7WebCore15BackForwardList9goForwardEv
 __ZN7WebCore15BackForwardListC1EPNS_4PageE
 __ZN7WebCore15BackForwardListD1Ev
 __ZN7WebCore15ContextMenuItem26releasePlatformDescriptionEv
+__ZN7WebCore15DatabaseTracker14deleteDatabaseERKNS_6StringES3_
+__ZN7WebCore15DatabaseTracker15setDatabasePathERKNS_6StringE
+__ZN7WebCore15DatabaseTracker18deleteAllDatabasesEv
+__ZN7WebCore15DatabaseTracker22databaseNamesForOriginERKNS_6StringERN3WTF6VectorIS1_Lm0EEE
+__ZN7WebCore15DatabaseTracker27deleteAllDatabasesForOriginERKNS_6StringE
+__ZN7WebCore15DatabaseTracker7originsEv
+__ZN7WebCore15DatabaseTracker7trackerEv
 __ZN7WebCore15FocusController15setFocusedFrameEN3WTF10PassRefPtrINS_5FrameEEE
 __ZN7WebCore15FocusController15setInitialFocusENS_14FocusDirectionEPNS_13KeyboardEventE
 __ZN7WebCore15FocusController18focusedOrMainFrameEv
@@ -303,6 +310,8 @@ __ZN7WebCore16DeprecatedStringC1ERKS0_
 __ZN7WebCore16DeprecatedStringC1Ev
 __ZN7WebCore16DeprecatedStringD1Ev
 __ZN7WebCore16DeprecatedStringaSERKS0_
+__ZN7WebCore16FontPlatformDataC1EP6NSFontbb
+__ZN7WebCore16FontPlatformDataD1Ev
 __ZN7WebCore16MIMETypeRegistry24isSupportedImageMIMETypeERKNS_6StringE
 __ZN7WebCore16MIMETypeRegistry26getSupportedImageMIMETypesEv
 __ZN7WebCore16MIMETypeRegistry29getSupportedNonImageMIMETypesEv
@@ -346,8 +355,6 @@ __ZN7WebCore4FontC1ERKNS_16FontPlatformDataEb
 __ZN7WebCore4FontC1Ev
 __ZN7WebCore4FontD1Ev
 __ZN7WebCore4FontaSERKS0_
-__ZN7WebCore16FontPlatformDataC1EP6NSFontbb
-__ZN7WebCore16FontPlatformDataD1Ev
 __ZN7WebCore4KURL13decode_stringERKNS_16DeprecatedStringE
 __ZN7WebCore4KURLC1EP5NSURL
 __ZN7WebCore4KURLC1ERKNS_16DeprecatedStringE
index 60e4c13..71ec808 100644 (file)
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="&quot;$(ProjectDir)..\&quot;;&quot;$(ProjectDir)..&quot;;&quot;$(ProjectDir)..\css&quot;;&quot;$(ProjectDir)..\css&quot;;&quot;$(ProjectDir)..\editing&quot;;&quot;$(ProjectDir)..\editing&quot;;&quot;$(ProjectDir)..\rendering&quot;;&quot;$(ProjectDir)..\rendering&quot;;&quot;$(ProjectDir)..\bindings\js&quot;;&quot;$(ProjectDir)..\bindings\js&quot;;&quot;$(ProjectDir)..\dom&quot;;&quot;$(ProjectDir)..\dom&quot;;&quot;$(ProjectDir)..\history&quot;;&quot;$(ProjectDir)..\html&quot;;&quot;$(ProjectDir)..\html&quot;;&quot;$(ProjectDir)..\bridge&quot;;&quot;$(ProjectDir)..\bridge&quot;;&quot;$(ProjectDir)..\bridge\win&quot;;&quot;$(ProjectDir)..\bridge\win&quot;;&quot;$(ProjectDir)..\loader&quot;;&quot;$(ProjectDir)..\loader&quot;;&quot;$(ProjectDir)..\loader\icon&quot;;&quot;$(ProjectDir)..\loader\icon&quot;;&quot;$(ProjectDir)..\page&quot;;&quot;$(ProjectDir)..\page&quot;;&quot;$(ProjectDir)..\platform&quot;;&quot;$(ProjectDir)..\platform\win&quot;;&quot;$(ProjectDir)..\platform\network&quot;;&quot;$(ProjectDir)..\platform\network\win&quot;;&quot;$(ProjectDir)..\platform&quot;;&quot;$(ProjectDir)..\platform\cf&quot;;&quot;$(ProjectDir)..\platform\network&quot;;&quot;$(ProjectDir)..\platform\network\cf&quot;;&quot;$(ProjectDir)..\platform\network\win&quot;;&quot;$(ProjectDir)..\platform\graphics&quot;;&quot;$(ProjectDir)..\platform\graphics&quot;;&quot;$(ProjectDir)..\platform\graphics\cairo&quot;;&quot;$(ProjectDir)..\platform\graphics\cairo&quot;;&quot;$(ProjectDir)..\platform\graphics\cg&quot;;&quot;$(ProjectDir)..\platform\graphics\cg&quot;;&quot;$(ProjectDir)..\platform\graphics\win&quot;;&quot;$(ProjectDir)..\platform\graphics\win&quot;;&quot;$(ProjectDir)..\platform\image-decoders&quot;;&quot;$(ProjectDir)..\platform\image-decoders&quot;;&quot;$(ProjectDir)..\platform\image-decoders\bmp&quot;;&quot;$(ProjectDir)..\platform\image-decoders\bmp&quot;;&quot;$(ProjectDir)..\platform\image-decoders\gif&quot;;&quot;$(ProjectDir)..\platform\image-decoders\gif&quot;;&quot;$(ProjectDir)..\platform\image-decoders\ico&quot;;&quot;$(ProjectDir)..\platform\image-decoders\ico&quot;;&quot;$(ProjectDir)..\platform\image-decoders\jpeg&quot;;&quot;$(ProjectDir)..\platform\image-decoders\jpeg&quot;;&quot;$(ProjectDir)..\platform\image-decoders\png&quot;;&quot;$(ProjectDir)..\platform\image-decoders\png&quot;;&quot;$(ProjectDir)..\platform\image-decoders\xbm&quot;;&quot;$(ProjectDir)..\platform\image-decoders\xbm&quot;;&quot;$(ProjectDir)..\platform\image-decoders\zlib&quot;;&quot;$(ProjectDir)..\platform\image-decoders\zlib&quot;;&quot;$(ProjectDir)..\xml&quot;;&quot;$(ProjectDir)..\xml&quot;;&quot;$(WebKitOutputDir)\obj\WebCore\DerivedSources&quot;;&quot;$(ProjectDir)..\platform\win&quot;;&quot;$(ProjectDir)..\plugins\win&quot;;&quot;$(ProjectDir)..\platform\cairo\pixman\src&quot;;&quot;$(ProjectDir)..\platform\cairo\pixman\src&quot;;&quot;$(ProjectDir)..\platform\cairo\cairo\src&quot;;&quot;$(ProjectDir)..\platform\cairo\cairo\src&quot;;&quot;$(ProjectDir)..\platform\graphics\svg&quot;;&quot;$(ProjectDir)..\platform\graphics\svg\cg&quot;;&quot;$(ProjectDir)..\platform\graphics\svg\filters&quot;;&quot;$(ProjectDir)..\kcanvas&quot;;&quot;$(ProjectDir)..\kcanvas\device&quot;;&quot;$(ProjectDir)..\kcanvas\device\quartz&quot;;&quot;$(ProjectDir)..\ksvg2&quot;;&quot;$(ProjectDir)..\ksvg2\css&quot;;&quot;$(ProjectDir)..\ksvg2\events&quot;;&quot;$(ProjectDir)..\ksvg2\misc&quot;;&quot;$(ProjectDir)..\ksvg2\svg&quot;;&quot;$(WebKitOutputDir)\include&quot;;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(ProjectDir)..\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;&quot;$(WebKitLibrariesDir)\include\iconv&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\include\sqlite&quot;;&quot;$(WebKitLibrariesDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(ProjectDir)..\&quot;;&quot;$(ProjectDir)..&quot;;&quot;$(ProjectDir)..\css&quot;;&quot;$(ProjectDir)..\editing&quot;;&quot;$(ProjectDir)..\rendering&quot;;&quot;$(ProjectDir)..\bindings\js&quot;;&quot;$(ProjectDir)..\dom&quot;;&quot;$(ProjectDir)..\history&quot;;&quot;$(ProjectDir)..\html&quot;;&quot;$(ProjectDir)..\bridge&quot;;&quot;$(ProjectDir)..\bridge\win&quot;;&quot;$(ProjectDir)..\loader&quot;;&quot;$(ProjectDir)..\loader\icon&quot;;&quot;$(ProjectDir)..\page&quot;;&quot;$(ProjectDir)..\platform&quot;;&quot;$(ProjectDir)..\platform\sql&quot;;&quot;$(ProjectDir)..\platform\win&quot;;&quot;$(ProjectDir)..\platform\network&quot;;&quot;$(ProjectDir)..\platform\network\win&quot;;&quot;$(ProjectDir)..\platform\cf&quot;;&quot;$(ProjectDir)..\platform\network\cf&quot;;&quot;$(ProjectDir)..\platform\graphics&quot;;&quot;$(ProjectDir)..\platform\graphics\cairo&quot;;&quot;$(ProjectDir)..\platform\graphics\cg&quot;;&quot;$(ProjectDir)..\platform\graphics\win&quot;;&quot;$(ProjectDir)..\platform\image-decoders&quot;;&quot;$(ProjectDir)..\platform\image-decoders\bmp&quot;;&quot;$(ProjectDir)..\platform\image-decoders\gif&quot;;&quot;$(ProjectDir)..\platform\image-decoders\ico&quot;;&quot;$(ProjectDir)..\platform\image-decoders\jpeg&quot;;&quot;$(ProjectDir)..\platform\image-decoders\png&quot;;&quot;$(ProjectDir)..\platform\image-decoders\xbm&quot;;&quot;$(ProjectDir)..\platform\image-decoders\zlib&quot;;&quot;$(ProjectDir)..\xml&quot;;&quot;$(WebKitOutputDir)\obj\WebCore\DerivedSources&quot;;&quot;$(ProjectDir)..\plugins\win&quot;;&quot;$(ProjectDir)..\platform\cairo\pixman\src&quot;;&quot;$(ProjectDir)..\platform\cairo\cairo\src&quot;;&quot;$(ProjectDir)..\platform\graphics\svg&quot;;&quot;$(ProjectDir)..\platform\graphics\svg\cg&quot;;&quot;$(ProjectDir)..\platform\graphics\svg\filters&quot;;&quot;$(ProjectDir)..\kcanvas&quot;;&quot;$(ProjectDir)..\kcanvas\device&quot;;&quot;$(ProjectDir)..\kcanvas\device\quartz&quot;;&quot;$(ProjectDir)..\ksvg2&quot;;&quot;$(ProjectDir)..\ksvg2\css&quot;;&quot;$(ProjectDir)..\ksvg2\events&quot;;&quot;$(ProjectDir)..\ksvg2\misc&quot;;&quot;$(ProjectDir)..\ksvg2\svg&quot;;&quot;$(ProjectDir)..\storage&quot;;&quot;$(WebKitOutputDir)\include&quot;;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(ProjectDir)..\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;&quot;$(WebKitLibrariesDir)\include\iconv&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\include\sqlite&quot;;&quot;$(WebKitLibrariesDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"\r
                                PreprocessorDefinitions="WIN32;__WIN32__;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ENABLE_XSLT;ENABLE_XPATH;ENABLE_SVG;ENABLE_SVG_EXPERIMENTAL_FEATURES;WEBCORE_CONTEXT_MENUS;USE_SAFARI_THEME"\r
                                MinimalRebuild="true"\r
                                ExceptionHandling="0"\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSDatabase.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSDatabase.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSDocument.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSSQLCallback.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSSQLCallback.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSSQLResultSet.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSSQLResultSet.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSSQLResultSetRowList.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSSQLResultSetRowList.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSStyleSheet.cpp"\r
                                >\r
                        </File>\r
                                        >\r
                                </File>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="sql"\r
+                               >\r
+                               <File\r
+                                       RelativePath="..\platform\sql\SQLAuthorizer.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\platform\sql\SQLAuthorizer.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\platform\sql\SQLValue.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\platform\sql\SQLValue.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="css"\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\bindings\js\JSCustomSQLCallback.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSCustomSQLCallback.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSCustomVersionChangeCallback.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSCustomVersionChangeCallback.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath="..\bindings\js\JSCustomXPathNSResolver.cpp"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\bindings\js\JSDatabaseCustom.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath="..\bindings\js\JSDocumentCustom.cpp"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\bindings\js\JSSQLResultSetRowListCustom.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath="..\bindings\js\JSStyleSheetCustom.cpp"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\ForwardingHeaders\wtf\Deque.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath="..\ForwardingHeaders\wtf\FastMalloc.h"\r
                                        >\r
                                </File>\r
                                >\r
                        </File>\r
                </Filter>\r
+               <Filter\r
+                       Name="storage"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\storage\Database.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\Database.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseAuthorizer.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseAuthorizer.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseCallback.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseCallback.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseTask.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseTask.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseThread.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseThread.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseTracker.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\DatabaseTracker.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\SQLCallback.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\SQLResultSet.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\SQLResultSet.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\SQLResultSetRowList.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\SQLResultSetRowList.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\storage\VersionChangeCallback.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
                <File\r
                        RelativePath="..\config.h"\r
                        >\r
index 6501196..853fbd0 100644 (file)
                1A1D13810A5325520064BF5F /* DOMXPath.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1D137F0A5325520064BF5F /* DOMXPath.mm */; };
                1A2A68230B5BEDE70002A480 /* ProgressTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A68210B5BEDE70002A480 /* ProgressTracker.cpp */; };
                1A2A68240B5BEDE70002A480 /* ProgressTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2A68220B5BEDE70002A480 /* ProgressTracker.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               1A2E6E590CC55213004A2062 /* SQLValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2E6E570CC55213004A2062 /* SQLValue.cpp */; };
+               1A2E6E5A0CC55213004A2062 /* SQLValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2E6E580CC55213004A2062 /* SQLValue.h */; };
+               1A2E6E7A0CC556D5004A2062 /* SQLAuthorizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2E6E780CC556D5004A2062 /* SQLAuthorizer.cpp */; };
+               1A2E6E7B0CC556D5004A2062 /* SQLAuthorizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2E6E790CC556D5004A2062 /* SQLAuthorizer.h */; };
                1A2E6FA40CC5795D004A2062 /* ThreadingPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2E6FA30CC5795D004A2062 /* ThreadingPthreads.cpp */; };
+               1A2E6FF50CC67855004A2062 /* VersionChangeCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2E6FF30CC67855004A2062 /* VersionChangeCallback.h */; };
+               1A2E6FF80CC6788D004A2062 /* VersionChangeCallback.idl in Resources */ = {isa = PBXBuildFile; fileRef = 1A2E6FF70CC6788D004A2062 /* VersionChangeCallback.idl */; };
+               1A2E6FFE0CC67907004A2062 /* JSVersionChangeCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2E6FFC0CC67907004A2062 /* JSVersionChangeCallback.cpp */; };
+               1A2E6FFF0CC67907004A2062 /* JSVersionChangeCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2E6FFD0CC67907004A2062 /* JSVersionChangeCallback.h */; };
+               1A2E70620CC67CAA004A2062 /* JSCustomVersionChangeCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2E70600CC67CAA004A2062 /* JSCustomVersionChangeCallback.h */; };
+               1A2E70630CC67CAA004A2062 /* JSCustomVersionChangeCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2E70610CC67CAA004A2062 /* JSCustomVersionChangeCallback.cpp */; };
                1A3178930B20A81600316987 /* SubresourceLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3178920B20A81600316987 /* SubresourceLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1A494BFA0A122F4400FDAFC1 /* JSHTMLElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A494BF80A122F4400FDAFC1 /* JSHTMLElement.cpp */; };
                1A494BFB0A122F4400FDAFC1 /* JSHTMLElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A494BF90A122F4400FDAFC1 /* JSHTMLElement.h */; };
                1ACE53EB0A8D18E70022947D /* XMLSerializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACE53E50A8D18E70022947D /* XMLSerializer.h */; };
                1ACE53F60A8D19470022947D /* JSXMLSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE53F40A8D19470022947D /* JSXMLSerializer.cpp */; };
                1ACE53F70A8D19470022947D /* JSXMLSerializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACE53F50A8D19470022947D /* JSXMLSerializer.h */; };
+               1AD51A140CB59CD300953D11 /* DatabaseTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AD51A120CB59CD300953D11 /* DatabaseTracker.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               1AD51A150CB59CD300953D11 /* DatabaseTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AD51A130CB59CD300953D11 /* DatabaseTracker.cpp */; };
                1AE2AA1E0A1CDAB400B42B25 /* JSHTMLAreaElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE2AA0A0A1CDAB300B42B25 /* JSHTMLAreaElement.cpp */; };
                1AE2AA1F0A1CDAB400B42B25 /* JSHTMLAreaElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE2AA0B0A1CDAB300B42B25 /* JSHTMLAreaElement.h */; };
                1AE2AA200A1CDAB400B42B25 /* JSHTMLBaseFontElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE2AA0C0A1CDAB300B42B25 /* JSHTMLBaseFontElement.cpp */; };
                1AE2AEE70A1D2A7500B42B25 /* JSHTMLBlockquoteElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE2AEE50A1D2A7500B42B25 /* JSHTMLBlockquoteElement.h */; };
                1AE42F6A0AA4B8CB00C8612D /* StringCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE42F680AA4B8CB00C8612D /* StringCF.cpp */; };
                1AE42F6B0AA4B8CB00C8612D /* StringImplCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE42F690AA4B8CB00C8612D /* StringImplCF.cpp */; };
+               1AE82F8F0CAAFA9D002237AE /* JSDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE82F8D0CAAFA9D002237AE /* JSDatabase.cpp */; };
+               1AE82F900CAAFA9D002237AE /* JSDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE82F8E0CAAFA9D002237AE /* JSDatabase.h */; };
+               1AE82FEC0CAB07EE002237AE /* JSSQLResultSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE82FEA0CAB07EE002237AE /* JSSQLResultSet.cpp */; };
+               1AE82FED0CAB07EE002237AE /* JSSQLResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE82FEB0CAB07EE002237AE /* JSSQLResultSet.h */; };
+               1AE8301D0CAB0999002237AE /* JSSQLCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE8301B0CAB0999002237AE /* JSSQLCallback.cpp */; };
+               1AE8301E0CAB0999002237AE /* JSSQLCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE8301C0CAB0999002237AE /* JSSQLCallback.h */; };
+               1AE830440CAB0ED1002237AE /* JSDatabaseCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE830420CAB0ED1002237AE /* JSDatabaseCustom.cpp */; };
+               1AE831060CAB166E002237AE /* JSCustomSQLCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE831040CAB166E002237AE /* JSCustomSQLCallback.h */; };
+               1AE831070CAB166E002237AE /* JSCustomSQLCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE831050CAB166E002237AE /* JSCustomSQLCallback.cpp */; };
+               1AFE117D0CBFFB36003017FA /* SQLResultSetRowList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFE117B0CBFFB36003017FA /* SQLResultSetRowList.cpp */; };
+               1AFE117E0CBFFB36003017FA /* SQLResultSetRowList.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AFE117C0CBFFB36003017FA /* SQLResultSetRowList.h */; };
+               1AFE118D0CBFFC4E003017FA /* SQLResultSetRowList.idl in Resources */ = {isa = PBXBuildFile; fileRef = 1AFE118C0CBFFC4E003017FA /* SQLResultSetRowList.idl */; };
+               1AFE11990CBFFCC4003017FA /* JSSQLResultSetRowList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFE11970CBFFCC4003017FA /* JSSQLResultSetRowList.cpp */; };
+               1AFE119A0CBFFCC4003017FA /* JSSQLResultSetRowList.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AFE11980CBFFCC4003017FA /* JSSQLResultSetRowList.h */; };
                1C11CCB50AA6093700DADB20 /* DOMNotation.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 85CA96E80A9624E900690CCF /* DOMNotation.h */; };
                1C11CCB60AA6093700DADB20 /* DOMComment.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 85089CD10A98C42700A275AA /* DOMComment.h */; };
                1C11CCB70AA6093700DADB20 /* DOMNamedNodeMap.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 8518DD760A9CF31B0091B7A6 /* DOMNamedNodeMap.h */; };
                513F14540AB634C400094DDF /* IconLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 513F14520AB634C400094DDF /* IconLoader.h */; };
                514B3F730C722047000530DF /* FileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 514B3F720C722047000530DF /* FileSystem.h */; };
                514B3F760C722055000530DF /* FileSystemMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 514B3F750C722055000530DF /* FileSystemMac.mm */; };
+               5160300B0CC4251200C8AC25 /* FileSystemPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5160300A0CC4251200C8AC25 /* FileSystemPOSIX.cpp */; };
+               5160306C0CC4362300C8AC25 /* FileSystemCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5160306B0CC4362300C8AC25 /* FileSystemCF.cpp */; };
                5160F3BC0B0A99C900C1D2AF /* CachedPageMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160F3BB0B0A99C900C1D2AF /* CachedPageMac.mm */; };
                5160F4980B0AA75F00C1D2AF /* HistoryItemMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160F4970B0AA75F00C1D2AF /* HistoryItemMac.mm */; };
                51741D0F0B07259A00ED442C /* BackForwardList.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0B0B07259A00ED442C /* BackForwardList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51741D100B07259A00ED442C /* BackForwardList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51741D0C0B07259A00ED442C /* BackForwardList.cpp */; };
                51741D110B07259A00ED442C /* HistoryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0D0B07259A00ED442C /* HistoryItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51741D120B07259A00ED442C /* HistoryItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51741D0E0B07259A00ED442C /* HistoryItem.cpp */; };
+               5196116A0CAC56570010A80C /* Database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5196115E0CAC56570010A80C /* Database.cpp */; };
+               5196116B0CAC56570010A80C /* Database.h in Headers */ = {isa = PBXBuildFile; fileRef = 5196115F0CAC56570010A80C /* Database.h */; };
+               5196116D0CAC56570010A80C /* DatabaseThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 519611610CAC56570010A80C /* DatabaseThread.cpp */; };
+               519611710CAC56570010A80C /* SQLCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 519611650CAC56570010A80C /* SQLCallback.h */; };
+               519611730CAC56570010A80C /* SQLResultSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 519611670CAC56570010A80C /* SQLResultSet.cpp */; };
+               519611740CAC56570010A80C /* SQLResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 519611680CAC56570010A80C /* SQLResultSet.h */; };
+               519611780CAC56A80010A80C /* DatabaseThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 519611620CAC56570010A80C /* DatabaseThread.h */; };
+               519611EA0CAC749C0010A80C /* DatabaseTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 519611E80CAC749C0010A80C /* DatabaseTask.h */; };
+               519611EB0CAC749C0010A80C /* DatabaseTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 519611E90CAC749C0010A80C /* DatabaseTask.cpp */; };
+               51A45B560CAD7FD7000D2BE9 /* DatabaseAuthorizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */; };
+               51A45B570CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */; };
                51AA3F6F0BD5AA9E00892971 /* ResourceLoaderMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51AA3F6E0BD5AA9E00892971 /* ResourceLoaderMac.mm */; };
                51C81B890C4422F70019ECE3 /* FTPDirectoryParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51C81B870C4422F70019ECE3 /* FTPDirectoryParser.cpp */; };
                51C81B8A0C4422F70019ECE3 /* FTPDirectoryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */; };
                51D3EA160A3D24D300BADA35 /* SQLDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D3EA130A3D24D300BADA35 /* SQLDatabase.cpp */; };
                51D3EA170A3D24D300BADA35 /* SQLDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 51D3EA140A3D24D300BADA35 /* SQLDatabase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51D3EA180A3D24D300BADA35 /* SQLStatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D3EA150A3D24D300BADA35 /* SQLStatement.cpp */; };
+               51DCE8020CAC9F1C00488358 /* JSSQLResultSetRowListCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51DCE8010CAC9F1C00488358 /* JSSQLResultSetRowListCustom.cpp */; };
                51DF6D7E0B92A16D00C2DC85 /* ThreadCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 51DF6D7D0B92A16D00C2DC85 /* ThreadCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51DF6D800B92A18E00C2DC85 /* ThreadCheck.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51DF6D7F0B92A18E00C2DC85 /* ThreadCheck.mm */; };
                51E1ECAF0C91C54600DC255B /* AutodrainedPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51E1ECAD0C91C54600DC255B /* AutodrainedPool.mm */; };
                51E1ECC30C91C90400DC255B /* PageURLRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E1ECBD0C91C90400DC255B /* PageURLRecord.h */; };
                51E4ADB60C42B4CF0042BC55 /* FTPDirectoryDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51E4ADB20C42B4CF0042BC55 /* FTPDirectoryDocument.cpp */; };
                51E4ADB70C42B4CF0042BC55 /* FTPDirectoryDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E4ADB30C42B4CF0042BC55 /* FTPDirectoryDocument.h */; };
+               51EC054F0CC6A615001DA88F /* DatabaseCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EC054E0CC6A615001DA88F /* DatabaseCallback.h */; };
+               51EC05510CC6ACBA001DA88F /* DatabaseCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC05500CC6ACBA001DA88F /* DatabaseCallback.cpp */; };
                51F11E150A48C2920034A24E /* SQLTransaction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F11E140A48C2920034A24E /* SQLTransaction.cpp */; };
                550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 550A0BC7085F6039007353D6 /* QualifiedName.cpp */; };
                550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */ = {isa = PBXBuildFile; fileRef = 550A0BC8085F6039007353D6 /* QualifiedName.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1A1D137F0A5325520064BF5F /* DOMXPath.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMXPath.mm; sourceTree = "<group>"; };
                1A2A68210B5BEDE70002A480 /* ProgressTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProgressTracker.cpp; sourceTree = "<group>"; };
                1A2A68220B5BEDE70002A480 /* ProgressTracker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProgressTracker.h; sourceTree = "<group>"; };
+               1A2E6E570CC55213004A2062 /* SQLValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SQLValue.cpp; path = sql/SQLValue.cpp; sourceTree = "<group>"; };
+               1A2E6E580CC55213004A2062 /* SQLValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLValue.h; path = sql/SQLValue.h; sourceTree = "<group>"; };
+               1A2E6E780CC556D5004A2062 /* SQLAuthorizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SQLAuthorizer.cpp; path = sql/SQLAuthorizer.cpp; sourceTree = "<group>"; };
+               1A2E6E790CC556D5004A2062 /* SQLAuthorizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLAuthorizer.h; path = sql/SQLAuthorizer.h; sourceTree = "<group>"; };
                1A2E6FA30CC5795D004A2062 /* ThreadingPthreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadingPthreads.cpp; path = pthreads/ThreadingPthreads.cpp; sourceTree = "<group>"; };
+               1A2E6FF30CC67855004A2062 /* VersionChangeCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionChangeCallback.h; sourceTree = "<group>"; };
+               1A2E6FF70CC6788D004A2062 /* VersionChangeCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VersionChangeCallback.idl; sourceTree = "<group>"; };
+               1A2E6FFC0CC67907004A2062 /* JSVersionChangeCallback.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = JSVersionChangeCallback.cpp; sourceTree = "<group>"; };
+               1A2E6FFD0CC67907004A2062 /* JSVersionChangeCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVersionChangeCallback.h; sourceTree = "<group>"; };
+               1A2E70600CC67CAA004A2062 /* JSCustomVersionChangeCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomVersionChangeCallback.h; sourceTree = "<group>"; };
+               1A2E70610CC67CAA004A2062 /* JSCustomVersionChangeCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomVersionChangeCallback.cpp; sourceTree = "<group>"; };
                1A3178920B20A81600316987 /* SubresourceLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubresourceLoaderClient.h; sourceTree = "<group>"; };
                1A494BBB0A122DCD00FDAFC1 /* HTMLElement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLElement.idl; sourceTree = "<group>"; };
                1A494BF80A122F4400FDAFC1 /* JSHTMLElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLElement.cpp; sourceTree = "<group>"; };
                1ACE53E60A8D18E70022947D /* XMLSerializer.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = XMLSerializer.idl; sourceTree = "<group>"; };
                1ACE53F40A8D19470022947D /* JSXMLSerializer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSXMLSerializer.cpp; sourceTree = "<group>"; };
                1ACE53F50A8D19470022947D /* JSXMLSerializer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSXMLSerializer.h; sourceTree = "<group>"; };
+               1AD51A120CB59CD300953D11 /* DatabaseTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseTracker.h; sourceTree = "<group>"; };
+               1AD51A130CB59CD300953D11 /* DatabaseTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseTracker.cpp; sourceTree = "<group>"; };
                1AE2A9F00A1CDA5700B42B25 /* HTMLAreaElement.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = HTMLAreaElement.idl; sourceTree = "<group>"; };
                1AE2A9F10A1CDA5700B42B25 /* HTMLBaseFontElement.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = HTMLBaseFontElement.idl; sourceTree = "<group>"; };
                1AE2A9F20A1CDA5700B42B25 /* HTMLBodyElement.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = HTMLBodyElement.idl; sourceTree = "<group>"; };
                1AE2AEE50A1D2A7500B42B25 /* JSHTMLBlockquoteElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLBlockquoteElement.h; sourceTree = "<group>"; };
                1AE42F680AA4B8CB00C8612D /* StringCF.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StringCF.cpp; sourceTree = "<group>"; };
                1AE42F690AA4B8CB00C8612D /* StringImplCF.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StringImplCF.cpp; sourceTree = "<group>"; };
+               1AE82F8D0CAAFA9D002237AE /* JSDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabase.cpp; sourceTree = "<group>"; };
+               1AE82F8E0CAAFA9D002237AE /* JSDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDatabase.h; sourceTree = "<group>"; };
+               1AE82FEA0CAB07EE002237AE /* JSSQLResultSet.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = JSSQLResultSet.cpp; sourceTree = "<group>"; };
+               1AE82FEB0CAB07EE002237AE /* JSSQLResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLResultSet.h; sourceTree = "<group>"; };
+               1AE8301B0CAB0999002237AE /* JSSQLCallback.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = JSSQLCallback.cpp; sourceTree = "<group>"; };
+               1AE8301C0CAB0999002237AE /* JSSQLCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLCallback.h; sourceTree = "<group>"; };
+               1AE830420CAB0ED1002237AE /* JSDatabaseCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabaseCustom.cpp; sourceTree = "<group>"; };
+               1AE831040CAB166E002237AE /* JSCustomSQLCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomSQLCallback.h; sourceTree = "<group>"; };
+               1AE831050CAB166E002237AE /* JSCustomSQLCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLCallback.cpp; sourceTree = "<group>"; };
+               1AFE117B0CBFFB36003017FA /* SQLResultSetRowList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLResultSetRowList.cpp; sourceTree = "<group>"; };
+               1AFE117C0CBFFB36003017FA /* SQLResultSetRowList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLResultSetRowList.h; sourceTree = "<group>"; };
+               1AFE118C0CBFFC4E003017FA /* SQLResultSetRowList.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLResultSetRowList.idl; sourceTree = "<group>"; };
+               1AFE11970CBFFCC4003017FA /* JSSQLResultSetRowList.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = JSSQLResultSetRowList.cpp; sourceTree = "<group>"; };
+               1AFE11980CBFFCC4003017FA /* JSSQLResultSetRowList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLResultSetRowList.h; sourceTree = "<group>"; };
                1C14E7690AD8C81C00B6158B /* deleteButtonPressed.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = deleteButtonPressed.tiff; sourceTree = "<group>"; };
                1C14E76A0AD8C81C00B6158B /* deleteButton.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = deleteButton.tiff; sourceTree = "<group>"; };
                1C4C8EFF0AD85D87009475CE /* DeleteButtonController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeleteButtonController.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                514B3F750C722055000530DF /* FileSystemMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileSystemMac.mm; sourceTree = "<group>"; };
                5150C2A10702629000AF642C /* WebDashboardRegion.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebDashboardRegion.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                5150C2A50702629800AF642C /* WebDashboardRegion.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebDashboardRegion.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+               5160300A0CC4251200C8AC25 /* FileSystemPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystemPOSIX.cpp; sourceTree = "<group>"; };
+               5160306B0CC4362300C8AC25 /* FileSystemCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystemCF.cpp; sourceTree = "<group>"; };
                5160F3BB0B0A99C900C1D2AF /* CachedPageMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CachedPageMac.mm; path = mac/CachedPageMac.mm; sourceTree = "<group>"; };
                5160F4970B0AA75F00C1D2AF /* HistoryItemMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = HistoryItemMac.mm; path = mac/HistoryItemMac.mm; sourceTree = "<group>"; };
                51741D0B0B07259A00ED442C /* BackForwardList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardList.h; sourceTree = "<group>"; };
                51741D0C0B07259A00ED442C /* BackForwardList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackForwardList.cpp; sourceTree = "<group>"; };
                51741D0D0B07259A00ED442C /* HistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HistoryItem.h; sourceTree = "<group>"; };
                51741D0E0B07259A00ED442C /* HistoryItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HistoryItem.cpp; sourceTree = "<group>"; };
+               5196115E0CAC56570010A80C /* Database.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Database.cpp; sourceTree = "<group>"; };
+               5196115F0CAC56570010A80C /* Database.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = "<group>"; };
+               519611600CAC56570010A80C /* Database.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Database.idl; sourceTree = "<group>"; };
+               519611610CAC56570010A80C /* DatabaseThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseThread.cpp; sourceTree = "<group>"; };
+               519611620CAC56570010A80C /* DatabaseThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseThread.h; sourceTree = "<group>"; };
+               519611650CAC56570010A80C /* SQLCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLCallback.h; sourceTree = "<group>"; };
+               519611660CAC56570010A80C /* SQLCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLCallback.idl; sourceTree = "<group>"; };
+               519611670CAC56570010A80C /* SQLResultSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLResultSet.cpp; sourceTree = "<group>"; };
+               519611680CAC56570010A80C /* SQLResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLResultSet.h; sourceTree = "<group>"; };
+               519611690CAC56570010A80C /* SQLResultSet.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLResultSet.idl; sourceTree = "<group>"; };
+               519611E80CAC749C0010A80C /* DatabaseTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseTask.h; sourceTree = "<group>"; };
+               519611E90CAC749C0010A80C /* DatabaseTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseTask.cpp; sourceTree = "<group>"; };
+               51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseAuthorizer.h; sourceTree = "<group>"; };
+               51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseAuthorizer.cpp; sourceTree = "<group>"; };
                51AA3F6E0BD5AA9E00892971 /* ResourceLoaderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceLoaderMac.mm; sourceTree = "<group>"; };
                51C81B870C4422F70019ECE3 /* FTPDirectoryParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FTPDirectoryParser.cpp; sourceTree = "<group>"; };
                51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FTPDirectoryParser.h; sourceTree = "<group>"; };
                51D3EA130A3D24D300BADA35 /* SQLDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SQLDatabase.cpp; sourceTree = "<group>"; };
                51D3EA140A3D24D300BADA35 /* SQLDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SQLDatabase.h; sourceTree = "<group>"; };
                51D3EA150A3D24D300BADA35 /* SQLStatement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SQLStatement.cpp; sourceTree = "<group>"; };
+               51DCE8010CAC9F1C00488358 /* JSSQLResultSetRowListCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSQLResultSetRowListCustom.cpp; sourceTree = "<group>"; };
                51DF6D7D0B92A16D00C2DC85 /* ThreadCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadCheck.h; sourceTree = "<group>"; };
                51DF6D7F0B92A18E00C2DC85 /* ThreadCheck.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ThreadCheck.mm; sourceTree = "<group>"; };
                51E1ECAD0C91C54600DC255B /* AutodrainedPool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutodrainedPool.mm; sourceTree = "<group>"; };
                51E1ECBD0C91C90400DC255B /* PageURLRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageURLRecord.h; sourceTree = "<group>"; };
                51E4ADB20C42B4CF0042BC55 /* FTPDirectoryDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FTPDirectoryDocument.cpp; sourceTree = "<group>"; };
                51E4ADB30C42B4CF0042BC55 /* FTPDirectoryDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FTPDirectoryDocument.h; sourceTree = "<group>"; };
+               51EC054E0CC6A615001DA88F /* DatabaseCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseCallback.h; sourceTree = "<group>"; };
+               51EC05500CC6ACBA001DA88F /* DatabaseCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseCallback.cpp; sourceTree = "<group>"; };
                51F11E140A48C2920034A24E /* SQLTransaction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SQLTransaction.cpp; sourceTree = "<group>"; };
                51F6A3D50663BF04004D2919 /* HTMLCanvasElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLCanvasElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                51F6A3D60663BF04004D2919 /* HTMLCanvasElement.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCanvasElement.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                65BF02180974806300C43196 /* page */,
                                BCF1A5BA097832090061A123 /* platform */,
                                F523D2F302DE443B018635CA /* rendering */,
+                               1AE82EC90CAAE177002237AE /* storage */,
                                E1F0424309839389006694EA /* xml */,
                                656580EC09D12B20000E61D7 /* Derived Sources */,
                                089C1665FE841158C02AAC07 /* Resources */,
                                14CF78A509F58CD800EB3665 /* JSCSSValue.h */,
                                A8D05FA90A23B30F005E7203 /* JSCSSValueList.cpp */,
                                A8D05FAA0A23B30F005E7203 /* JSCSSValueList.h */,
+                               1AE82F8D0CAAFA9D002237AE /* JSDatabase.cpp */,
+                               1AE82F8E0CAAFA9D002237AE /* JSDatabase.h */,
                                659DDC8009E198BA001BF3C6 /* JSDocument.cpp */,
                                659DDC8109E198BA001BF3C6 /* JSDocument.h */,
                                1A494EDC0A123F4C00FDAFC1 /* JSDocumentFragment.cpp */,
                                BCFE2F100C1B58370020235F /* JSRect.h */,
                                BCEC01C00C274DDD009F4EC9 /* JSScreen.cpp */,
                                BCEC01C10C274DDD009F4EC9 /* JSScreen.h */,
+                               1AE8301B0CAB0999002237AE /* JSSQLCallback.cpp */,
+                               1AE8301C0CAB0999002237AE /* JSSQLCallback.h */,
+                               1AE82FEA0CAB07EE002237AE /* JSSQLResultSet.cpp */,
+                               1AE82FEB0CAB07EE002237AE /* JSSQLResultSet.h */,
+                               1AFE11970CBFFCC4003017FA /* JSSQLResultSetRowList.cpp */,
+                               1AFE11980CBFFCC4003017FA /* JSSQLResultSetRowList.h */,
                                BCE013980C0BEF180043860A /* JSStyleSheet.cpp */,
                                BCE013990C0BEF180043860A /* JSStyleSheet.h */,
                                A84EBD820CB8C97700079609 /* JSStyleSheetList.cpp */,
                                1A750D5B0A90DEE1000FF215 /* JSTreeWalker.h */,
                                A86629CA09DA2B47009633A5 /* JSUIEvent.cpp */,
                                A86629C909DA2B47009633A5 /* JSUIEvent.h */,
+                               1A2E6FFC0CC67907004A2062 /* JSVersionChangeCallback.cpp */,
+                               1A2E6FFD0CC67907004A2062 /* JSVersionChangeCallback.h */,
                                65DF31F109D1CC60000BE325 /* JSWheelEvent.cpp */,
                                65DF31F209D1CC60000BE325 /* JSWheelEvent.h */,
                                656581D709D1508D000E61D7 /* JSXMLHttpRequest.lut.h */,
                        path = DerivedSources/WebCore;
                        sourceTree = BUILT_PRODUCTS_DIR;
                };
+               1A2E6E560CC551E0004A2062 /* sql */ = {
+                       isa = PBXGroup;
+                       children = (
+                               1A2E6E780CC556D5004A2062 /* SQLAuthorizer.cpp */,
+                               1A2E6E790CC556D5004A2062 /* SQLAuthorizer.h */,
+                               1A2E6E570CC55213004A2062 /* SQLValue.cpp */,
+                               1A2E6E580CC55213004A2062 /* SQLValue.h */,
+                       );
+                       name = sql;
+                       sourceTree = "<group>";
+               };
                1AE42F670AA4B8CB00C8612D /* cf */ = {
                        isa = PBXGroup;
                        children = (
                                1A98956A0AA78F80005EF5EF /* KURLCFNet.cpp */,
                                1AE42F680AA4B8CB00C8612D /* StringCF.cpp */,
                                1AE42F690AA4B8CB00C8612D /* StringImplCF.cpp */,
+                               5160306B0CC4362300C8AC25 /* FileSystemCF.cpp */,
                        );
                        path = cf;
                        sourceTree = "<group>";
                };
+               1AE82EC90CAAE177002237AE /* storage */ = {
+                       isa = PBXGroup;
+                       children = (
+                               5196115E0CAC56570010A80C /* Database.cpp */,
+                               5196115F0CAC56570010A80C /* Database.h */,
+                               519611600CAC56570010A80C /* Database.idl */,
+                               51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */,
+                               51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */,
+                               51EC05500CC6ACBA001DA88F /* DatabaseCallback.cpp */,
+                               51EC054E0CC6A615001DA88F /* DatabaseCallback.h */,
+                               519611E90CAC749C0010A80C /* DatabaseTask.cpp */,
+                               519611E80CAC749C0010A80C /* DatabaseTask.h */,
+                               519611610CAC56570010A80C /* DatabaseThread.cpp */,
+                               519611620CAC56570010A80C /* DatabaseThread.h */,
+                               1AD51A130CB59CD300953D11 /* DatabaseTracker.cpp */,
+                               1AD51A120CB59CD300953D11 /* DatabaseTracker.h */,
+                               519611650CAC56570010A80C /* SQLCallback.h */,
+                               519611660CAC56570010A80C /* SQLCallback.idl */,
+                               519611670CAC56570010A80C /* SQLResultSet.cpp */,
+                               519611680CAC56570010A80C /* SQLResultSet.h */,
+                               519611690CAC56570010A80C /* SQLResultSet.idl */,
+                               1AFE117B0CBFFB36003017FA /* SQLResultSetRowList.cpp */,
+                               1AFE117C0CBFFB36003017FA /* SQLResultSetRowList.h */,
+                               1AFE118C0CBFFC4E003017FA /* SQLResultSetRowList.idl */,
+                               1A2E6FF30CC67855004A2062 /* VersionChangeCallback.h */,
+                               1A2E6FF70CC6788D004A2062 /* VersionChangeCallback.idl */,
+                       );
+                       indentWidth = 4;
+                       path = storage;
+                       sourceTree = "<group>";
+                       tabWidth = 8;
+                       usesTabs = 0;
+               };
                1CDD44660BA9C80000F90147 /* Configurations */ = {
                        isa = PBXGroup;
                        children = (
                        name = pthreads;
                        sourceTree = "<group>";
                };
+               516030090CC4245400C8AC25 /* posix */ = {
+                       isa = PBXGroup;
+                       children = (
+                               5160300A0CC4251200C8AC25 /* FileSystemPOSIX.cpp */,
+                       );
+                       path = posix;
+                       sourceTree = "<group>";
+               };
                5160F4920B0AA71500C1D2AF /* mac */ = {
                        isa = PBXGroup;
                        children = (
                                93F8B3060A300FEA00F61AB8 /* CodeGeneratorJS.pm */,
                                1432E8480C51493F00B1500F /* GCController.cpp */,
                                1432E8460C51493800B1500F /* GCController.h */,
+                               1AE831050CAB166E002237AE /* JSCustomSQLCallback.cpp */,
+                               1AE831040CAB166E002237AE /* JSCustomSQLCallback.h */,
+                               1A2E70610CC67CAA004A2062 /* JSCustomVersionChangeCallback.cpp */,
+                               1A2E70600CC67CAA004A2062 /* JSCustomVersionChangeCallback.h */,
                                E10B93C20B73C291003ED890 /* JSCustomXPathNSResolver.cpp */,
                                E10B937B0B73C00A003ED890 /* JSCustomXPathNSResolver.h */,
                                BCD9C2680C17AA81005C90A2 /* JSDOMExceptionConstructor.cpp */,
                                BC46C1ED0C0DDBDF0020CFC3 /* JSCSSRuleCustom.cpp */,
                                BC5825F20C0B89380053F1B5 /* JSCSSStyleDeclarationCustom.cpp */,
                                BC20FB7E0C0E8E6C00D1447F /* JSCSSValueCustom.cpp */,
+                               1AE830420CAB0ED1002237AE /* JSDatabaseCustom.cpp */,
                                929264760B61FC7200B41D34 /* JSDocumentCustom.cpp */,
                                BCD9C25E0C17AA67005C90A2 /* JSDOMWindowCustom.cpp */,
                                BC2ED5540C6B9BD300920BFF /* JSElementCustom.cpp */,
                                BCB773600C17853D00132BA4 /* JSNodeFilterCustom.cpp */,
                                1A750DD30A90E729000FF215 /* JSNodeIteratorCustom.cpp */,
                                BCD9C2610C17AA67005C90A2 /* JSNodeListCustom.cpp */,
+                               51DCE8010CAC9F1C00488358 /* JSSQLResultSetRowListCustom.cpp */,
                                BC98A27C0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp */,
                                A84EBD770CB8C89200079609 /* JSStyleSheetListCustom.cpp */,
                                B25DFAAE0B2E2929000E6510 /* JSSVGMatrixCustom.cpp */,
                                B2A015910AF6CD53006BCE0E /* graphics */,
                                6582A14809999D6C00BEEB6D /* mac */,
                                656B84D70AEA1CE900A095B4 /* network */,
+                               516030090CC4245400C8AC25 /* posix */,
                                5154498E0CAA35F600194B2D /* pthreads */,
+                               1A2E6E560CC551E0004A2062 /* sql */,
                                BCFB2F74097A2E1A00BA703D /* Arena.cpp */,
                                BCFB2F75097A2E1A00BA703D /* Arena.h */,
                                BCB16B890979B01400467741 /* ArrayImpl.cpp */,
                                51E1ECC10C91C90400DC255B /* IconRecord.h in Headers */,
                                51E1ECC30C91C90400DC255B /* PageURLRecord.h in Headers */,
                                0A4844990CA44CB200B7BD48 /* SoftLinking.h in Headers */,
+                               1AE82F900CAAFA9D002237AE /* JSDatabase.h in Headers */,
+                               1AE82FED0CAB07EE002237AE /* JSSQLResultSet.h in Headers */,
+                               1AE8301E0CAB0999002237AE /* JSSQLCallback.h in Headers */,
+                               1AE831060CAB166E002237AE /* JSCustomSQLCallback.h in Headers */,
+                               5196116B0CAC56570010A80C /* Database.h in Headers */,
+                               519611710CAC56570010A80C /* SQLCallback.h in Headers */,
+                               519611740CAC56570010A80C /* SQLResultSet.h in Headers */,
+                               519611780CAC56A80010A80C /* DatabaseThread.h in Headers */,
+                               519611EA0CAC749C0010A80C /* DatabaseTask.h in Headers */,
+                               51A45B560CAD7FD7000D2BE9 /* DatabaseAuthorizer.h in Headers */,
+                               1AD51A140CB59CD300953D11 /* DatabaseTracker.h in Headers */,
+                               1AFE117E0CBFFB36003017FA /* SQLResultSetRowList.h in Headers */,
+                               1AFE119A0CBFFCC4003017FA /* JSSQLResultSetRowList.h in Headers */,
                                A8F4FB940C169E7B002AFED5 /* SVGRenderSupport.h in Headers */,
                                AA31B5B50C1DFD1000AE7083 /* RenderSVGRoot.h in Headers */,
                                B266CD4E0C3AEC6500EB08D2 /* JSSVGException.h in Headers */,
                                A8A909AC0CBCD6B50029B807 /* RenderSVGTransformableContainer.h in Headers */,
                                BC9ADD230CC4032600098C4C /* CSSTransformValue.h in Headers */,
                                E1ED8AC30CC49BE000BFC557 /* CSSPrimitiveValueMappings.h in Headers */,
+                               1A2E6E5A0CC55213004A2062 /* SQLValue.h in Headers */,
+                               1A2E6E7B0CC556D5004A2062 /* SQLAuthorizer.h in Headers */,
+                               1A2E6FF50CC67855004A2062 /* VersionChangeCallback.h in Headers */,
+                               1A2E6FFF0CC67907004A2062 /* JSVersionChangeCallback.h in Headers */,
+                               1A2E70620CC67CAA004A2062 /* JSCustomVersionChangeCallback.h in Headers */,
+                               51EC054F0CC6A615001DA88F /* DatabaseCallback.h in Headers */,
                                BC014C750CC5579D009C4B20 /* SecurityOrigin.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
                                06693F7B0BFBC91700216072 /* inspector in Resources */,
                                1AB1AE7A0C051FDE00139F4F /* zoomInCursor.png in Resources */,
                                1AB1AE7B0C051FDE00139F4F /* zoomOutCursor.png in Resources */,
+                               1AFE118D0CBFFC4E003017FA /* SQLResultSetRowList.idl in Resources */,
+                               1A2E6FF80CC6788D004A2062 /* VersionChangeCallback.idl in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                51E1ECB00C91C54600DC255B /* Threading.mm in Sources */,
                                51E1ECC00C91C90400DC255B /* IconRecord.cpp in Sources */,
                                51E1ECC20C91C90400DC255B /* PageURLRecord.cpp in Sources */,
+                               1AE82F8F0CAAFA9D002237AE /* JSDatabase.cpp in Sources */,
+                               1AE82FEC0CAB07EE002237AE /* JSSQLResultSet.cpp in Sources */,
+                               1AE8301D0CAB0999002237AE /* JSSQLCallback.cpp in Sources */,
+                               1AE830440CAB0ED1002237AE /* JSDatabaseCustom.cpp in Sources */,
+                               1AE831070CAB166E002237AE /* JSCustomSQLCallback.cpp in Sources */,
+                               5196116A0CAC56570010A80C /* Database.cpp in Sources */,
+                               5196116D0CAC56570010A80C /* DatabaseThread.cpp in Sources */,
+                               519611730CAC56570010A80C /* SQLResultSet.cpp in Sources */,
+                               519611EB0CAC749C0010A80C /* DatabaseTask.cpp in Sources */,
+                               51DCE8020CAC9F1C00488358 /* JSSQLResultSetRowListCustom.cpp in Sources */,
+                               51A45B570CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp in Sources */,
+                               1AD51A150CB59CD300953D11 /* DatabaseTracker.cpp in Sources */,
+                               1AFE117D0CBFFB36003017FA /* SQLResultSetRowList.cpp in Sources */,
+                               1AFE11990CBFFCC4003017FA /* JSSQLResultSetRowList.cpp in Sources */,
+                               5160300B0CC4251200C8AC25 /* FileSystemPOSIX.cpp in Sources */,
+                               5160306C0CC4362300C8AC25 /* FileSystemCF.cpp in Sources */,
                                A8F4FB960C169E85002AFED5 /* SVGRenderSupport.cpp in Sources */,
                                AA31B5B40C1DFD1000AE7083 /* RenderSVGRoot.cpp in Sources */,
                                B2D3FC8A0C2212CB00CF3618 /* JSSVGTransformListCustom.cpp in Sources */,
                                A84EC1390CB9FDBC00079609 /* SVGCSSComputedStyleDeclaration.cpp in Sources */,
                                A8A909AD0CBCD6B50029B807 /* RenderSVGTransformableContainer.cpp in Sources */,
                                BC9ADD800CC4092200098C4C /* CSSTransformValue.cpp in Sources */,
+                               1A2E6E590CC55213004A2062 /* SQLValue.cpp in Sources */,
+                               1A2E6E7A0CC556D5004A2062 /* SQLAuthorizer.cpp in Sources */,
                                1A2E6FA40CC5795D004A2062 /* ThreadingPthreads.cpp in Sources */,
+                               1A2E6FFE0CC67907004A2062 /* JSVersionChangeCallback.cpp in Sources */,
+                               1A2E70630CC67CAA004A2062 /* JSCustomVersionChangeCallback.cpp in Sources */,
+                               51EC05510CC6ACBA001DA88F /* DatabaseCallback.cpp in Sources */,
                                BC014C740CC5579D009C4B20 /* SecurityOrigin.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
diff --git a/WebCore/bindings/js/JSCustomSQLCallback.cpp b/WebCore/bindings/js/JSCustomSQLCallback.cpp
new file mode 100644 (file)
index 0000000..c4a122e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2007 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 "JSCustomSQLCallback.h"
+
+#include "CString.h"
+#include "Frame.h"
+#include "kjs_proxy.h"
+#include "JSSQLResultSet.h"
+#include "Page.h"
+
+namespace WebCore {
+
+using namespace KJS;
+
+JSCustomSQLCallback::JSCustomSQLCallback(JSObject* callback, Frame* frame)
+    : m_callback(callback)
+    , m_frame(frame)
+{
+
+}
+
+void JSCustomSQLCallback::handleEvent(SQLResultSet* resultSet)
+{
+    ASSERT(m_callback);
+    ASSERT(m_frame);
+
+    KJSProxy* proxy = m_frame->scriptProxy();
+    if (!proxy)
+        return;
+
+    ScriptInterpreter* interpreter = proxy->interpreter();
+    ExecState* exec = interpreter->globalExec();
+
+    KJS::JSLock lock;
+
+    JSValue* handleEventFuncValue = m_callback->get(exec, "handleEvent");
+    JSObject* handleEventFunc = 0;
+    if (handleEventFuncValue->isObject()) {
+        handleEventFunc = static_cast<JSObject*>(handleEventFuncValue);
+        if (!handleEventFunc->implementsCall())
+            handleEventFunc = 0;
+    }
+
+    if (!handleEventFunc && !m_callback->implementsCall()) {
+        // FIXME: Should an exception be thrown here?
+        return;
+    }
+
+    RefPtr<JSCustomSQLCallback> protect(this);
+
+    List args;
+    args.append(toJS(exec, resultSet));
+
+    interpreter->startTimeoutCheck();
+    if (handleEventFunc)
+        handleEventFunc->call(exec, m_callback, args);
+    else
+        m_callback->call(exec, m_callback, args);
+    interpreter->stopTimeoutCheck();
+
+    if (exec->hadException()) {
+        JSObject* exception = exec->exception()->toObject(exec);
+        String message = exception->get(exec, exec->propertyNames().message)->toString(exec);
+        int lineNumber = exception->get(exec, "line")->toInt32(exec);
+        String sourceURL = exception->get(exec, "sourceURL")->toString(exec);
+        if (Interpreter::shouldPrintExceptions())
+            printf("SQLCallback: %s\n", message.utf8().data());
+        if (Page* page = m_frame->page())
+            page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, lineNumber, sourceURL);
+        exec->clearException();
+    }
+
+    Document::updateDocumentsRendering();
+}
+
+}
diff --git a/WebCore/bindings/js/JSCustomSQLCallback.h b/WebCore/bindings/js/JSCustomSQLCallback.h
new file mode 100644 (file)
index 0000000..7b881b4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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 "SQLCallback.h"
+
+#include <kjs/object.h>
+#include <kjs/protect.h>
+#include <wtf/Forward.h>
+
+namespace KJS {
+    class JSObject;
+}
+
+namespace WebCore {
+
+class Frame;
+class SQLResultSet;
+
+class JSCustomSQLCallback : public SQLCallback {
+public:
+    JSCustomSQLCallback(KJS::JSObject* callback, Frame*);
+
+    virtual void handleEvent(SQLResultSet*);
+private:
+    KJS::ProtectedPtr<KJS::JSObject> m_callback;
+    RefPtr<Frame> m_frame;
+};
+
+}
diff --git a/WebCore/bindings/js/JSCustomVersionChangeCallback.cpp b/WebCore/bindings/js/JSCustomVersionChangeCallback.cpp
new file mode 100644 (file)
index 0000000..6d30479
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2007 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 "JSCustomVersionChangeCallback.h"
+
+#include "CString.h"
+#include "Frame.h"
+#include "kjs_proxy.h"
+#include "JSSQLResultSet.h"
+#include "Page.h"
+
+namespace WebCore {
+
+using namespace KJS;
+
+JSCustomVersionChangeCallback::JSCustomVersionChangeCallback(JSObject* callback, Frame* frame)
+    : m_callback(callback)
+    , m_frame(frame)
+{
+
+}
+
+void JSCustomVersionChangeCallback::handleEvent(bool versionChanged)
+{
+    ASSERT(m_callback);
+    ASSERT(m_frame);
+
+    KJSProxy* proxy = m_frame->scriptProxy();
+    if (!proxy)
+        return;
+
+    ScriptInterpreter* interpreter = proxy->interpreter();
+    ExecState* exec = interpreter->globalExec();
+
+    KJS::JSLock lock;
+
+    JSValue* handleEventFuncValue = m_callback->get(exec, "handleEvent");
+    JSObject* handleEventFunc = 0;
+    if (handleEventFuncValue->isObject()) {
+        handleEventFunc = static_cast<JSObject*>(handleEventFuncValue);
+        if (!handleEventFunc->implementsCall())
+            handleEventFunc = 0;
+    }
+
+    if (!handleEventFunc && !m_callback->implementsCall()) {
+        // FIXME: Should an exception be thrown here?
+        return;
+    }
+
+    RefPtr<JSCustomVersionChangeCallback> protect(this);
+
+    List args;
+    args.append(jsBoolean(versionChanged));
+
+    interpreter->startTimeoutCheck();
+    if (handleEventFunc)
+        handleEventFunc->call(exec, m_callback, args);
+    else
+        m_callback->call(exec, m_callback, args);
+    interpreter->stopTimeoutCheck();
+
+    if (exec->hadException()) {
+        JSObject* exception = exec->exception()->toObject(exec);
+        String message = exception->get(exec, exec->propertyNames().message)->toString(exec);
+        int lineNumber = exception->get(exec, "line")->toInt32(exec);
+        String sourceURL = exception->get(exec, "sourceURL")->toString(exec);
+        if (Interpreter::shouldPrintExceptions())
+            printf("VersionChangeCallback: %s\n", message.utf8().data());
+        if (Page* page = m_frame->page())
+            page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, lineNumber, sourceURL);
+        exec->clearException();
+    }
+
+    Document::updateDocumentsRendering();
+}
+
+}
diff --git a/WebCore/bindings/js/JSCustomVersionChangeCallback.h b/WebCore/bindings/js/JSCustomVersionChangeCallback.h
new file mode 100644 (file)
index 0000000..073e8d1
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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 "VersionChangeCallback.h"
+
+#include <kjs/object.h>
+#include <kjs/protect.h>
+#include <wtf/Forward.h>
+
+namespace KJS {
+    class JSObject;
+}
+
+namespace WebCore {
+
+    class Frame;
+    class SQLResultSet;
+
+    class JSCustomVersionChangeCallback : public VersionChangeCallback {
+    public:
+        JSCustomVersionChangeCallback(KJS::JSObject* callback, Frame*);
+
+        virtual void handleEvent(bool versionChanges);
+    private:
+        KJS::ProtectedPtr<KJS::JSObject> m_callback;
+        RefPtr<Frame> m_frame;
+    };
+
+}
diff --git a/WebCore/bindings/js/JSDatabaseCustom.cpp b/WebCore/bindings/js/JSDatabaseCustom.cpp
new file mode 100644 (file)
index 0000000..0f54fe2
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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 "JSDatabase.h"
+
+#include "Database.h"
+#include "Document.h"
+#include "DOMWindow.h"
+#include "ExceptionCode.h"
+#include "kjs_window.h"
+#include "JSCustomSQLCallback.h"
+#include "JSCustomVersionChangeCallback.h"
+#include "PlatformString.h"
+#include "SQLValue.h"
+
+namespace WebCore {
+
+using namespace KJS;
+
+JSValue* JSDatabase::executeSql(ExecState* exec, const List& args)
+{
+    // There has to be at least two arguments
+    if (args.size() < 2) {
+        setDOMException(exec, SYNTAX_ERR);
+        return jsUndefined();
+    }
+
+    String sqlStatement = args[0]->toString(exec);
+
+    // Now assemble the list of SQL arguments
+    Vector<SQLValue> SQLValues;
+
+    for (int i = 0 ; i < args.size() - 2; i++) {
+        JSValue* value = args[i + 1];
+
+        if (value->isNull()) {
+            SQLValues.append(SQLValue());
+        } else if (value->isNumber()) {
+            SQLValues.append(value->getNumber());
+        } else {
+            // Convert the argument to a string and append it
+            SQLValues.append(value->toString(exec));
+        }
+    }
+
+    // REVIEW: This checks that the last argument passed in is a JS Object
+    // (instead of a string or a number for example) and throws a type mismatch exception if it's not.
+    // Should this go into the spec?
+    JSObject* callback = args[args.size() - 1]->getObject();
+    if (!callback) {
+        setDOMException(exec, TYPE_MISMATCH_ERR);
+        return jsUndefined();
+    }
+
+    if (Frame* frame = m_impl->document()->frame()) {
+        ExceptionCode ec = 0;
+        RefPtr<SQLCallback> sqlCallback(new JSCustomSQLCallback(callback, frame));
+        m_impl->executeSql(sqlStatement, SQLValues, sqlCallback, ec);
+        setDOMException(exec, ec);
+    }
+
+    return jsUndefined();
+}
+
+JSValue* JSDatabase::changeVersion(ExecState* exec, const List& args)
+{
+    String oldVersion = args[0]->toString(exec);
+    String newVersion = args[1]->toString(exec);
+
+    JSObject* callback = args[2]->getObject();
+    if (!callback) {
+        setDOMException(exec, TYPE_MISMATCH_ERR);
+        return jsUndefined();
+    }
+
+    if (Frame* frame = m_impl->document()->frame()) {
+        RefPtr<VersionChangeCallback> changeCallback(new JSCustomVersionChangeCallback(callback, frame));
+        m_impl->changeVersion(oldVersion, newVersion, changeCallback.release());
+    }
+
+    return jsUndefined();
+}
+
+}
diff --git a/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp b/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp
new file mode 100644 (file)
index 0000000..fba0b5d
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 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 "JSSQLResultSetRowList.h"
+
+#include "ExceptionCode.h"
+#include "SQLValue.h"
+#include "SQLResultSetRowList.h"
+
+using namespace KJS;
+
+namespace WebCore {
+
+JSValue* JSSQLResultSetRowList::item(ExecState* exec, const List& args)
+{
+    bool indexOk;
+    int index = args[0]->toInt32(exec, indexOk);
+    if (!indexOk) {
+        setDOMException(exec, TYPE_MISMATCH_ERR);
+        return jsUndefined();
+    }
+    if (index < 0 || (unsigned)index >= m_impl->length()) {
+        setDOMException(exec, INDEX_SIZE_ERR);
+        return jsUndefined();
+    }
+
+    JSObject* object = new JSObject(exec->lexicalInterpreter()->builtinObjectPrototype());
+
+    unsigned numColumns = m_impl->columnNames().size();
+    unsigned valuesIndex = index * numColumns;
+    for (unsigned i = 0; i < numColumns; i++) {
+        const SQLValue& value = m_impl->values()[valuesIndex + i];
+        JSValue* jsValue = 0;
+
+        switch (value.type()) {
+            case SQLValue::StringValue:
+              jsValue = jsString(value.string());
+              break;
+          case SQLValue::NullValue:
+              jsValue = jsNull();
+              break;
+          case SQLValue::NumberValue:
+              jsValue = jsNumber(value.number());
+              break;
+          default:
+              ASSERT_NOT_REACHED();
+        }
+
+        object->put(exec, m_impl->columnNames()[i], jsValue, DontDelete | ReadOnly);
+    }
+
+    return object;
+}
+
+}
index 5699c6e..9751da9 100644 (file)
@@ -1354,6 +1354,7 @@ sub TypeCanFailConversion
                 $type eq "Range" or
                 $type eq "NodeFilter" or
                 $type eq "DOMWindow" or
+                $type eq "SQLResultSet" or
                 $type eq "XPathEvaluator" or
                 $type eq "XPathNSResolver" or
                 $type eq "XPathResult" or
index f3e3617..f00fa5d 100644 (file)
@@ -32,6 +32,7 @@
 #include "CSSValueKeywords.h"
 #include "Comment.h"
 #include "CookieJar.h"
+#include "DatabaseThread.h"
 #include "DOMImplementation.h"
 #include "DocLoader.h"
 #include "DocumentFragment.h"
@@ -284,6 +285,7 @@ Document::Document(DOMImplementation* impl, Frame* frame, bool isXHTML)
     , m_isXHTML(isXHTML)
     , m_numNodeLists(0)
 {
+    printf("Document %p being constructed\n", this);
     m_document.resetSkippingRef(this);
 
     m_printing = false;
@@ -381,6 +383,7 @@ void Document::removedLastRef()
 
 Document::~Document()
 {
+    printf("Document %p is being destroyed\n", this);
     ASSERT(!renderer());
     ASSERT(!m_inPageCache);
     ASSERT(!m_savedRenderer);
@@ -434,6 +437,12 @@ Document::~Document()
     for (unsigned i = 0; i < count; i++)
         deleteAllValues(m_nameCollectionInfo[i]);
 
+    if (m_databaseThread) {
+        printf("Destroying document %p which has a database thread\n", this);
+        m_databaseThread->documentGoingAway();
+        m_databaseThread = 0;
+    }
+
     if (m_styleSheets)
         m_styleSheets->documentDestroyed();
 }
@@ -3728,4 +3737,15 @@ void Document::updateFocusAppearanceTimerFired(Timer<Document>*)
         element->updateFocusAppearance(false);
 }
 
+DatabaseThread* Document::databaseThread()
+{
+    if (!m_databaseThread) {
+        m_databaseThread = new DatabaseThread(this);
+        if (!m_databaseThread->start())
+            m_databaseThread = 0;
+    }
+
+    return m_databaseThread.get();
+}
+
 } // namespace WebCore
index ffb8cb8..3d863e8 100644 (file)
@@ -49,6 +49,7 @@ namespace WebCore {
     class CSSStyleSelector;
     class CSSStyleSheet;
     class Comment;
+    class DatabaseThread;
     class DOMImplementation;
     class DOMWindow;
     class DocLoader;
@@ -855,6 +856,7 @@ public:
 
     bool processingLoadEvent() const { return m_processingLoadEvent; }
 
+    DatabaseThread* databaseThread();
 protected:
     void clearXMLVersion() { m_xmlVersion = String(); }
 
@@ -919,6 +921,8 @@ private:
     bool m_isXHTML;
 
     unsigned m_numNodeLists;
+
+    RefPtr<DatabaseThread> m_databaseThread;
 #if USE(LOW_BANDWIDTH_DISPLAY)
     bool m_inLowBandwidthDisplay;
 #endif
index a882003..c3ad23a 100644 (file)
@@ -117,42 +117,6 @@ void IconDatabase::setClient(IconDatabaseClient* client)
     m_client = client;
 }
 
-bool makeAllDirectories(const String& path)
-{
-#if PLATFORM(WIN_OS)
-    String fullPath = path;
-    if (!SHCreateDirectoryEx(0, fullPath.charactersWithNullTermination(), 0)) {
-        DWORD error = GetLastError();
-        if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) {
-            LOG_ERROR("Failed to create path %s", path.ascii().data());
-            return false;
-        }
-    }
-#else
-    CString fullPath = path.utf8();
-    if (!access(fullPath.data(), F_OK))
-        return true;
-        
-    char* p = fullPath.mutableData() + 1;
-    int length = fullPath.length();
-    
-    if(p[length - 1] == '/')
-        p[length - 1] = '\0';
-    for (; *p; ++p)
-        if (*p == '/') {
-            *p = '\0';
-            if (access(fullPath.data(), F_OK))
-                if (mkdir(fullPath.data(), S_IRWXU))
-                    return false;
-            *p = '/';
-        }
-    if (access(fullPath.data(), F_OK))        
-        if (mkdir(fullPath.data(), S_IRWXU))
-            return false;
-#endif   
-    return true;
-}
-
 bool IconDatabase::open(const String& databasePath)
 {
     ASSERT_NOT_SYNC_THREAD();
@@ -168,18 +132,8 @@ bool IconDatabase::open(const String& databasePath)
     m_databaseDirectory = databasePath.copy();
 
     // Formulate the full path for the database file
-#if PLATFORM(WIN_OS)
-    if (m_databaseDirectory[m_databaseDirectory.length()] == '\\')
-        m_completeDatabasePath = m_databaseDirectory + defaultDatabaseFilename();
-    else
-        m_completeDatabasePath = m_databaseDirectory + "\\" + defaultDatabaseFilename();
-#else
-    if (m_databaseDirectory[m_databaseDirectory.length()] == '/')
-        m_completeDatabasePath = m_databaseDirectory + defaultDatabaseFilename();
-    else
-        m_completeDatabasePath = m_databaseDirectory + "/" + defaultDatabaseFilename();
-#endif
-    
+    m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, defaultDatabaseFilename());
+
     initializeThreading();
 
     // Lock here as well as first thing in the thread so the tread doesn't actually commence until the pthread_create() call 
index 1ce9c52..e2d82f8 100644 (file)
 #include "SQLDatabase.h"
 
 #include "Logging.h"
-#include <sqlite3.h>
+#include "SQLAuthorizer.h"
 #include "SQLStatement.h"
 
+#include <sqlite3.h>
 
 namespace WebCore {
 
-const int SQLResultError = SQLITE_ERROR;
 const int SQLResultDone = SQLITE_DONE;
+const int SQLResultError = SQLITE_ERROR;
 const int SQLResultOk = SQLITE_OK;
 const int SQLResultRow = SQLITE_ROW;
+const int SQLResultSchema = SQLITE_SCHEMA;
+
 
 SQLDatabase::SQLDatabase()
     : m_db(0)
@@ -47,6 +50,11 @@ SQLDatabase::SQLDatabase()
 #endif
 }
 
+SQLDatabase::~SQLDatabase()
+{
+    close();
+}
+
 bool SQLDatabase::open(const String& filename)
 {
     close();
@@ -184,6 +192,107 @@ const char* SQLDatabase::lastErrorMsg()
     return sqlite3_errmsg(m_db);
 }
 
+int SQLDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/)
+{
+    SQLAuthorizer* auth = static_cast<SQLAuthorizer*>(userData);
+    ASSERT(auth);
+
+    switch (actionCode) {
+        case SQLITE_CREATE_INDEX:
+            return auth->createIndex(parameter1, parameter2);
+        case SQLITE_CREATE_TABLE:
+            return auth->createTable(parameter1);
+        case SQLITE_CREATE_TEMP_INDEX:
+            return auth->createTempIndex(parameter1, parameter2);
+        case SQLITE_CREATE_TEMP_TABLE:
+            return auth->createTempTable(parameter1);
+        case SQLITE_CREATE_TEMP_TRIGGER:
+            return auth->createTempTrigger(parameter1, parameter2);
+        case SQLITE_CREATE_TEMP_VIEW:
+            return auth->createTempView(parameter1);
+        case SQLITE_CREATE_TRIGGER:
+            return auth->createTrigger(parameter1, parameter2);
+        case SQLITE_CREATE_VIEW:
+            return auth->createView(parameter1);
+        case SQLITE_DELETE:
+            return auth->allowDelete(parameter1);
+        case SQLITE_DROP_INDEX:
+            return auth->dropIndex(parameter1, parameter2);
+        case SQLITE_DROP_TABLE:
+            return auth->dropTable(parameter1);
+        case SQLITE_DROP_TEMP_INDEX:
+            return auth->dropTempIndex(parameter1, parameter2);
+        case SQLITE_DROP_TEMP_TABLE:
+            return auth->dropTempTable(parameter1);
+        case SQLITE_DROP_TEMP_TRIGGER:
+            return auth->dropTempTrigger(parameter1, parameter2);
+        case SQLITE_DROP_TEMP_VIEW:
+            return auth->dropTempView(parameter1);
+        case SQLITE_DROP_TRIGGER:
+            return auth->dropTrigger(parameter1, parameter2);
+        case SQLITE_DROP_VIEW:
+            return auth->dropView(parameter1);
+        case SQLITE_INSERT:
+            return auth->allowInsert(parameter1);
+        case SQLITE_PRAGMA:
+            return auth->allowPragma(parameter1, parameter2);
+        case SQLITE_READ:
+            return auth->allowRead(parameter1, parameter2);
+        case SQLITE_SELECT:
+            return auth->allowSelect();
+        case SQLITE_TRANSACTION:
+            return auth->allowTransaction();
+        case SQLITE_UPDATE:
+            return auth->allowUpdate(parameter1, parameter2);
+        case SQLITE_ATTACH:
+            return auth->allowAttach(parameter1);
+        case SQLITE_DETACH:
+            return auth->allowDetach(parameter1);
+        case SQLITE_ALTER_TABLE:
+            return auth->allowAlterTable(parameter1, parameter2);
+        case SQLITE_REINDEX:
+            return auth->allowReindex(parameter1);
+        case SQLITE_ANALYZE:
+            return auth->allowAnalyze(parameter1);
+        case SQLITE_CREATE_VTABLE:
+            return auth->createVTable(parameter1, parameter2);
+        case SQLITE_DROP_VTABLE:
+            return auth->dropVTable(parameter1, parameter2);
+        case SQLITE_FUNCTION:
+            return auth->allowFunction(parameter1);
+        default:
+            ASSERT_NOT_REACHED();
+            return SQLAuthDeny;
+    }
+}
+
+void SQLDatabase::setAuthorizer(PassRefPtr<SQLAuthorizer> auth)
+{
+    if (!m_db) {
+        LOG_ERROR("Attempt to set an authorizer on a non-open SQL database");
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    MutexLocker locker(m_authorizerLock);
+
+    m_authorizer = auth;
+    if (m_authorizer)
+        sqlite3_set_authorizer(m_db, SQLDatabase::authorizerFunction, m_authorizer.get());
+    else
+        sqlite3_set_authorizer(m_db, NULL, 0);
+}
+
+void SQLDatabase::lock()
+{
+    m_lockingMutex.lock();
+}
+
+void SQLDatabase::unlock()
+{
+    m_lockingMutex.unlock();
+}
+
 } // namespace WebCore
 
 
index f91ad50..88a03bf 100644 (file)
@@ -27,6 +27,7 @@
 #define SQLDatabase_h
 
 #include "PlatformString.h"
+#include "Threading.h"
 #include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
 
@@ -42,20 +43,23 @@ typedef struct sqlite3 sqlite3;
 
 namespace WebCore {
 
+class SQLAuthorizer;
 class SQLStatement;
 class SQLTransaction;
 
-extern const int SQLResultError;
 extern const int SQLResultDone;
+extern const int SQLResultError;
 extern const int SQLResultOk;
 extern const int SQLResultRow;
+extern const int SQLResultSchema;
+
 
 class SQLDatabase : public Noncopyable
 {
 friend class SQLTransaction;
 public:
     SQLDatabase();
-    ~SQLDatabase() { close(); }
+    ~SQLDatabase();
 
     bool open(const String& filename);
     bool isOpen() const { return m_db; }
@@ -97,13 +101,24 @@ public:
         return m_db;
     }
     
+    void setAuthorizer(PassRefPtr<SQLAuthorizer>);
+
+    // (un)lock's the database like a mutex
+    void lock();
+    void unlock();
 private:
+    static int authorizerFunction(void*, int, const char*, const char*, const char*, const char*);
+
     String   m_path;
     sqlite3* m_db;
     int m_lastError;
     
     bool m_transactionInProgress;
     
+    Mutex m_authorizerLock;
+    RefPtr<SQLAuthorizer> m_authorizer;
+
+    Mutex m_lockingMutex;
 #ifndef NDEBUG
     pthread_t m_openingThread;
 #endif
index 27c4d94..6ddeaa0 100644 (file)
@@ -27,6 +27,7 @@
 #include "SQLStatement.h"
 
 #include "Logging.h"
+#include "SQLValue.h"
 #include <sqlite3.h>
 #include <wtf/Assertions.h>
 
@@ -49,7 +50,11 @@ int SQLStatement::prepare()
 {    
     const void* tail;
     LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data());
+#if SQLITE_VERSION_NUMBER > 3003000 
+    if (sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.characters(), -1, &m_statement, &tail) != SQLITE_OK) {
+#else
     if (sqlite3_prepare16(m_database.sqlite3Handle(), m_query.characters(), -1, &m_statement, &tail) != SQLITE_OK) {
+#endif
         LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", lastError(), m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle()));
         m_statement = 0;
     }
@@ -152,11 +157,38 @@ int SQLStatement::bindInt64(int index, int64_t integer)
     return sqlite3_bind_int64(m_statement, index, integer);
 }
 
+int SQLStatement::bindDouble(int index, double number)
+{
+    return sqlite3_bind_double(m_statement, index, number);
+}
+
 int SQLStatement::bindNull(int index)
 {
     return sqlite3_bind_null(m_statement, index);
 }
 
+int SQLStatement::bindValue(int index, const SQLValue& value)
+{
+    switch (value.type()) {
+        case SQLValue::StringValue:
+            return bindText16(index, value.string());
+        case SQLValue::NumberValue:
+            return bindDouble(index, value.number());
+        case SQLValue::NullValue:
+            return bindNull(index);
+        default:
+            ASSERT_NOT_REACHED();
+            // To keep the compiler happy
+            return SQLITE_ERROR;
+    }
+}
+
+unsigned SQLStatement::bindParameterCount() const
+{
+    ASSERT(isPrepared());
+    return sqlite3_bind_parameter_count(m_statement);
+}
+
 int SQLStatement::columnCount()
 {
     if (m_statement)
index 4242ccd..e0d0542 100644 (file)
@@ -35,6 +35,7 @@ typedef struct sqlite3_stmt sqlite3_stmt;
 namespace WebCore {
 
 class SQLDatabase;
+class SQLValue;
 
 class SQLStatement : public Noncopyable
 {
@@ -43,12 +44,15 @@ public:
     ~SQLStatement();
     
     int prepare();
-    bool isPrepared() { return m_statement; }
+    bool isPrepared() const { return m_statement; }
     int bindBlob(int index, const void* blob, int size, bool copy = true);
     int bindText(int index, const char* text, bool copy = true);
     int bindText16(int index, const String& text, bool copy = true);
     int bindInt64(int index, int64_t integer);
+    int bindDouble(int index, double number);
     int bindNull(int index);
+    int bindValue(int index, const SQLValue&);
+    unsigned bindParameterCount() const;
 
     int step();
     int finalize();
index 7b9e899..0213e66 100644 (file)
@@ -347,6 +347,12 @@ void Chrome::print(Frame* frame)
     m_client->print(frame);
 }
 
+bool Chrome::runDatabaseSizeLimitPrompt(Frame* f, const String& origin)
+{
+    return m_client->runDatabaseSizeLimitPrompt(f, origin);
+}
+
+
 PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
 {
     const HashSet<Page*>* group = page->frameNamespace();
index 13930e1..1c53067 100644 (file)
@@ -125,6 +125,9 @@ namespace WebCore {
 
         void print(Frame*);
 
+        bool runDatabaseSizeLimitPrompt(Frame*, const String& origin);
+
+
 #if PLATFORM(MAC)
         void focusNSView(NSView*);
 #endif
index 3913551..6f99085 100644 (file)
@@ -102,6 +102,16 @@ namespace WebCore {
         virtual void setToolTip(const String&) = 0;
 
         virtual void print(Frame*) = 0;
+
+//  Possible permission levels -
+//  -Allow just this database to be created
+//  -Allow this domain to create whatever it wants
+//  -Don't allow this database
+//  -Don't allow this domain to ever create any
+//  -Don't allow any databases
+//        virtual bool runDatabaseCreationPrompt(Frame*, const String& origin, const String& name) = 0;
+
+        virtual bool runDatabaseSizeLimitPrompt(Frame*, const String& origin) = 0;
 };
 
 }
index 4240c92..0d22da9 100644 (file)
@@ -31,6 +31,7 @@
 #include "CSSRuleList.h"
 #include "CSSStyleSelector.h"
 #include "Chrome.h"
+#include "Database.h"
 #include "DOMSelection.h"
 #include "Document.h"
 #include "Element.h"
@@ -549,4 +550,17 @@ double DOMWindow::devicePixelRatio() const
     return page->chrome()->scaleFactor();
 }
 
+PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, ExceptionCode& e)
+{
+    if (!m_frame)
+        return 0;
+
+    Document* doc = m_frame->document();
+    ASSERT(doc);
+    if (!doc)
+        return 0;
+
+    return Database::openDatabase(doc, name, version, e);
+}
+
 } // namespace WebCore
index 6841349..763a13a 100644 (file)
@@ -36,6 +36,7 @@ namespace WebCore {
     class BarInfo;
     class CSSRuleList;
     class CSSStyleDeclaration;
+    class Database;
     class DOMSelection;
     class Document;
     class Element;
@@ -43,6 +44,8 @@ namespace WebCore {
     class History;
     class Screen;
     
+    typedef int ExceptionCode;
+
     class DOMWindow : public Shared<DOMWindow> {
     public:
         DOMWindow(Frame*);
@@ -128,6 +131,9 @@ namespace WebCore {
         PassRefPtr<CSSRuleList> getMatchedCSSRules(Element*, const String& pseudoElt, bool authorOnly = true) const;
         double devicePixelRatio() const;
 
+        // HTML 5 client-side database
+        PassRefPtr<Database> openDatabase(const String& name, const String& version, ExceptionCode&);
+
     private:
         Frame* m_frame;
         mutable RefPtr<Screen> m_screen;
index 29e3696..b7149dd 100644 (file)
@@ -110,6 +110,9 @@ module window {
                                        in [Optional] boolean authorOnly);
         readonly attribute double devicePixelRatio;
 
+        Database openDatabase(in DOMString name, in DOMString version)
+            raises(DOMException);
+
 #if defined(LANGUAGE_JAVASCRIPT)
         // Global constructors
         attribute StyleSheetConstructor StyleSheet;
index 91e7e7b..4df91f7 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "CString.h"
 #include "CachedResource.h"
+#include "Database.h"
 #include "DocLoader.h"
 #include "Document.h"
 #include "DocumentLoader.h"
@@ -41,6 +42,7 @@
 #include "FrameTree.h"
 #include "HTMLFrameOwnerElement.h"
 #include "InspectorClient.h"
+#include "JSDatabase.h"
 #include "JSRange.h"
 #include "Page.h"
 #include "Range.h"
@@ -181,6 +183,44 @@ struct InspectorResource : public Shared<InspectorResource> {
     double endTime;
 };
 
+
+struct InspectorDatabaseResource : public Shared<InspectorDatabaseResource> {
+    InspectorDatabaseResource(Database* database, String domain, String name, String version)
+        : database(database)
+        , domain(domain)
+        , name(name)
+        , version(version)
+        , scriptContext(0)
+        , scriptObject(0)
+    {
+    }
+
+    InspectorDatabaseResource()
+    {
+        setScriptObject(0, 0);
+    }
+
+    void setScriptObject(JSContextRef context, JSObjectRef newScriptObject)
+    {
+        if (scriptContext && scriptObject)
+            JSValueUnprotect(scriptContext, scriptObject);
+
+        scriptObject = newScriptObject;
+        scriptContext = context;
+
+        ASSERT((context && newScriptObject) || (!context && !newScriptObject));
+        if (context && newScriptObject)
+            JSValueProtect(context, newScriptObject);
+    }
+
+    RefPtr<Database> database;
+    String domain;
+    String name;
+    String version;
+    JSContextRef scriptContext;
+    JSObjectRef scriptObject;
+};
+
 static JSValueRef addSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
 {
     JSValueRef undefined = JSValueMakeUndefined(ctx);
@@ -436,6 +476,45 @@ static JSValueRef search(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef
     return array;
 }
 
+static JSValueRef databaseTableNames(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
+{
+    InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
+    if (!controller)
+        return JSValueMakeUndefined(ctx);
+
+    if (argumentCount < 1)
+        return JSValueMakeUndefined(ctx);
+
+    Database* database = toDatabase(toJS(arguments[0]));
+    if (!database)
+        return JSValueMakeUndefined(ctx);
+
+    JSObjectRef global = JSContextGetGlobalObject(ctx);
+    JSStringRef arrayString = JSStringCreateWithUTF8CString("Array");
+    JSObjectRef arrayConstructor = JSValueToObject(ctx, JSObjectGetProperty(ctx, global, arrayString, 0), 0);
+    JSStringRelease(arrayString);
+
+    JSObjectRef result = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, 0);
+
+    JSStringRef pushString = JSStringCreateWithUTF8CString("push");
+    JSObjectRef pushFunction = JSValueToObject(ctx, JSObjectGetProperty(ctx, result, pushString, 0), 0);
+    JSStringRelease(pushString);
+
+    Vector<String> tableNames = database->tableNames();
+    unsigned length = tableNames.size();
+    for (unsigned i = 0; i < length; ++i) {
+        String tableName = tableNames[i];
+        JSStringRef tableNameString = JSStringCreateWithCharacters(tableName.characters(), tableName.length());
+        JSValueRef tableNameValue = JSValueMakeString(ctx, tableNameString);
+        JSStringRelease(tableNameString);
+
+        JSValueRef pushArguments[] = { tableNameValue };
+        JSObjectCallAsFunction(ctx, pushFunction, result, 1, pushArguments, 0);
+    }
+
+    return result;
+}
+
 static JSValueRef inspectedWindow(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/)
 {
     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
@@ -573,6 +652,7 @@ void InspectorController::setWindowVisible(bool visible)
     } else {
         clearScriptResources();
         clearScriptConsoleMessages();
+        clearDatabaseScriptResources();
         clearNetworkTimeline();
     }
 }
@@ -624,6 +704,7 @@ void InspectorController::windowScriptObjectAvailable()
         { "detach", detach, kJSPropertyAttributeNone },
         { "log", log, kJSPropertyAttributeNone },
         { "search", search, kJSPropertyAttributeNone },
+        { "databaseTableNames", databaseTableNames, kJSPropertyAttributeNone },
         { "inspectedWindow", inspectedWindow, kJSPropertyAttributeNone },
         { 0, 0, 0 }
     };
@@ -992,6 +1073,7 @@ void InspectorController::populateScriptResources()
 
     clearScriptResources();
     clearScriptConsoleMessages();
+    clearDatabaseScriptResources();
     clearNetworkTimeline();
 
     ResourcesMap::iterator resourcesEnd = m_resources.end();
@@ -1001,6 +1083,79 @@ void InspectorController::populateScriptResources()
     unsigned messageCount = m_consoleMessages.size();
     for (unsigned i = 0; i < messageCount; ++i)
         addScriptConsoleMessage(m_consoleMessages[i]);
+
+    DatabaseResourcesSet::iterator databasesEnd = m_databaseResources.end();
+    for (DatabaseResourcesSet::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it)
+        addDatabaseScriptResource((*it).get());
+}
+
+JSObjectRef InspectorController::addDatabaseScriptResource(InspectorDatabaseResource* resource)
+{
+    ASSERT_ARG(resource, resource);
+
+    if (resource->scriptObject)
+        return resource->scriptObject;
+
+    ASSERT(m_scriptContext);
+    ASSERT(m_scriptObject);
+    if (!m_scriptContext || !m_scriptObject)
+        return 0;
+
+    JSStringRef databaseString = JSStringCreateWithUTF8CString("Database");
+    JSObjectRef databaseConstructor = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, databaseString, 0), 0);
+    JSStringRelease(databaseString);
+
+    JSValueRef database = toRef(toJS(toJS(m_scriptContext), resource->database.get()));
+
+    JSStringRef domain = JSStringCreateWithCharacters(resource->domain.characters(), resource->domain.length());
+    JSValueRef domainValue = JSValueMakeString(m_scriptContext, domain);
+    JSStringRelease(domain);
+
+    JSStringRef name = JSStringCreateWithCharacters(resource->name.characters(), resource->name.length());
+    JSValueRef nameValue = JSValueMakeString(m_scriptContext, name);
+    JSStringRelease(name);
+
+    JSStringRef version = JSStringCreateWithCharacters(resource->version.characters(), resource->version.length());
+    JSValueRef versionValue = JSValueMakeString(m_scriptContext, version);
+    JSStringRelease(version);
+
+    JSValueRef arguments[] = { database, domainValue, nameValue, versionValue };
+    JSObjectRef result = JSObjectCallAsConstructor(m_scriptContext, databaseConstructor, 4, arguments, 0);
+
+    resource->setScriptObject(m_scriptContext, result);
+
+    ASSERT(result);
+
+    JSStringRef addResourceString = JSStringCreateWithUTF8CString("addResource");
+    JSObjectRef addResourceFunction = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, addResourceString, 0), 0);
+    JSStringRelease(addResourceString);
+
+    JSValueRef addArguments[] = { result };
+    JSObjectCallAsFunction(m_scriptContext, addResourceFunction, m_scriptObject, 1, addArguments, 0);
+
+    return result;
+}
+
+void InspectorController::removeDatabaseScriptResource(InspectorDatabaseResource* resource)
+{
+    ASSERT(m_scriptContext);
+    ASSERT(m_scriptObject);
+    if (!m_scriptContext || !m_scriptObject)
+        return;
+
+    ASSERT(resource);
+    ASSERT(resource->scriptObject);
+    if (!resource || !resource->scriptObject)
+        return;
+
+    JSStringRef removeResourceString = JSStringCreateWithUTF8CString("removeResource");
+    JSObjectRef removeResourceFunction = JSValueToObject(m_scriptContext, JSObjectGetProperty(m_scriptContext, m_scriptObject, removeResourceString, 0), 0);
+    JSStringRelease(removeResourceString);
+
+    JSValueRef arguments[] = { resource->scriptObject };
+    JSObjectCallAsFunction(m_scriptContext, removeResourceFunction, m_scriptObject, 1, arguments, 0);
+
+    resource->setScriptObject(0, 0);
 }
 
 void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message)
@@ -1057,6 +1212,20 @@ void InspectorController::clearScriptResources()
     callClearFunction(m_scriptContext, m_scriptObject, "clearResources");
 }
 
+void InspectorController::clearDatabaseScriptResources()
+{
+    if (!m_scriptContext || !m_scriptObject)
+        return;
+
+    DatabaseResourcesSet::iterator databasesEnd = m_databaseResources.end();
+    for (DatabaseResourcesSet::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it) {
+        InspectorDatabaseResource* resource = (*it).get();
+        resource->setScriptObject(0, 0);
+    }
+
+    callClearFunction(m_scriptContext, m_scriptObject, "clearDatabaseResources");
+}
+
 void InspectorController::clearScriptConsoleMessages()
 {
     if (!m_scriptContext || !m_scriptObject)
@@ -1102,10 +1271,15 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
         // FIXME: Should look into asserting that m_mainResource->loader == loader here.
 
         m_client->inspectedURLChanged(loader->URL().url());
+
         deleteAllValues(m_consoleMessages);
         m_consoleMessages.clear();
+
+        m_databaseResources.clear();
+
         if (windowVisible()) {
             clearScriptConsoleMessages();
+            clearDatabaseScriptResources();
             clearNetworkTimeline();
 
             // We don't add the main resource until its load is committed. This
@@ -1311,4 +1485,17 @@ void InspectorController::didFailLoading(DocumentLoader* loader, unsigned long i
     }
 }
 
+void InspectorController::didOpenDatabase(Database* database, const String& domain, const String& name, const String& version)
+{
+    if (!enabled())
+        return;
+
+    InspectorDatabaseResource* resource = new InspectorDatabaseResource(database, domain, name, version);
+
+    m_databaseResources.add(resource);
+
+    if (windowVisible())
+        addDatabaseScriptResource(resource);
+}
+
 } // namespace WebCore
index dc4bef7..890c717 100644 (file)
 #include "Chrome.h"
 #include <JavaScriptCore/JSContextRef.h>
 #include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
 
+class Database;
 class DocumentLoader;
 class InspectorClient;
 class Node;
@@ -43,6 +45,7 @@ class ResourceResponse;
 class ResourceError;
 
 struct ConsoleMessage;
+struct InspectorDatabaseResource;
 struct InspectorResource;
 struct ResourceRequest;
 
@@ -50,6 +53,7 @@ class InspectorController {
 public:
     typedef HashMap<long long, RefPtr<InspectorResource> > ResourcesMap;
     typedef HashMap<RefPtr<Frame>, ResourcesMap*> FrameResourcesMap;
+    typedef HashSet<RefPtr<InspectorDatabaseResource> > DatabaseResourcesSet;
 
     InspectorController(Page*, InspectorClient*);
     ~InspectorController();
@@ -95,6 +99,8 @@ public:
     void didFinishLoading(DocumentLoader*, unsigned long identifier);
     void didFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&);
 
+    void didOpenDatabase(Database*, const String& domain, const String& name, const String& version);
+
     const ResourcesMap& resources() const { return m_resources; }
 
 private:
@@ -104,6 +110,7 @@ private:
     void clearScriptConsoleMessages();
 
     void clearNetworkTimeline();
+    void clearDatabaseScriptResources();
 
     void addResource(InspectorResource*);
     void removeResource(InspectorResource*);
@@ -121,6 +128,9 @@ private:
     void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0);
     void removeAllResources(ResourcesMap* map) { pruneResources(map); }
 
+    JSObjectRef addDatabaseScriptResource(InspectorDatabaseResource*);
+    void removeDatabaseScriptResource(InspectorDatabaseResource*);
+
     Page* m_inspectedPage;
     InspectorClient* m_client;
     Page* m_page;
@@ -129,6 +139,7 @@ private:
     ResourcesMap m_resources;
     FrameResourcesMap m_frameResources;
     Vector<ConsoleMessage*> m_consoleMessages;
+    DatabaseResourcesSet m_databaseResources;
     JSObjectRef m_scriptObject;
     JSObjectRef m_controllerScriptObject;
     JSContextRef m_scriptContext;
diff --git a/WebCore/page/inspector/Database.js b/WebCore/page/inspector/Database.js
new file mode 100644 (file)
index 0000000..99353fc
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+WebInspector.Database = function(database, domain, name, version)
+{
+    this.database = database;
+    this.domain = domain;
+    this.name = name;
+    this.version = version;
+
+    this.listItem = new WebInspector.ResourceTreeElement(this);
+    this.updateTitle();
+
+    this.category.addResource(this);
+}
+
+WebInspector.Database.prototype = {
+    get database()
+    {
+        return this._database;
+    },
+
+    set database(x)
+    {
+        if (this._database === x)
+            return;
+        this._database = x;
+    },
+
+    get name()
+    {
+        return this._name;
+    },
+
+    set name(x)
+    {
+        if (this._name === x)
+            return;
+        this._name = x;
+        this.updateTitleSoon();
+    },
+
+    get version()
+    {
+        return this._version;
+    },
+
+    set version(x)
+    {
+        if (this._version === x)
+            return;
+        this._version = x;
+    },
+
+    get domain()
+    {
+        return this._domain;
+    },
+
+    set domain(x)
+    {
+        if (this._domain === x)
+            return;
+        this._domain = x;
+        this.updateTitleSoon();
+    },
+
+    get category()
+    {
+        return WebInspector.resourceCategories.databases;
+    },
+
+    updateTitleSoon: function()
+    {
+        if (this.updateTitleTimeout)
+            return;
+        var _self = this;
+        this.updateTitleTimeout = setTimeout(function () { _self.updateTitle() }, 0);
+    },
+
+    updateTitle: function()
+    {
+        delete this.updateTitleTimeout;
+
+        var title = this.name;
+
+        var info = "";
+        if (this.domain && (!WebInspector.mainResource || (WebInspector.mainResource && this.domain !== WebInspector.mainResource.domain)))
+            info = this.domain;
+
+        var fullTitle = "<span class=\"title" + (info && info.length ? "" : " only") + "\">" + title.escapeHTML() + "</span>";
+        if (info && info.length)
+            fullTitle += "<span class=\"info\">" + info.escapeHTML() + "</span>";
+        fullTitle += "<div class=\"icon database\"></div>";
+
+        this.listItem.title = fullTitle;
+    },
+
+    get panel()
+    {
+        if (!this._panel)
+            this._panel = new WebInspector.DatabasePanel(this);
+        return this._panel;
+    },
+
+    select: function()
+    {
+        WebInspector.navigateToResource(this);
+    },
+
+    deselect: function()
+    {
+        this.listItem.deselect(true);
+        if (WebInspector.currentPanel === this._panel)
+            WebInspector.currentPanel = null;
+    },
+
+    attach: function()
+    {
+        this.panel.attach();
+    },
+
+    detach: function()
+    {
+        if (this._panel)
+            this.panel.detach();
+    }
+}
diff --git a/WebCore/page/inspector/DatabasePanel.js b/WebCore/page/inspector/DatabasePanel.js
new file mode 100644 (file)
index 0000000..369ec7a
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+WebInspector.DatabasePanel = function(database)
+{
+    WebInspector.Panel.call(this);
+
+    this.database = database;
+
+    this.queryPromptElement = document.createElement("textarea");
+    this.queryPromptElement.className = "database-prompt";
+    this.element.appendChild(this.queryPromptElement);
+
+    var panel = this;
+    this.queryPromptElement.addEventListener("keydown", function(event) { panel.queryInputKeypress(event) }, false);
+
+    this.queryPromptHistory = [];
+    this.queryPromptHistoryOffset = 0;
+
+    var selectViewFunction = function(event)
+    {
+        WebInspector.navigateToView(event.currentTarget.view);
+    }
+
+    var views = [
+        { name: "query", title: "Query", selected: false },
+        { name: "browse", title: "Browse", selected: true }
+    ];
+
+    this.views = {};
+    this.viewButtons = [];
+    for (var i = 0; i < views.length; ++i) {
+        var buttonElement = document.createElement("button");
+        buttonElement.setAttribute("title", views[i].title);
+        buttonElement.addEventListener("click", selectViewFunction, "true");
+        buttonElement.appendChild(document.createElement("img"));
+
+        var contentElement = document.createElement("div");
+        contentElement.className = "content database-" + views[i].name;
+
+        var view = {};
+        view.panel = this;
+        view.buttonElement = buttonElement;
+        view.contentElement = contentElement;
+        view.buttonElement.view = view;
+
+        this.views[views[i].name] = view;
+        this.viewButtons.push(buttonElement);
+        this.element.appendChild(contentElement);
+    }
+
+    this.currentView = this.views.browse;
+
+    var queryPanel = this.views.query;
+
+    queryPanel.commandListElement = document.createElement("ol");
+    queryPanel.commandListElement.className = "database-command-list";
+    queryPanel.contentElement.appendChild(queryPanel.commandListElement);
+
+    queryPanel.onshow = function()
+    {
+        panel.queryPromptElement.focus();
+        this.commandListElement.scrollTop = this.previousScrollTop;
+    };
+
+    queryPanel.onhide = function()
+    {
+        this.previousScrollTop = this.commandListElement.scrollTop;
+    };
+
+    var browsePanel = this.views.browse;
+
+    browsePanel.reloadTableElement = document.createElement("button");
+    browsePanel.reloadTableElement.appendChild(document.createElement("img"));
+    browsePanel.reloadTableElement.className = "database-table-reload";
+    browsePanel.reloadTableElement.title = "Reload";
+    browsePanel.reloadTableElement.addEventListener("click", function() { panel.updateTableList(); panel.updateTableBrowser() }, false);
+
+    browsePanel.onshow = function()
+    {
+        panel.updateTableList();
+        panel.queryPromptElement.focus();
+
+        this.tableSelectElement.removeStyleClass("hidden");
+        document.getElementById("viewbuttons").appendChild(this.tableSelectElement);
+
+        this.reloadTableElement.removeStyleClass("hidden");
+        document.getElementById("viewbuttons").appendChild(this.reloadTableElement);
+
+        this.contentElement.scrollTop = this.previousScrollTop;
+    };
+
+    browsePanel.onhide = function()
+    {
+        this.tableSelectElement.addStyleClass("hidden");
+        this.reloadTableElement.addStyleClass("hidden");
+        this.previousScrollTop = this.contentElement.scrollTop;
+    };
+}
+
+WebInspector.DatabasePanel.prototype = {
+    show: function()
+    {
+        WebInspector.Panel.prototype.show.call(this);
+        this.queryPromptElement.focus();
+        if (this.currentView && "onshow" in this.currentView)
+            this.currentView.onshow.call(this.currentView);
+    },
+
+    hide: function()
+    {
+        if (this.currentView && "onhide" in this.currentView)
+            this.currentView.onhide();
+        WebInspector.Panel.prototype.hide.call(this);
+    },
+
+    get currentView()
+    {
+        return this._currentView;
+    },
+
+    set currentView(x)
+    {
+        if (this._currentView === x)
+            return;
+
+        if (this._currentView) {
+            if ("onhide" in this._currentView)
+                this._currentView.onhide.call(this._currentView);
+            this._currentView.buttonElement.removeStyleClass("selected");
+            this._currentView.contentElement.removeStyleClass("selected");
+        }
+
+        this._currentView = x;
+
+        if (x) {
+            x.buttonElement.addStyleClass("selected");
+            x.contentElement.addStyleClass("selected");
+            if ("onshow" in x)
+                x.onshow.call(x);
+
+            if (x.contentElement.parentNode !== this.element)
+                InspectorController.log("Tried to set currentView to a view " + x.title + " whose contentElement is a non-child");
+        }
+    },
+
+    get currentTable()
+    {
+        return this._currentTable;
+    },
+
+    set currentTable(x)
+    {
+        if (this._currentTable === x)
+            return;
+
+        this._currentTable = x;
+
+        if (x) {
+            var browseView = this.views.browse;
+            if (browseView.tableSelectElement) {
+                var length = browseView.tableSelectElement.options.length;
+                for (var i = 0; i < length; ++i) {
+                    var option = browseView.tableSelectElement.options[i];
+                    if (option.value === x) {
+                        browseView.tableSelectElement.selectedIndex = i;
+                        break;
+                    }
+                }
+            }
+
+            this.updateTableBrowser();
+        }
+    },
+
+    updateTableList: function()
+    {
+        var browseView = this.views.browse;
+        if (!browseView.tableSelectElement) {
+            browseView.tableSelectElement = document.createElement("select");
+            browseView.tableSelectElement.className = "database-table-select hidden";
+
+            var panel = this;
+            var changeTableFunction = function()
+            {
+                var browseView = panel.views.browse;
+                var index = browseView.tableSelectElement.selectedIndex;
+                if (index != -1)
+                    panel.currentTable = browseView.tableSelectElement.options[index].value;
+                else
+                    panel.currentTable = null;
+            };
+
+            browseView.tableSelectElement.addEventListener("change", changeTableFunction, false);
+        }
+
+        browseView.tableSelectElement.removeChildren();
+
+        var selectedTableName = this.currentTable;
+        var tableNames = InspectorController.databaseTableNames(this.database.database).sort();
+
+        var length = tableNames.length;
+        for (var i = 0; i < length; ++i) {
+            var option = document.createElement("option");
+            option.value = tableNames[i];
+            option.text = tableNames[i];
+            browseView.tableSelectElement.appendChild(option);
+
+            if (tableNames[i] === selectedTableName)
+                browseView.tableSelectElement.selectedIndex = i;
+        }
+
+        if (!selectedTableName && length)
+            this.currentTable = tableNames[0];
+    },
+
+    updateTableBrowser: function()
+    {
+        if (!this.currentTable) {
+            this.views.browse.contentElement.removeChildren();
+            return;
+        }
+
+        try {
+            var panel = this;
+            var query = "SELECT * FROM " + this.currentTable;
+            this.database.database.executeSql(query, function(result) { panel.browseQueryFinished(result) });
+        } catch(e) {
+            // FIXME: handle this error a better way.
+            this.views.browse.contentElement.removeChildren();
+        }
+    },
+
+    browseQueryFinished: function(result)
+    {
+        this.views.browse.contentElement.removeChildren();
+
+        var table = this._tableForResult(result);
+        if (table) {
+            var rowCount = table.getElementsByTagName("tr").length;
+            var columnCount = table.getElementsByTagName("tr").item(0).getElementsByTagName("th").length;
+
+            var tr = document.createElement("tr");
+            tr.className = "database-result-filler-row";
+            table.appendChild(tr);
+
+            if (!(rowCount % 2))
+                tr.addStyleClass("alternate");
+
+            for (var i = 0; i < columnCount; ++i) {
+                var td = document.createElement("td");
+                tr.appendChild(td);
+            }
+
+            table.addStyleClass("database-browse-table");
+            this.views.browse.contentElement.appendChild(table);
+        } else {
+            if (!result.errorCode) {
+                var emptyMsgElement = document.createElement("div");
+                emptyMsgElement.className = "database-table-empty";
+                emptyMsgElement.innerHTML = "The <q>" + this.currentTable + "</q><br>table is empty.";
+                this.views.browse.contentElement.appendChild(emptyMsgElement);
+            } else {
+                var errorMsgElement = document.createElement("div");
+                errorMsgElement.className = "database-table-error";
+                errorMsgElement.innerHTML = "An error occurred trying to<br>read the <q>" + this.currentTable + "</q> table.";
+                this.views.browse.contentElement.appendChild(errorMsgElement);
+            }
+        }
+    },
+
+    queryInputKeypress: function(event)
+    {
+        switch (event.keyIdentifier) {
+            case "Enter":
+                this._onQueryInputEnterPressed(event);
+                break;
+            case "Up":
+                this._onQueryInputUpPressed(event);
+                break;
+            case "Down":
+                this._onQueryInputDownPressed(event);
+                break;
+        }
+    },
+
+    queryFinished: function(query, result)
+    {
+        var commandItem = document.createElement("li");
+        commandItem.className = "database-command";
+
+        var queryDiv = document.createElement("div");
+        queryDiv.className = "database-command-query";
+        queryDiv.textContent = query;
+        commandItem.appendChild(queryDiv);
+
+        var resultDiv = document.createElement("div");
+        resultDiv.className = "database-command-result";
+        commandItem.appendChild(resultDiv);
+
+        if (!result.errorCode) {
+            var table = this._tableForResult(result);
+            if (table)
+                resultDiv.appendChild(table);
+        } else {
+            if (this.currentView !== this.views.query)
+                this.currentView = this.views.query;
+
+            if (result.errorCode == 1) {
+                resultDiv.className += " error";
+                resultDiv.textContent = result.error;
+            } else if (result.errorCode == 2) {
+                resultDiv.className += " error";
+                resultDiv.textContent = "Database no longer has expected version.";
+            } else {
+                resultDiv.className += " error";
+                resultDiv.textContent = "An unexpected error " + result.errorCode + " occured.";
+            }
+        }
+
+        this.views.query.commandListElement.appendChild(commandItem);
+        commandItem.scrollIntoView(false);
+    },
+
+    _onQueryInputEnterPressed: function(event)
+    {
+        event.preventDefault();
+        event.stopPropagation();
+
+        var query = this.queryPromptElement.value;
+        if (!query.length)
+            return;
+
+        try {
+            var panel = this;
+            this.database.database.executeSql(query, function(result) { panel.queryFinished(query, result) });
+
+            this.queryPromptHistory.push(query);
+            this.queryPromptHistoryOffset = 0;
+
+            this.queryPromptElement.value = "";
+
+            if (query.match(/^select /i)) {
+                if (this.currentView !== this.views.query)
+                    this.currentView = this.views.query;
+            } else {
+                if (query.match(/^create /i) || query.match(/^drop table /i))
+                    this.updateTableList();
+
+                // FIXME: we should only call updateTableBrowser() is we know the current table was modified
+                this.updateTableBrowser();
+            }
+        } catch(e) {
+            // FIXME: handle this error some way.
+        }
+    },
+
+    _onQueryInputUpPressed: function(event)
+    {
+        event.preventDefault();
+        event.stopPropagation();
+
+        if (this.queryPromptHistoryOffset == this.queryPromptHistory.length)
+            return;
+
+        if (this.queryPromptHistoryOffset == 0)
+            this.tempSavedQuery = this.queryPromptElement.value;
+
+        ++this.queryPromptHistoryOffset;
+        this.queryPromptElement.value = this.queryPromptHistory[this.queryPromptHistory.length - this.queryPromptHistoryOffset];
+        this.queryPromptElement.moveCursorToEnd();
+    },
+
+    _onQueryInputDownPressed: function(event)
+    {
+        event.preventDefault();
+        event.stopPropagation();
+
+        if (this.queryPromptHistoryOffset == 0)
+            return;
+
+        --this.queryPromptHistoryOffset;
+
+        if (this.queryPromptHistoryOffset == 0) {
+            this.queryPromptElement.value = this.tempSavedQuery;
+            this.queryPromptElement.moveCursorToEnd();
+            delete this.tempSavedQuery;
+            return;
+        }
+
+        this.queryPromptElement.value = this.queryPromptHistory[this.queryPromptHistory.length - this.queryPromptHistoryOffset];
+        this.queryPromptElement.moveCursorToEnd();
+    },
+
+    _tableForResult: function(result)
+    {
+        if (result.errorCode || !result.rows.length)
+            return null;
+
+        var rows = result.rows;
+        var length = rows.length;
+        var columnWidths = [];
+
+        var table = document.createElement("table");
+        table.className = "database-result-table";
+
+        var headerRow = document.createElement("tr");
+        table.appendChild(headerRow);
+
+        var j = 0;
+        for (var column in rows.item(0)) {
+            var th = document.createElement("th");
+            headerRow.appendChild(th);
+
+            var div = document.createElement("div");
+            div.textContent = column;
+            div.title = column;
+            th.appendChild(div);
+
+            columnWidths[j++] = column.length;
+        }
+
+        for (var i = 0; i < length; ++i) {
+            var row = rows.item(i);
+            var tr = document.createElement("tr");
+            if (i % 2)
+                tr.className = "alternate";
+            table.appendChild(tr);
+
+            var j = 0;
+            for (var column in row) {
+                var td = document.createElement("td");
+                tr.appendChild(td);
+
+                var text = row[column];
+                var div = document.createElement("div");
+                div.textContent = text;
+                div.title = text;
+                td.appendChild(div);
+
+                if (text.length > columnWidths[j])
+                    columnWidths[j] = text.length;
+                ++j;
+            }
+        }
+
+        var totalColumnWidths = 0;
+        length = columnWidths.length;
+        for (var i = 0; i < length; ++i)
+            totalColumnWidths += columnWidths[i];
+
+        // Calculate the percentage width for the columns.
+        var minimumPrecent = 5;
+        var recoupPercent = 0;
+        for (var i = 0; i < length; ++i) {
+            columnWidths[i] = Math.round((columnWidths[i] / totalColumnWidths) * 100);
+            if (columnWidths[i] < minimumPrecent) {
+                recoupPercent += (minimumPrecent - columnWidths[i]);
+                columnWidths[i] = minimumPrecent;
+            }
+        }
+
+        // Enforce the minimum percentage width.
+        while (recoupPercent > 0) {
+            for (var i = 0; i < length; ++i) {
+                if (columnWidths[i] > minimumPrecent) {
+                    --columnWidths[i];
+                    --recoupPercent;
+                    if (!recoupPercent)
+                        break;
+                }
+            }
+        }
+
+        length = headerRow.childNodes.length;
+        for (var i = 0; i < length; ++i) {
+            var th = headerRow.childNodes[i];
+            th.style.width = columnWidths[i] + "%";
+        }
+
+        return table;
+    }
+}
+
+WebInspector.DatabasePanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/WebCore/page/inspector/Images/alternateTableRows.png b/WebCore/page/inspector/Images/alternateTableRows.png
new file mode 100644 (file)
index 0000000..7706f50
Binary files /dev/null and b/WebCore/page/inspector/Images/alternateTableRows.png differ
diff --git a/WebCore/page/inspector/Images/database.png b/WebCore/page/inspector/Images/database.png
new file mode 100644 (file)
index 0000000..2c13789
Binary files /dev/null and b/WebCore/page/inspector/Images/database.png differ
diff --git a/WebCore/page/inspector/Images/databaseBrowserViewButton.png b/WebCore/page/inspector/Images/databaseBrowserViewButton.png
new file mode 100644 (file)
index 0000000..bc8e6c9
Binary files /dev/null and b/WebCore/page/inspector/Images/databaseBrowserViewButton.png differ
diff --git a/WebCore/page/inspector/Images/databaseQueryViewButton.png b/WebCore/page/inspector/Images/databaseQueryViewButton.png
new file mode 100644 (file)
index 0000000..548480b
Binary files /dev/null and b/WebCore/page/inspector/Images/databaseQueryViewButton.png differ
index 7ad1e79..aca8a8b 100644 (file)
Binary files a/WebCore/page/inspector/Images/domViewButton.png and b/WebCore/page/inspector/Images/domViewButton.png differ
diff --git a/WebCore/page/inspector/Images/glossyHeader.png b/WebCore/page/inspector/Images/glossyHeader.png
new file mode 100644 (file)
index 0000000..8c80b6b
Binary files /dev/null and b/WebCore/page/inspector/Images/glossyHeader.png differ
diff --git a/WebCore/page/inspector/Images/glossyHeaderPressed.png b/WebCore/page/inspector/Images/glossyHeaderPressed.png
new file mode 100644 (file)
index 0000000..6b0dd60
Binary files /dev/null and b/WebCore/page/inspector/Images/glossyHeaderPressed.png differ
diff --git a/WebCore/page/inspector/Images/popupArrowsBlack.png b/WebCore/page/inspector/Images/popupArrowsBlack.png
new file mode 100644 (file)
index 0000000..9c9b061
Binary files /dev/null and b/WebCore/page/inspector/Images/popupArrowsBlack.png differ
diff --git a/WebCore/page/inspector/Images/reload.png b/WebCore/page/inspector/Images/reload.png
new file mode 100644 (file)
index 0000000..770c459
Binary files /dev/null and b/WebCore/page/inspector/Images/reload.png differ
index 8c78f26..bd9dea4 100644 (file)
Binary files a/WebCore/page/inspector/Images/sourceViewButton.png and b/WebCore/page/inspector/Images/sourceViewButton.png differ
diff --git a/WebCore/page/inspector/Images/toolbarPopup.png b/WebCore/page/inspector/Images/toolbarPopup.png
new file mode 100644 (file)
index 0000000..437c4b6
Binary files /dev/null and b/WebCore/page/inspector/Images/toolbarPopup.png differ
diff --git a/WebCore/page/inspector/Images/toolbarPopupInactive.png b/WebCore/page/inspector/Images/toolbarPopupInactive.png
new file mode 100644 (file)
index 0000000..9e759cc
Binary files /dev/null and b/WebCore/page/inspector/Images/toolbarPopupInactive.png differ
diff --git a/WebCore/page/inspector/Images/toolbarPopupPressed.png b/WebCore/page/inspector/Images/toolbarPopupPressed.png
new file mode 100644 (file)
index 0000000..8458036
Binary files /dev/null and b/WebCore/page/inspector/Images/toolbarPopupPressed.png differ
diff --git a/WebCore/page/inspector/Images/toolbarPopupPressedInactive.png b/WebCore/page/inspector/Images/toolbarPopupPressedInactive.png
new file mode 100644 (file)
index 0000000..3f27ce4
Binary files /dev/null and b/WebCore/page/inspector/Images/toolbarPopupPressedInactive.png differ
index 33369eb..5193b48 100644 (file)
@@ -47,8 +47,12 @@ WebInspector.ResourceCategory.prototype = {
         var resourcesLength = this.resources.length;
         for (var i = 0; i < resourcesLength; ++i) {
             var b = this.resources[i];
-            if (a._lastPathComponentLowerCase < b._lastPathComponentLowerCase)
-                break;
+            if (a._lastPathComponentLowerCase && b._lastPathComponentLowerCase)
+                if (a._lastPathComponentLowerCase < b._lastPathComponentLowerCase)
+                    break;
+            else if (a.name && b.name)
+                if (a.name < b.name)
+                    break;
         }
 
         this.resources.splice(i, 0, resource);
index c40ce88..5d96bae 100644 (file)
@@ -111,6 +111,37 @@ body.inactive #toolbar button, body.inactive #toolbar button:disabled:active {
     -webkit-border-image: url(Images/toolbarButtonInactive.png) 3 3 4 3;
 }
 
+#toolbar select, #toolbar select:disabled:active {
+    background-color: transparent;
+    border-width: 3px 12px 4px 3px;
+    border-color: transparent;
+    -webkit-border-image: url(Images/toolbarPopup.png) 3 12 4 3;
+    height: 19px;
+    font-size: 10px;
+    padding-left: 8px;
+    padding-right: 4px;
+    -webkit-box-sizing: border-box;
+    -webkit-border-radius: 0;
+    -webkit-appearance: none;
+    vertical-align: middle;
+}
+
+#toolbar select:focus {
+    outline: none;
+}
+
+#toolbar select:active, #toolbar select.selected {
+    -webkit-border-image: url(Images/toolbarPopupPressed.png) 3 12 4 3;
+}
+
+body.inactive #toolbar select:active, body.inactive #toolbar select.selected {
+    -webkit-border-image: url(Images/toolbarPopupPressedInactive.png) 3 12 4 3;
+}
+
+body.inactive #toolbar select, body.inactive #toolbar select:disabled:active {
+    -webkit-border-image: url(Images/toolbarPopupInactive.png) 3 12 4 3;
+}
+
 #toolbar .split-button-divider {
     width: 1px;
     height: 19px;
@@ -168,10 +199,11 @@ body.inactive #toolbar .split-button-divider {
     top: -1px;
     width: 8px;
     height: 7px;
+    opacity: 0.66;
 }
 
 .view-button-source.selected img {
-    content: url(Images/sourceViewButtonSelected.png);
+    opacity: 1;
 }
 
 .view-button-dom img {
@@ -181,10 +213,11 @@ body.inactive #toolbar .split-button-divider {
     left: 1px;
     width: 10px;
     height: 7px;
+    opacity: 0.66;
 }
 
 .view-button-dom.selected img {
-    content: url(Images/domViewButtonSelected.png);
+    opacity: 1;
 }
 
 #viewbuttons {
@@ -491,6 +524,10 @@ body.attached #attachToggle:active {
     background-position: center center;
 }
 
+#list .icon.database {
+    background-image: url(Images/database.png);
+}
+
 #list .icon.plain {
     background-image: url(Images/plainDocument.png);
 }
@@ -1326,6 +1363,222 @@ body.inactive #sidebar li.selected {
     top: 1px;
 }
 
+.view-button-browse img {
+    content: url(Images/databaseBrowserViewButton.png);
+    position: relative;
+    top: -1px;
+    left: 1px;
+    width: 11px;
+    height: 7px;
+    opacity: 0.66;
+}
+
+.view-button-browse.selected img {
+    opacity: 1;
+}
+
+.view-button-query img {
+    content: url(Images/databaseQueryViewButton.png);
+    position: relative;
+    top: -1px;
+    left: 0px;
+    width: 10px;
+    height: 7px;
+    opacity: 0.66;
+}
+
+.view-button-query.selected img {
+    opacity: 1;
+}
+
+.database-table-reload {
+    padding-left: 0;
+    padding-right: 0;
+    width: 20px;
+    margin-left: 6px;
+}
+
+.database-table-reload img {
+    content: url(Images/reload.png);
+    position: relative;
+    top: -2px;
+    left: 0px;
+    width: 10px;
+    height: 11px;
+    opacity: 0.7;
+}
+
+.database-query.content {
+    bottom: 21px;
+}
+
+.database-browse.content {
+    font-size: 10px;
+    overflow-y: auto;
+    overflow-x: hidden;
+    bottom: 21px;
+}
+
+.database-browse.content .database-result-table {
+    border: none;
+}
+
+.database-browse.content .database-table-empty {
+    position: absolute;
+    top: 0;
+    bottom: 25%;
+    left: 0;
+    right: 0;
+    font-size: 24px;
+    color: rgb(75%, 75%, 75%);
+    margin-top: auto;
+    margin-bottom: auto;
+    height: 50px;
+    line-height: 26px;
+    text-align: center;
+    font-weight: bold;
+    padding: 10px;
+}
+
+.database-browse.content .database-table-error {
+    position: absolute;
+    top: 0;
+    bottom: 25%;
+    left: 0;
+    right: 0;
+    font-size: 24px;
+    color: rgb(66%, 33%, 33%);
+    margin-top: auto;
+    margin-bottom: auto;
+    height: 50px;
+    line-height: 26px;
+    text-align: center;
+    padding: 10px;
+}
+
+.database-browse-table {
+    height: 100%;
+}
+
+.database-result-table .database-result-filler-row {
+    height: auto;
+}
+
+.database-result-table .database-result-filler-row.alternate td {
+    background-position-y: 16px;
+}
+
+.database-result-filler-row td {
+    background-image: url(Images/alternateTableRows.png);
+}
+
+.database-table-select {
+    margin-left: 6px;
+    max-width: 150px;
+    min-width: 75px;
+}
+
+.database-command-list {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.database-prompt {
+    font-family: monospace;
+    font-size: 11px;
+    margin: 0;
+    padding: 2px 0 0;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 18px;
+    resize: none;
+    outline: none;
+    border: none;
+    border-top: 1px solid rgb(64%, 64%, 64%);
+}
+
+.database-command {
+    font-size: 10px;
+    margin: 0;
+    padding: 5px;
+    border-bottom: 1px solid rgb(75%, 75%, 75%);
+    word-break: break-word;
+    position: relative;
+}
+
+.database-command a:hover {
+    text-decoration: underline;
+    cursor: pointer;
+}
+
+.database-command-query {
+    font-family: monospace;
+    font-size: 11px;
+    white-space: pre-wrap;
+}
+
+.database-command-result {
+    margin-top: 3px;
+}
+
+.database-command-result.error {
+    color: red;
+}
+
+.database-result-table {
+    border: 1px solid #aaa;
+    table-layout: fixed;
+    border-spacing: 0;
+    border-collapse: collapse;
+    width: 100%;
+    -webkit-box-sizing: border-box;
+}
+
+.database-result-table th {
+    text-align: left;
+    background: url(Images/glossyHeader.png) repeat-x;
+    border-right: 1px solid #aaa;
+    height: 15px;
+    -webkit-box-sizing: border-box;
+    border-bottom: 1px solid #aaa;
+    font-weight: normal;
+    vertical-align: middle;
+    padding: 0 4px;
+    white-space: nowrap;
+}
+
+.database-result-table tr {
+    height: 16px;
+}
+
+.database-result-table tr.alternate {
+    background-color: rgb(236, 243, 254);
+}
+
+.database-result-table td {
+    vertical-align: top;
+    padding: 2px 4px;
+    -webkit-box-sizing: border-box;
+    white-space: nowrap;
+    border-right: 1px solid #aaa;
+}
+
+.database-result-table td > div, .database-result-table th > div {
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
 .network-timeline {
     position: absolute;
     top: 0;
index d99d19e..1cd8819 100644 (file)
@@ -38,6 +38,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     <script type="text/javascript" src="ResourceCategory.js"></script>
     <script type="text/javascript" src="ResourcePanel.js"></script>
     <script type="text/javascript" src="NetworkPanel.js"></script>
+    <script type="text/javascript" src="Database.js"></script>
+    <script type="text/javascript" src="DatabasePanel.js"></script>
     <link rel="stylesheet" type="text/css" href="inspector.css" />
 </head>
 <body class="detached">
index 6b1e0a2..1fb14ef 100644 (file)
@@ -204,6 +204,7 @@ WebInspector.loaded = function(event)
         stylesheets: new WebInspector.ResourceCategory("stylesheets"),
         images: new WebInspector.ResourceCategory("images"),
         scripts: new WebInspector.ResourceCategory("scripts"),
+        databases: new WebInspector.ResourceCategory("databases"),
         other: new WebInspector.ResourceCategory("other")
     };
 
@@ -558,12 +559,14 @@ WebInspector.updateViewButtons = function()
 WebInspector.addResource = function(resource)
 {
     this.resources.push(resource);
-    this.resourceURLMap[resource.url] = resource;
 
     if (resource.mainResource)
         this.mainResource = resource;
 
-    this.networkPanel.addResourceToTimeline(resource);
+    if (resource.url) {
+        this.resourceURLMap[resource.url] = resource;
+        this.networkPanel.addResourceToTimeline(resource);
+    }
 }
 
 WebInspector.removeResource = function(resource)
@@ -572,7 +575,8 @@ WebInspector.removeResource = function(resource)
 
     resource.category.removeResource(resource);
 
-    delete this.resourceURLMap[resource.url];
+    if (resource.url)
+        delete this.resourceURLMap[resource.url];
 
     var resourcesLength = this.resources.length;
     for (var i = 0; i < resourcesLength; ++i) {
@@ -593,6 +597,11 @@ WebInspector.clearResources = function()
     delete this.mainResource;
 }
 
+WebInspector.clearDatabaseResources = function()
+{
+    this.resourceCategories.databases.removeAllResources();
+}
+
 WebInspector.resourceURLChanged = function(resource, oldURL)
 {
     delete this.resourceURLMap[oldURL];
index 8489608..582726c 100644 (file)
 #ifndef FileSystem_h
 #define FileSystem_h
 
+#include <wtf/Vector.h>
+
 namespace WebCore {
 
+class CString;
 class String;
 
 bool fileExists(const String&);
 bool deleteFile(const String&);
 bool fileSize(const String&, long long& result);
+String pathByAppendingComponent(const String& path, const String& component);
+bool makeAllDirectories(const String& path);
+String homeDirectoryPath();
+
+CString fileSystemRepresentation(const String&);
 
 } // namespace WebCore
 
index b744b99..5d756a0 100644 (file)
@@ -52,4 +52,6 @@ WTFLogChannel LogPlatformLeaks =     { 0x00010000, "WebCoreLogLevel", WTFLogChan
 WTFLogChannel LogNetwork =           { 0x00100000, "WebCoreLogLevel", WTFLogChannelOff };
 WTFLogChannel LogFTP =               { 0x00200000, "WebCoreLogLevel", WTFLogChannelOff };
 WTFLogChannel LogThreading =         { 0x00400000, "WebCoreLogLevel", WTFLogChannelOff };
+WTFLogChannel LogStorageAPI =        { 0x00800000, "WebCoreLogLevel", WTFLogChannelOff };
+
 }
index 44d9f3d..2a2dbcc 100644 (file)
@@ -51,6 +51,7 @@ namespace WebCore {
     extern WTFLogChannel LogNetwork;
     extern WTFLogChannel LogFTP;
     extern WTFLogChannel LogThreading;
+    extern WTFLogChannel LogStorageAPI;
 
     void InitializeLoggingChannelsIfNecessary();
 }
index 391e4ee..1f5107c 100644 (file)
@@ -133,4 +133,9 @@ bool SecurityOrigin::isSecureTransitionTo(const KURL& url) const
     return equalIgnoringCase(m_host, String(url.host())) && equalIgnoringCase(m_protocol, String(url.protocol())) && m_port == url.port();
 }
 
+String SecurityOrigin::toString() const
+{
+    return m_protocol + ":" + m_host + ":" + String::number(m_port);
+}
+
 } // namespace WebCore
index 21192ea..e6c9afc 100644 (file)
@@ -46,6 +46,8 @@ namespace WebCore {
         bool allowsAccessFrom(const SecurityOrigin&) const;
         bool isSecureTransitionTo(const KURL&) const;
 
+        String toString() const;
+        
     private:
         void clear();
         bool isEmpty() const;
diff --git a/WebCore/platform/cf/FileSystemCF.cpp b/WebCore/platform/cf/FileSystemCF.cpp
new file mode 100644 (file)
index 0000000..b6cc645
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+#import "config.h"
+#import "FileSystem.h"
+
+#import "CString.h"
+#import "PlatformString.h"
+#import <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+CString fileSystemRepresentation(const String& path)
+{
+    RetainPtr<CFStringRef> cfString(AdoptCF, path.createCFString());
+
+    if (!cfString)
+        return CString();
+
+    CFIndex size = CFStringGetMaximumSizeOfFileSystemRepresentation(cfString.get());
+
+    char* buffer;
+    CString string = CString::newUninitialized(size, buffer);
+
+    if (!CFStringGetFileSystemRepresentation(cfString.get(), buffer, size)) {
+        LOG_ERROR("Failed to get filesystem representation to create CString from cfString");
+        return CString();
+    }
+
+    return string;
+}
+
+} // namespace WebCore
index fb0cbf2..ae6f728 100644 (file)
@@ -116,6 +116,9 @@ public:
     virtual void setToolTip(const String&) { }
 
     virtual void print(Frame*) { }
+
+    virtual bool runDatabaseSizeLimitPrompt(Frame*, const String&) { return false; }
+
 };
 
 class SVGEmptyFrameLoaderClient : public FrameLoaderClient {
index e4aa046..98f85bb 100644 (file)
 
 namespace WebCore {
 
-bool fileExists(const String& path) 
+String homeDirectoryPath()
 {
-    const char* fsRep = [(NSString *)path fileSystemRepresentation];
-        
-    if (!fsRep || fsRep[0] == '\0')
-        return false;
-        
-    struct stat fileInfo;
-
-    // stat(...) returns 0 on successful stat'ing of the file, and non-zero in any case where the file doesn't exist or cannot be accessed
-    return !stat(fsRep, &fileInfo);
-}
-
-bool deleteFile(const String& path) 
-{
-    const char* fsRep = [(NSString *)path fileSystemRepresentation];
-        
-    if (!fsRep || fsRep[0] == '\0')
-        return false;
-        
-    // unlink(...) returns 0 on successful deletion of the path and non-zero in any other case (including invalid permissions or non-existent file)
-    return !unlink(fsRep);
-}
-
-bool fileSize(const String& path, long long& result)
-{
-    const char* fsRep = [(NSString *)path fileSystemRepresentation];
-    
-    if (!fsRep || fsRep[0] == '\0')
-        return false;
-    
-    struct stat fileInfo;
-    
-    if (!stat(fsRep, &fileInfo))
-        return false;
-    
-    result = fileInfo.st_size;
-    return true;
+    return NSHomeDirectory();
 }
 
-} //namespace WebCore
+} // namespace WebCore
diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp
new file mode 100644 (file)
index 0000000..972bfe4
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007 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 "FileSystem.h"
+
+#include "CString.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+bool fileExists(const String& path)
+{
+    if (path.isNull())
+        return false;
+
+    CString fsRep = fileSystemRepresentation(path);
+
+    if (!fsRep.data() || fsRep.data()[0] == '\0')
+        return false;
+
+    struct stat fileInfo;
+
+    // stat(...) returns 0 on successful stat'ing of the file, and non-zero in any case where the file doesn't exist or cannot be accessed
+    return !stat(fsRep.data(), &fileInfo);
+}
+
+bool deleteFile(const String& path)
+{
+    CString fsRep = fileSystemRepresentation(path);
+
+    if (!fsRep.data() || fsRep.data()[0] == '\0')
+        return false;
+
+    // unlink(...) returns 0 on successful deletion of the path and non-zero in any other case (including invalid permissions or non-existent file)
+    return !unlink(fsRep.data());
+}
+
+bool fileSize(const String& path, long long& result)
+{
+    CString fsRep = fileSystemRepresentation(path);
+
+    if (!fsRep.data() || fsRep.data()[0] == '\0')
+        return false;
+
+    struct stat fileInfo;
+
+    if (stat(fsRep.data(), &fileInfo))
+        return false;
+
+    result = fileInfo.st_size;
+    return true;
+}
+
+String pathByAppendingComponent(const String& path, const String& component)
+{
+    if (path.endsWith("/"))
+        return path + component;
+    else
+        return path + "/" + component;
+}
+
+bool makeAllDirectories(const String& path)
+{
+    CString fullPath = fileSystemRepresentation(path);
+    if (!access(fullPath.data(), F_OK))
+        return true;
+
+    char* p = fullPath.mutableData() + 1;
+    int length = fullPath.length();
+
+    if(p[length - 1] == '/')
+        p[length - 1] = '\0';
+    for (; *p; ++p)
+        if (*p == '/') {
+            *p = '\0';
+            if (access(fullPath.data(), F_OK))
+                if (mkdir(fullPath.data(), S_IRWXU))
+                    return false;
+            *p = '/';
+        }
+    if (access(fullPath.data(), F_OK))
+        if (mkdir(fullPath.data(), S_IRWXU))
+            return false;
+
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/sql/SQLAuthorizer.cpp b/WebCore/platform/sql/SQLAuthorizer.cpp
new file mode 100644 (file)
index 0000000..4451843
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition
+ * 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 "SQLAuthorizer.h"
+
+#include <sqlite3.h>
+
+namespace WebCore {
+
+const int SQLAuthAllow = SQLITE_OK;
+const int SQLAuthIgnore = SQLITE_IGNORE;
+const int SQLAuthDeny = SQLITE_DENY;
+
+} // namespace WebCore
diff --git a/WebCore/platform/sql/SQLAuthorizer.h b/WebCore/platform/sql/SQLAuthorizer.h
new file mode 100644 (file)
index 0000000..5acc0db
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition
+ * 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.
+ */
+#ifndef SQLAuthorizer_h
+#define SQLAuthorizer_h
+
+#include "Threading.h"
+
+namespace WebCore {
+
+class String;
+
+extern const int SQLAuthAllow;
+extern const int SQLAuthIgnore;
+extern const int SQLAuthDeny;
+
+class SQLAuthorizer : public ThreadSafeShared<SQLAuthorizer> {
+public:
+    virtual ~SQLAuthorizer() { }
+
+    virtual int createTable(const String& tableName) { return SQLAuthAllow; }
+    virtual int createTempTable(const String& tableName) { return SQLAuthAllow; }
+    virtual int dropTable(const String& tableName) { return SQLAuthAllow; }
+    virtual int dropTempTable(const String& tableName) { return SQLAuthAllow; }
+    virtual int allowAlterTable(const String& databaseName, const String& tableName) { return SQLAuthAllow; }
+
+    virtual int createIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; }
+    virtual int createTempIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; }
+    virtual int dropIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; }
+    virtual int dropTempIndex(const String& indexName, const String& tableName) { return SQLAuthAllow; }
+
+    virtual int createTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; }
+    virtual int createTempTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; }
+    virtual int dropTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; }
+    virtual int dropTempTrigger(const String& triggerName, const String& tableName) { return SQLAuthAllow; }
+
+    virtual int createView(const String& viewName) { return SQLAuthAllow; }
+    virtual int createTempView(const String& viewName) { return SQLAuthAllow; }
+    virtual int dropView(const String& viewName) { return SQLAuthAllow; }
+    virtual int dropTempView(const String& viewName) { return SQLAuthAllow; }
+
+    virtual int createVTable(const String& tableName, const String& moduleName) { return SQLAuthAllow; }
+    virtual int dropVTable(const String& tableName, const String& moduleName) { return SQLAuthAllow; }
+
+    virtual int allowDelete(const String& tableName) { return SQLAuthAllow; }
+    virtual int allowInsert(const String& tableName) { return SQLAuthAllow; }
+    virtual int allowUpdate(const String& tableName, const String& columnName) { return SQLAuthAllow; }
+    virtual int allowTransaction() { return SQLAuthAllow; }
+
+    virtual int allowSelect() { return SQLAuthAllow; }
+    virtual int allowRead(const String& tableName, const String& columnName) { return SQLAuthAllow; }
+
+    virtual int allowAttach(const String& filename) { return SQLAuthAllow; }
+    virtual int allowDetach(const String& databaseName) { return SQLAuthAllow; }
+
+    virtual int allowReindex(const String& indexName) { return SQLAuthAllow; }
+    virtual int allowAnalyze(const String& tableName) { return SQLAuthAllow; }
+    virtual int allowFunction(const String& functionName) { return SQLAuthAllow; }
+    virtual int allowPragma(const String& pragmaName, const String& firstArgument) { return SQLAuthAllow; }
+};
+
+} // namespace WebCore
+
+#endif // SQLAuthorizer_h
diff --git a/WebCore/platform/sql/SQLValue.cpp b/WebCore/platform/sql/SQLValue.cpp
new file mode 100644 (file)
index 0000000..7e178f9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition
+ * 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 "SQLValue.h"
+
+namespace WebCore {
+
+SQLValue::SQLValue(const SQLValue& val)
+{
+    m_number = val.m_number;
+    m_string = val.m_string.copy();
+    m_type = val.m_type;
+}
+
+String SQLValue::string() const
+{
+    ASSERT(m_type == StringValue);
+
+    // Must return a copy since ref-shared Strings are not thread safe
+    return m_string.copy();
+}
+
+double SQLValue::number() const
+{
+    ASSERT(m_type == NumberValue);
+
+    return m_number;
+}
+
+}
diff --git a/WebCore/platform/sql/SQLValue.h b/WebCore/platform/sql/SQLValue.h
new file mode 100644 (file)
index 0000000..ae2432d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition
+ * 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.
+ */
+
+#ifndef SQLValue_h
+#define SQLValue_h
+
+#include "PlatformString.h"
+#include "Threading.h"
+
+namespace WebCore {
+
+    class SQLValue {
+    public:
+        enum Type { NullValue, NumberValue, StringValue };
+
+        SQLValue() : m_type(NullValue) { }
+        SQLValue(double number) : m_type(NumberValue), m_number(number) { }
+        SQLValue(const String& s) : m_type(StringValue), m_string(s) { }
+        SQLValue(const SQLValue&);
+
+        Type type() const { return m_type; }
+
+        String string() const;
+        double number() const;
+
+    private:
+        Type m_type;
+        double m_number;
+        String m_string;
+    };
+};
+
+#endif
index 8daca20..578f9e9 100644 (file)
@@ -1,62 +1,98 @@
-/*
- * Copyright (C) 2007 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 "FileSystem.h"
-#include "PlatformString.h"
-
-#include <sys/stat.h>
-
-namespace WebCore {
-
-bool fileSize(const String& path, long long& result)
-{
-    struct _stat32i64 sb;
-    String filename = path;
-    int statResult = _wstat32i64(filename.charactersWithNullTermination(), &sb);
-    if (statResult != 0 || (sb.st_mode & S_IFMT) != S_IFREG)
-        return false;
-    result = sb.st_size;
-    return true;
-}
-
-bool fileExists(const String& path) 
-{
-    struct _stat32i64 sb;
-    String filename = path;
-    return !_wstat32i64(filename.charactersWithNullTermination(), &sb);
-}
-
-bool deleteFile(const String& path)
-{
-    String filename = path;
-    return !!DeleteFileW(filename.charactersWithNullTermination());
-}
-
-}
+/*\r
+ * Copyright (C) 2007 Apple Inc. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1.  Redistributions of source code must retain the above copyright\r
+ *     notice, this list of conditions and the following disclaimer. \r
+ * 2.  Redistributions in binary form must reproduce the above copyright\r
+ *     notice, this list of conditions and the following disclaimer in the\r
+ *     documentation and/or other materials provided with the distribution. \r
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of\r
+ *     its contributors may be used to endorse or promote products derived\r
+ *     from this software without specific prior written permission. \r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY\r
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\r
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include "config.h"\r
+#include "FileSystem.h"\r
+\r
+#include "CString.h"\r
+#include "NotImplemented.h"\r
+#include "PlatformString.h"\r
+\r
+#include <windows.h>\r
+#include <winbase.h>\r
+#include <shlobj.h>\r
+\r
+namespace WebCore {\r
+\r
+bool fileSize(const String& path, long long& result)\r
+{\r
+    struct _stat32i64 sb;\r
+    String filename = path;\r
+    int statResult = _wstat32i64(filename.charactersWithNullTermination(), &sb);\r
+    if (statResult != 0 || (sb.st_mode & S_IFMT) != S_IFREG)\r
+        return false;\r
+    result = sb.st_size;\r
+    return true;\r
+}\r
+\r
+bool fileExists(const String& path) \r
+{\r
+    struct _stat32i64 sb;\r
+    String filename = path;\r
+    return !_wstat32i64(filename.charactersWithNullTermination(), &sb);\r
+}\r
+\r
+bool deleteFile(const String& path)\r
+{\r
+    String filename = path;\r
+    return !!DeleteFileW(filename.charactersWithNullTermination());\r
+}\r
+\r
+String pathByAppendingComponent(const String& path, const String& component)\r
+{\r
+    if (path.endsWith("\\"))\r
+        return path + component;\r
+    else\r
+        return path + "\\" + component;\r
+}\r
+\r
+CString fileSystemRepresentation(const String&)\r
+{\r
+    return "";\r
+}\r
+\r
+bool makeAllDirectories(const String& path)\r
+{\r
+    String fullPath = path;\r
+    if (!SHCreateDirectoryEx(0, fullPath.charactersWithNullTermination(), 0)) {\r
+        DWORD error = GetLastError();\r
+        if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) {\r
+            LOG_ERROR("Failed to create path %s", path.ascii().data());\r
+            return false;\r
+        }\r
+    }\r
+    return true;\r
+}\r
+\r
+String homeDirectoryPath()\r
+{\r
+    notImplemented();\r
+    return "";\r
+}\r
+\r
+} // namespace WebCore\r
diff --git a/WebCore/storage/Database.cpp b/WebCore/storage/Database.cpp
new file mode 100644 (file)
index 0000000..2c552f3
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2007 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 "CString.h"
+#include "DatabaseAuthorizer.h"
+#include "DatabaseCallback.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 "SQLCallback.h"
+#include "SQLDatabase.h"
+#include "SQLResultSet.h"
+#include "SQLStatement.h"
+#include "VersionChangeCallback.h"
+
+namespace WebCore {
+
+Mutex& Database::globalCallbackMutex()
+{
+    static Mutex mutex;
+    return mutex;
+}
+
+HashSet<RefPtr<Database> >& Database::globalCallbackSet()
+{
+    static HashSet<RefPtr<Database> > set;
+    return set;
+}
+
+bool Database::s_globalCallbackScheduled = false;
+
+Mutex& Database::guidMutex()
+{
+    static Mutex mutex;
+    return mutex;
+}
+
+HashMap<int, String>& Database::guidToVersionMap()
+{
+    static HashMap<int, String> map;
+    return map;
+}
+
+HashMap<int, HashSet<Database*>*>& Database::guidToDatabaseMap()
+{
+    static HashMap<int, HashSet<Database*>*> map;
+    return map;
+}
+
+const String& Database::databaseInfoTableName()
+{
+    static String name = "__WebKitDatabaseInfoTable__";
+    return name;
+}
+
+static const String& databaseVersionKey()
+{
+    static String key = "WebKitDatabaseVersionKey";
+    return key;
+}
+
+PassRefPtr<Database> Database::openDatabase(Document* document, const String& name, const String& expectedVersion, ExceptionCode& e)
+{
+    RefPtr<Database> database = 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;
+    }
+
+    if (Page* page = document->frame()->page())
+        page->inspectorController()->didOpenDatabase(database.get(), document->securityOrigin().toString(), name, expectedVersion);
+
+    return database;
+}
+
+Database::Database(Document* document, const String& name, const String& expectedVersion)
+    : m_document(document)
+    , m_name(name.copy())
+    , m_guid(0)
+    , m_expectedVersion(expectedVersion)
+    , m_databaseThread(0)
+{
+    ASSERT(document);
+
+    // FIXME: Right now, this is the entire domain of the document, when it really needs to be scheme/host/port only
+    m_securityOrigin = document->securityOrigin();
+
+    if (m_name.isNull())
+        m_name = "";
+
+    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);
+    }
+
+    {
+        MutexLocker locker(m_databaseThreadMutex);
+        m_databaseThread = document->databaseThread();
+        ASSERT(m_databaseThread);
+    }
+
+    m_filename = DatabaseTracker::tracker().fullPathForDatabase(m_securityOrigin.toString(), m_name);
+}
+
+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;
+        ASSERT(guidToVersionMap().contains(m_guid));
+        guidToVersionMap().remove(m_guid);
+    }
+}
+
+bool Database::openAndVerifyVersion(ExceptionCode& e)
+{
+    // Open the main thread connection to the database
+    if (!m_mainSQLDatabase.open(m_filename)) {
+        LOG_ERROR("Unable to open database at path %s", m_filename.ascii().data());
+        e = INVALID_STATE_ERR;
+        return false;
+    }
+
+    m_databaseAuthorizer = new DatabaseAuthorizer();
+    m_mainSQLDatabase.setAuthorizer(m_databaseAuthorizer);
+
+    // Open the background thread connection
+    RefPtr<DatabaseOpenTask> task = new DatabaseOpenTask();
+
+    task->lockForSynchronousScheduling();
+    m_databaseThread->scheduleImmediateTask(this, task.get());
+    task->waitForSynchronousCompletion();
+
+    ASSERT(task->isComplete());
+    e = task->exceptionCode();
+    return task->openSuccessful();
+}
+
+
+static bool retrieveTextResultFromDatabase(SQLDatabase& db, const String& query, String& resultString)
+{
+    SQLStatement 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.getColumnText16(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)
+{
+    static String getVersionQuery = "SELECT value FROM " + databaseInfoTableName() + " WHERE key = '" + databaseVersionKey() + "';";
+
+    m_databaseAuthorizer->disable();
+
+    bool result = retrieveTextResultFromDatabase(m_threadSQLDatabase, 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(SQLDatabase& db, const String& query, const String& value)
+{
+    SQLStatement 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.bindText16(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)
+{
+    static String setVersionQuery = "INSERT INTO " + databaseInfoTableName() + " (key, value) VALUES ('" + databaseVersionKey() + "', ?);";
+
+    m_databaseAuthorizer->disable();
+
+    bool result = setTextValueInDatabase(m_threadSQLDatabase, 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;
+}
+
+void Database::databaseThreadGoingAway()
+{
+    // FIXME: We might not need this anymore
+
+    LOG(StorageAPI, "Database thread is going away for database %p\n", this);
+}
+
+void Database::disableAuthorizer()
+{
+    ASSERT(m_databaseAuthorizer);
+    m_databaseAuthorizer->disable();
+}
+
+void Database::enableAuthorizer()
+{
+    ASSERT(m_databaseAuthorizer);
+    m_databaseAuthorizer->enable();
+}
+
+int Database::guidForOriginAndName(const String& origin, const String& name)
+{
+    static int currentNewGUID = 1;
+    static Mutex stringIdentifierMutex;
+    static HashMap<String, int> stringIdentifierToGUIDMap;
+
+    String stringID;
+    if (origin.endsWith("/"))
+        stringID = origin + name;
+    else
+        stringID = origin + "/" + name;
+
+    MutexLocker locker(stringIdentifierMutex);
+    int guid = stringIdentifierToGUIDMap.get(stringID);
+    if (!guid) {
+        guid = currentNewGUID++;
+        stringIdentifierToGUIDMap.set(stringID, guid);
+    }
+
+    return guid;
+}
+
+void Database::resetAuthorizer()
+{
+    if (m_databaseAuthorizer)
+        m_databaseAuthorizer->reset();
+}
+
+void Database::performPolicyChecks()
+{
+    // FIXME: Code similar to the following will need to be run to enforce the per-origin size limit the spec mandates.
+    // Additionally, we might need a way to pause the database thread while the UA prompts the user for permission to
+    // increase the size limit
+
+    /*
+    if (m_databaseAuthorizer->lastActionIncreasedSize())
+        DatabaseTracker::scheduleFileSizeCheckOnMainThread(this);
+    */
+
+    notImplemented();
+}
+
+bool Database::performOpenAndVerify(ExceptionCode& e)
+{
+    if (!m_threadSQLDatabase.open(m_filename)) {
+        LOG_ERROR("Unable to open database at path %s", m_filename.ascii().data());
+        e = INVALID_STATE_ERR;
+        return false;
+    }
+
+    ASSERT(m_databaseAuthorizer);
+    m_threadSQLDatabase.setAuthorizer(m_databaseAuthorizer);
+
+    if (!m_threadSQLDatabase.executeCommand("CREATE TABLE IF NOT EXISTS " + databaseInfoTableName() + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
+        LOG_ERROR("Unable to create table %s in database %s", databaseInfoTableName().ascii().data(), databaseDebugName().ascii().data());
+        e = INVALID_STATE_ERR;
+        return false;
+    }
+
+
+    String currentVersion;
+    {
+        MutexLocker locker(guidMutex());
+        currentVersion = guidToVersionMap().get(m_guid);
+
+
+        if (currentVersion.isNull())
+            LOG(StorageAPI, "Current cached version for guid %i is null", m_guid);
+        else
+            LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data());
+
+        if (currentVersion.isNull()) {
+            if (!getVersionFromDatabase(currentVersion)) {
+                LOG_ERROR("Failed to get current version from database %s", databaseDebugName().ascii().data());
+                e = INVALID_STATE_ERR;
+                return false;
+            }
+            if (currentVersion.length()) {
+                LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
+            } else {
+                LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
+                if (!setVersionInDatabase(m_expectedVersion)) {
+                    LOG_ERROR("Failed to set version %s in database %s", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
+                    e = INVALID_STATE_ERR;
+                    return false;
+                }
+
+                currentVersion = m_expectedVersion;
+            }
+
+            guidToVersionMap().set(m_guid, currentVersion.copy());
+        }
+    }
+
+    if (currentVersion.isNull()) {
+        LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data());
+        currentVersion = "";
+    }
+
+    // FIXME: For now, the spec says that if the database has no version, it is valid for any "Expected version" string.  That seems silly and I think it should be
+    // changed, and here's where we would change it
+    if (m_expectedVersion.length()) {
+        if (currentVersion.length() && m_expectedVersion != currentVersion) {
+            LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(),
+                databaseDebugName().ascii().data(), currentVersion.ascii().data());
+            e = INVALID_STATE_ERR;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void Database::scheduleDatabaseCallback(DatabaseCallback* callback)
+{
+    ASSERT(callback);
+    MutexLocker locker(globalCallbackMutex());
+    {
+        MutexLocker locker(m_callbackMutex);
+        m_pendingCallbacks.append(callback);
+        globalCallbackSet().add(this);
+        if (!s_globalCallbackScheduled) {
+            callOnMainThread(deliverAllPendingCallbacks);
+            s_globalCallbackScheduled = true;
+        }
+    }
+}
+
+void Database::performChangeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<VersionChangeCallback> callback)
+{
+    // FIXME: "user agent must obtain a full lock of the database (waiting for all open transactions to be closed)"
+    // Currently, not having implemented the implicit thread transaction, we're not all too worried about this.
+    // Once the transaction is implemented, we'll have to find a way to reschedule the changeVersion over and over as long as
+    // transactions are active.  Keep on bumping it to second in line, or something!
+
+    bool result = true;
+
+    MutexLocker locker(guidMutex());
+    {
+        // Run this code in a block to guarantee that actualVersion goes out of scope before the mutex
+        // is released, so we can avoid copying the string when inserting but still avoid
+        // string thread-safety issues
+        String actualVersion;
+        if (!getVersionFromDatabase(actualVersion)) {
+            LOG_ERROR("Unable to retrieve actual current version from database");
+            result = false;
+        }
+
+        if (result && actualVersion != oldVersion) {
+            LOG_ERROR("Old version doesn't match actual version");
+            result = false;
+        }
+
+        if (result && !setVersionInDatabase(newVersion)) {
+            LOG_ERROR("Unable to set new version in database");
+            result = false;
+        }
+
+        if (result)
+            guidToVersionMap().set(m_guid, actualVersion);
+    }
+
+    scheduleDatabaseCallback(new DatabaseChangeVersionCallback(callback, result));
+}
+
+void Database::performExecuteSql(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLCallback> callback)
+{
+    ASSERT(callback);
+
+    RefPtr<SQLResultSet> resultSet = new SQLResultSet;
+    bool succeeded = true;
+
+    m_databaseAuthorizer->reset();
+
+    SQLStatement statement(m_threadSQLDatabase, sqlStatement);
+    int result = statement.prepare();
+    if (result != SQLResultOk) {
+        LOG(StorageAPI, "Failed to prepare sql query '%s' - error was: %s", sqlStatement.ascii().data(), statement.lastErrorMsg());
+        succeeded = false;
+        resultSet->setErrorCode(1);
+        resultSet->setErrorMessage(m_threadSQLDatabase.lastErrorMsg());
+    }
+
+    if (succeeded) {
+        for (unsigned i = 0; i < arguments.size(); ++i) {
+            if (statement.bindValue(i + 1, arguments[i]) != SQLResultOk) {
+                LOG(StorageAPI, "Failed to bind value index %i to statement for query '%s'", i + 1, sqlStatement.ascii().data());
+                // FIXME: Mark the transaction invalid here once we implement the transaction part of the spec
+                succeeded = false;
+                resultSet->setErrorCode(1);
+                resultSet->setErrorMessage(m_threadSQLDatabase.lastErrorMsg());
+                break;
+            }
+        }
+    }
+
+    // Step so we can fetch the column names.
+    result = statement.step();
+    if (result == SQLResultRow && succeeded) {
+        int columnCount = statement.columnCount();
+        SQLResultSetRowList* rows = resultSet->rows();
+
+        for (int i = 0; i < columnCount; i++)
+            rows->addColumn(statement.getColumnName16(i));
+
+        do {
+            for (int i = 0; i < columnCount; i++) {
+                // FIXME: Look at the column type
+                rows->addResult(statement.getColumnText16(i));
+            }
+
+            result = statement.step();
+        } while (result == SQLResultRow);
+
+        if (result != SQLResultDone) {
+            resultSet->setErrorCode(1);
+            resultSet->setErrorMessage(m_threadSQLDatabase.lastErrorMsg());
+            succeeded = false;
+        }
+    } else if (result == SQLResultDone && succeeded) {
+        // Didn't find anything, or was an insert
+        if (m_databaseAuthorizer->lastActionWasInsert())
+            resultSet->setInsertId(m_threadSQLDatabase.lastInsertRowID());
+    } else if (succeeded) {
+        // A new error occured on the first step of the statement - record it here
+        resultSet->setErrorCode(1);
+        resultSet->setErrorMessage(m_threadSQLDatabase.lastErrorMsg());
+        succeeded = false;
+    }
+
+    // FIXME: If the spec allows triggers, and we want to be "accurate" in a different way, we'd use
+    // sqlite3_total_changes() here instead of sqlite3_changed, because that includes rows modified from within a trigger
+    // For now, this seems sufficient
+    if (succeeded)
+        resultSet->setRowsAffected(m_threadSQLDatabase.lastChanges());
+
+    scheduleDatabaseCallback(new DatabaseExecuteSqlCallback(callback, resultSet.release()));
+}
+
+void Database::performCloseTransaction()
+{
+    notImplemented();
+}
+
+Vector<String> Database::performGetTableNames()
+{
+    disableAuthorizer();
+
+    SQLStatement statement(m_threadSQLDatabase, "SELECT name FROM sqlite_master WHERE type='table';");
+    if (statement.prepare() != SQLResultOk) {
+        LOG_ERROR("Unable to retrieve list of tables for database %s", databaseDebugName().ascii().data());
+        enableAuthorizer();
+        return Vector<String>();
+    }
+
+    Vector<String> tableNames;
+    int result;
+    while ((result = statement.step()) == SQLResultRow) {
+        String name = statement.getColumnText16(0);
+        if (name != databaseInfoTableName())
+            tableNames.append(name);
+    }
+
+    enableAuthorizer();
+
+    if (result != SQLResultDone) {
+        LOG_ERROR("Error getting tables for database %s", databaseDebugName().ascii().data());
+        return Vector<String>();
+    }
+
+    return tableNames;
+}
+
+String Database::version() const
+{
+    MutexLocker locker(guidMutex());
+    return guidToVersionMap().get(m_guid).copy();
+}
+
+void Database::changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<VersionChangeCallback> callback)
+{
+    ASSERT(m_databaseThread);
+    m_databaseThread->scheduleTask(this, new DatabaseChangeVersionTask(oldVersion, newVersion, callback));
+}
+
+void Database::executeSql(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLCallback> callback, ExceptionCode& e)
+{
+    // 4.11.3 Step 1 - Statement and argument validation
+    // FIXME: Currently the best way we have to validate the statement is to create an actual SQLStatement and prepare it.  We can't prepare on
+    // the main thread and run on the worker thread, because the worker thread might be in the middle of database activity.  So we have two options
+    // 1 - Break up the executeSql task into two steps.  Step 1 is prepare the statement on the background thread while the main thread waits.  If
+    //     the statement is valid, the main thread can return and step 2 would continue asynchronously, actually running the statement and generating results
+    //     The synchronous step 1 could "cut in line", but the main thread could still block waiting for any currently running query to complete
+    // 2 - Keep a main thread connection around, and keep a worker thread connection around.  The main thread connection will be used solely to prepare
+    //     statements, checking them for validity.  After a statement is clear,  the work can be scheduled on the background thread.  This way, if there is a
+    //     read-only query running on the background thread, the main thread can simultaneously do the prepare on the main thread and there will be no
+    //     contention.  This is an advantage over #1.  A disadvantage is that between the prepare on the main thread and actually performing the query on the
+    //     background thread, there is a time window where the schema could change and the statement is no longer valid.
+    // 3 - A much more complex, less tested, but possibly premium solution is to do #1, but combine it with the use of the sqlite_busy_handler.  This would allow
+    //     any long-running queries to periodically check and see if there's anything they need to do.  The sqlite3 docs claim sqlite is theoretically reentrant,
+    //     and therefore a statement could be prepared inside a busy handler, if just to check for validation.  But it is also likely untested, and is not recc.
+    //     Testing must be done on this possibility before going forward with it
+    //
+    //     For now, I'm going with solution #2, as it is easiest to implement and the true badness of its "con" is dubious.
+
+    SQLStatement statement(m_mainSQLDatabase, sqlStatement);
+    int result = statement.prepare();
+
+    // Workaround for <rdar://problem/5537019> - a prepare on 1 connection immediately after a statement that changes the schema on the second connection
+    // can fail with a SQLResultSchema error.  Trying to prepare it a second time will succeed, assuming it is actually a valid statement
+    if (result == SQLResultSchema) {
+        statement.finalize();
+        result = statement.prepare();
+    }
+
+    if (result != SQLResultOk) {
+        LOG(StorageAPI, "Unable to verify correctness of statement %s - error %i (%s)", sqlStatement.ascii().data(), result, statement.lastErrorMsg());
+        e = SYNTAX_ERR;
+        return;
+    }
+
+    // FIXME:  If the statement uses the ?### syntax supported by sqlite, the bind parameter count is very likely off from the number of question marks.
+    // If this is the case, they might be trying to do something fishy or malicious
+    if (statement.bindParameterCount() != arguments.size()) {
+        LOG(StorageAPI, "Bind parameter count doesn't match number of question marks - someone's trying to use the ?### format and this might be bad");
+        e = SYNTAX_ERR;
+        return;
+    }
+
+    statement.finalize();
+
+    // FIXME: There is one remaining error with the above procedure.  The statement might have ?### style binds in it that will still escape the above checks
+    // For example, a statement with "?2 ?2" in it will have 2 question marks, a bind parameter count of 2, but bind number 1 will not be valid.
+    // To catch this, we either need to do a dry run of bindings here (which might be expensive), or do some manual parsing to make sure ?### isn't used at all
+
+    // FIXME: Haven't yet implemented the thread global transaction due to ambiguity/churn in the spec
+    // 4.11.3 Step 2 - Assign existing transaction or begin a new one to "transaction" associated with this statement
+
+    // FIXME: Haven't yet implemented the thread global transaction due to ambiguity/churn in the spec
+    // 4.11.3 Step 3 - If "transaction" is marked as bad, throw "INVALID_STATE_ERR" exception
+
+    ASSERT(m_databaseThread);
+    m_databaseThread->scheduleTask(this, new DatabaseExecuteSqlTask(sqlStatement, arguments, callback));
+}
+
+void Database::closeTransaction()
+{
+    // FIXME: Haven't yet implemented the thread global transaction due to ambiguity/churn in the spec
+    notImplemented();
+}
+
+void Database::deliverAllPendingCallbacks()
+{
+    Vector<RefPtr<Database> > databases;
+    {
+        MutexLocker locker(globalCallbackMutex());
+        copyToVector(globalCallbackSet(), databases);
+        globalCallbackSet().clear();
+        s_globalCallbackScheduled = false;
+    }
+
+    LOG(StorageAPI, "Having %u databases deliver their pending callbacks", databases.size());
+    for (unsigned i = 0; i < databases.size(); ++i)
+        databases[i]->deliverPendingCallbacks();
+}
+
+void Database::deliverPendingCallbacks()
+{
+    Vector<RefPtr<DatabaseCallback> > callbacks;
+    {
+        MutexLocker locker(m_callbackMutex);
+        callbacks.swap(m_pendingCallbacks);
+    }
+
+    LOG(StorageAPI, "Delivering %u callbacks for database %p", callbacks.size(), this);
+    for (unsigned i = 0; i < callbacks.size(); ++i)
+        callbacks[i]->performCallback();
+}
+
+Vector<String> Database::tableNames()
+{
+    RefPtr<DatabaseTableNamesTask> task = new DatabaseTableNamesTask();
+
+    task->lockForSynchronousScheduling();
+    m_databaseThread->scheduleImmediateTask(this, task.get());
+    task->waitForSynchronousCompletion();
+
+    return task->tableNames();
+}
+
+}
diff --git a/WebCore/storage/Database.h b/WebCore/storage/Database.h
new file mode 100644 (file)
index 0000000..4c5dbee
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef Database_h
+#define Database_h
+
+#include "PlatformString.h"
+#include "SecurityOrigin.h"
+#include "SQLDatabase.h"
+#include "StringHash.h"
+#include "Threading.h"
+#include "Timer.h"
+#include "VersionChangeCallback.h"
+
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Deque.h>
+
+namespace WebCore {
+
+class DatabaseAuthorizer;
+class DatabaseCallback;
+class DatabaseThread;
+class Document;
+class SQLCallback;
+class SQLResultSet;
+class SQLValue;
+
+typedef int ExceptionCode;
+
+class Database : public ThreadSafeShared<Database> {
+public:
+    ~Database();
+
+// Direct support for the DOM API
+    static PassRefPtr<Database> openDatabase(Document* document, const String& name, const String& expectedVersion, ExceptionCode&);
+
+    String version() const;
+    void changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<VersionChangeCallback> callback);
+
+    void executeSql(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLCallback> callback, ExceptionCode&);
+    void closeTransaction();
+
+// Internal engine support
+    void databaseThreadGoingAway();
+    static const String& databaseInfoTableName();
+
+    void disableAuthorizer();
+    void enableAuthorizer();
+
+    Vector<String> tableNames();
+
+    Document* document() const { return m_document; }
+    
+// Called from DatabaseThread, must be prepared to work on the background thread
+    void resetAuthorizer();
+    void performPolicyChecks();
+
+    bool performOpenAndVerify(ExceptionCode&);
+    void performChangeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<VersionChangeCallback> callback);
+    void performExecuteSql(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLCallback> callback);
+    void performCloseTransaction();
+    Vector<String> performGetTableNames();
+
+private:
+    Database(Document* document, const String& name, const String& expectedVersion);
+
+    bool openAndVerifyVersion(ExceptionCode&);
+    bool getVersionFromDatabase(String&);
+    bool setVersionInDatabase(const String&);
+
+    static void scheduleFileSizeTimerOnMainThread(Database*);
+    static void performScheduleFileSizeTimers();
+    void scheduleFileSizeTimer();
+    void sizeTimerFired(Timer<Database>*);
+    OwnPtr<Timer<Database> > m_sizeTimer;
+
+    static void deliverAllPendingCallbacks();
+    void deliverPendingCallbacks();
+
+    void scheduleDatabaseCallback(DatabaseCallback*);
+
+    // FIXME: Is it okay to reconcile hanging on to the raw pointer?  We definitely have to rely on
+    // Document telling DatabaseThread it's going away, and DatabaseThread telling Database its going away
+    Document* m_document;
+    SecurityOrigin m_securityOrigin;
+    String m_name;
+    int m_guid;
+    String m_expectedVersion;
+    String m_filename;
+
+    SQLDatabase m_mainSQLDatabase;
+    SQLDatabase m_threadSQLDatabase;
+    RefPtr<DatabaseAuthorizer> m_databaseAuthorizer;
+
+    Mutex m_databaseThreadMutex;
+    DatabaseThread* m_databaseThread;
+
+    Mutex m_callbackMutex;
+    Vector<RefPtr<DatabaseCallback> > m_pendingCallbacks;
+
+#ifndef NDEBUG
+    String databaseDebugName() const { return m_securityOrigin.toString() + "::" + m_name; }
+#endif
+
+    static Mutex& globalCallbackMutex();
+    static HashSet<RefPtr<Database> >& globalCallbackSet();
+    static bool s_globalCallbackScheduled;
+
+    static int guidForOriginAndName(const String&, const String&);
+
+    static Mutex& guidMutex();
+    static HashMap<int, String>& guidToVersionMap();
+    static HashMap<int, HashSet<Database*>*>& guidToDatabaseMap();
+};
+
+} // namespace WebCore
+
+#endif // Database_h
diff --git a/WebCore/storage/Database.idl b/WebCore/storage/Database.idl
new file mode 100644 (file)
index 0000000..6007089
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+module storage {
+
+    interface Database {
+        readonly attribute DOMString version;
+        [Custom] boolean changeVersion(in DOMString oldVersion, in DOMString newVersion, in VersionChangeCallback callback);
+        [Custom] void executeSql(in DOMString sqlStatement, arguments..., in SQLCallback callback);
+        void closeTransaction();
+    };
+
+}
diff --git a/WebCore/storage/DatabaseAuthorizer.cpp b/WebCore/storage/DatabaseAuthorizer.cpp
new file mode 100644 (file)
index 0000000..96a2f84
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2007 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 "DatabaseAuthorizer.h"
+
+#include "Database.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+DatabaseAuthorizer::DatabaseAuthorizer()
+    : m_securityEnabled(false)
+{
+    reset();
+}
+
+void DatabaseAuthorizer::reset()
+{
+    m_lastActionWasInsert = false;
+    m_lastActionIncreasedSize = false;
+}
+
+int DatabaseAuthorizer::createTable(const String& tableName)
+{
+    m_lastActionIncreasedSize = true;
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::createTempTable(const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::dropTable(const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::dropTempTable(const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::allowAlterTable(const String& databaseName, const String& tableName)
+{
+    m_lastActionIncreasedSize = true;
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::createIndex(const String& indexName, const String& tableName)
+{
+    m_lastActionIncreasedSize = true;
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::createTempIndex(const String& indexName, const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::dropIndex(const String& indexName, const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::dropTempIndex(const String& indexName, const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::createTrigger(const String& triggerName, const String& tableName)
+{
+    m_lastActionIncreasedSize = true;
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::createTempTrigger(const String& triggerName, const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::dropTrigger(const String& triggerName, const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::dropTempTrigger(const String& triggerName, const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::createVTable(const String& tableName, const String& moduleName)
+{
+    m_lastActionIncreasedSize = true;
+    return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
+}
+
+int DatabaseAuthorizer::dropVTable(const String& tableName, const String& moduleName)
+{
+    return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
+}
+
+int DatabaseAuthorizer::allowDelete(const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::allowInsert(const String& tableName)
+{
+    m_lastActionIncreasedSize = true;
+    m_lastActionWasInsert = true;
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::allowUpdate(const String& tableName, const String& columnName)
+{
+    m_lastActionIncreasedSize = true;
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::allowRead(const String& tableName, const String& columnName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::allowAnalyze(const String& tableName)
+{
+    return denyBasedOnTableName(tableName);
+}
+
+int DatabaseAuthorizer::allowPragma(const String& pragmaName, const String& firstArgument)
+{
+    return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
+}
+
+int DatabaseAuthorizer::allowAttach(const String& filename)
+{
+    return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
+}
+
+int DatabaseAuthorizer::allowDetach(const String& databaseName)
+{
+    return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow;
+}
+
+int DatabaseAuthorizer::allowFunction(const String& functionName)
+{
+    // FIXME: Are there any of these we need to prevent?  One might guess current_date, current_time, current_timestamp because
+    // they would violate the "sandbox environment" part of 4.11.3, but scripts can generate the local client side information via
+    // javascript directly, anyways.  Are there any other built-ins we need to be worried about?
+    return SQLAuthAllow;
+}
+
+void DatabaseAuthorizer::disable()
+{
+    m_securityEnabled = false;
+}
+
+void DatabaseAuthorizer::enable()
+{
+    m_securityEnabled = true;
+}
+
+int DatabaseAuthorizer::denyBasedOnTableName(const String& tableName)
+{
+    if (!m_securityEnabled)
+        return SQLAuthAllow;
+
+    // Sadly, normal creates and drops end up affecting sqlite_master in an authorizer callback, so
+    // it will be tough to enforce all of the following policies
+    //if (equalIgnoringCase(tableName, "sqlite_master") || equalIgnoringCase(tableName, "sqlite_temp_master") ||
+    //    equalIgnoringCase(tableName, "sqlite_sequence") || equalIgnoringCase(tableName, Database::databaseInfoTableName()))
+    //        return SQLAuthDeny;
+
+    if (equalIgnoringCase(tableName, Database::databaseInfoTableName()))
+        return SQLAuthDeny;
+
+    return SQLAuthAllow;
+}
+
+
+} // namespace WebCore
diff --git a/WebCore/storage/DatabaseAuthorizer.h b/WebCore/storage/DatabaseAuthorizer.h
new file mode 100644 (file)
index 0000000..a5ba91c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+#ifndef DatabaseAuthorizer_h
+#define DatabaseAuthorizer_h
+
+#include "SQLAuthorizer.h"
+
+namespace WebCore {
+
+class DatabaseAuthorizer : public SQLAuthorizer {
+public:
+    DatabaseAuthorizer();
+
+    virtual int createTable(const String& tableName);
+    virtual int createTempTable(const String& tableName);
+    virtual int dropTable(const String& tableName);
+    virtual int dropTempTable(const String& tableName);
+    virtual int allowAlterTable(const String& databaseName, const String& tableName);
+
+    virtual int createIndex(const String& indexName, const String& tableName);
+    virtual int createTempIndex(const String& indexName, const String& tableName);
+    virtual int dropIndex(const String& indexName, const String& tableName);
+    virtual int dropTempIndex(const String& indexName, const String& tableName);
+
+    virtual int createTrigger(const String& triggerName, const String& tableName);
+    virtual int createTempTrigger(const String& triggerName, const String& tableName);
+    virtual int dropTrigger(const String& triggerName, const String& tableName);
+    virtual int dropTempTrigger(const String& triggerName, const String& tableName);
+
+    virtual int createVTable(const String& tableName, const String& moduleName);
+    virtual int dropVTable(const String& tableName, const String& moduleName);
+
+    virtual int allowDelete(const String& tableName);
+    virtual int allowInsert(const String& tableName);
+    virtual int allowUpdate(const String& tableName, const String& columnName);
+
+    virtual int allowRead(const String& tableName, const String& columnName);
+
+    virtual int allowAnalyze(const String& tableName);
+    virtual int allowPragma(const String& pragmaName, const String& firstArgument);
+
+    virtual int allowAttach(const String& filename);
+    virtual int allowDetach(const String& databaseName);
+
+    virtual int allowFunction(const String& functionName);
+
+    void disable();
+    void enable();
+
+    void reset();
+
+    bool lastActionWasInsert() const { return m_lastActionWasInsert; }
+    bool lastActionIncreasedSize() const { return m_lastActionIncreasedSize; }
+private:
+    int denyBasedOnTableName(const String&);
+    bool m_securityEnabled;
+    bool m_lastActionWasInsert;
+    bool m_lastActionIncreasedSize;
+};
+
+} // namespace WebCore
+
+#endif // DatabaseAuthorizer_h
diff --git a/WebCore/storage/DatabaseCallback.cpp b/WebCore/storage/DatabaseCallback.cpp
new file mode 100644 (file)
index 0000000..7de7a1d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007 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 "DatabaseCallback.h"
+
+#include "SQLCallback.h"
+#include "SQLResultSet.h"
+#include "VersionChangeCallback.h"
+
+namespace WebCore {
+
+DatabaseChangeVersionCallback::DatabaseChangeVersionCallback(PassRefPtr<VersionChangeCallback> callback, bool versionChanged)
+    : m_callback(callback)
+    , m_versionChanged(versionChanged)
+{
+    ASSERT(callback->isThreadSafe());
+}
+
+void DatabaseChangeVersionCallback::performCallback()
+{
+    m_callback->handleEvent(m_versionChanged);
+}
+
+DatabaseExecuteSqlCallback::DatabaseExecuteSqlCallback(PassRefPtr<SQLCallback> callback, PassRefPtr<SQLResultSet> resultSet)
+    : m_callback(callback)
+    , m_resultSet(resultSet)
+{
+    ASSERT(callback->isThreadSafe());
+    ASSERT(resultSet->isThreadSafe());
+}
+
+void DatabaseExecuteSqlCallback::performCallback()
+{
+    m_callback->handleEvent(m_resultSet.get());
+}
+
+} // namespace WebCore
diff --git a/WebCore/storage/DatabaseCallback.h b/WebCore/storage/DatabaseCallback.h
new file mode 100644 (file)
index 0000000..4e0ba86
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef DatabaseCallback_h
+#define DatabaseCallback_h
+
+#include "Threading.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class SQLCallback;
+class SQLResultSet;
+class VersionChangeCallback;
+
+class DatabaseCallback : public ThreadSafeShared<DatabaseCallback> {
+public:
+    virtual ~DatabaseCallback() { }
+    virtual void performCallback() = 0;
+};
+
+class DatabaseChangeVersionCallback : public DatabaseCallback {
+public:
+    DatabaseChangeVersionCallback(PassRefPtr<VersionChangeCallback>, bool versionChanged);
+    virtual ~DatabaseChangeVersionCallback() { }
+    virtual void performCallback();
+
+private:
+    RefPtr<VersionChangeCallback> m_callback;
+    bool m_versionChanged;
+};
+
+class DatabaseExecuteSqlCallback : public DatabaseCallback {
+public:
+    DatabaseExecuteSqlCallback(PassRefPtr<SQLCallback>, PassRefPtr<SQLResultSet>);
+    virtual ~DatabaseExecuteSqlCallback() { }
+    virtual void performCallback();
+private:
+    RefPtr<SQLCallback> m_callback;
+    RefPtr<SQLResultSet> m_resultSet;
+};
+
+} // namespace WebCore
+
+#endif // DatabaseCallback_h
diff --git a/WebCore/storage/DatabaseTask.cpp b/WebCore/storage/DatabaseTask.cpp
new file mode 100644 (file)
index 0000000..1f597ef
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2007 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 "DatabaseTask.h"
+
+#include "Database.h"
+#include "Logging.h"
+#include "SQLValue.h"
+#include "SQLCallback.h"
+
+namespace WebCore {
+
+DatabaseTask::DatabaseTask()
+    : m_complete(false)
+    , m_synchronous(false)
+{
+}
+
+DatabaseTask::~DatabaseTask()
+{
+}
+
+void DatabaseTask::performTask(Database* db)
+{
+    // Database tasks are meant to be used only once, so make sure this one hasn't been performed before
+    ASSERT(!m_complete);
+
+    LOG(StorageAPI, "Performing DatabaseTask %p\n", this);
+
+    if (m_synchronous)
+        m_synchronousMutex.lock();
+
+    db->resetAuthorizer();
+    doPerformTask(db);
+    db->performPolicyChecks();
+
+    m_complete = true;
+
+    if (m_synchronous) {
+        m_synchronousCondition.signal();
+        m_synchronousMutex.unlock();
+    }
+}
+
+void DatabaseTask::lockForSynchronousScheduling()
+{
+    m_synchronousMutex.lock();
+    m_synchronous = true;
+}
+
+void DatabaseTask::waitForSynchronousCompletion()
+{
+    // Caller of this method must lock this object beforehand
+    ASSERT(m_synchronousMutex.tryLock() == false);
+
+    m_synchronousCondition.wait(m_synchronousMutex);
+    m_synchronous = false;
+    m_synchronousMutex.unlock();
+}
+
+// *** DatabaseOpenTask ***
+// Opens the database file and verifies the version matches the expected version
+
+DatabaseOpenTask::DatabaseOpenTask()
+    : DatabaseTask()
+    , m_code(0)
+    , m_success(false)
+{
+}
+
+void DatabaseOpenTask::doPerformTask(Database* db)
+{
+    m_success = db->performOpenAndVerify(m_code);
+}
+
+// *** DatabaseExecuteSqlTask ***
+// Runs the passed in sql query along with the arguments, and calls the callback with the results
+
+DatabaseExecuteSqlTask::DatabaseExecuteSqlTask(const String& query, const Vector<SQLValue>& arguments, PassRefPtr<SQLCallback> callback)
+    : DatabaseTask()
+    , m_query(query.copy())
+    , m_arguments(arguments)
+    , m_callback(callback)
+{
+    ASSERT(callback->isThreadSafe());
+}
+
+void DatabaseExecuteSqlTask::doPerformTask(Database* db)
+{
+    db->performExecuteSql(m_query, m_arguments, m_callback);
+}
+
+// *** DatabaseChangeVersionTask ***
+// Atomically verifies the current version is the same as the passed in "old version", and changes it to the new version
+
+DatabaseChangeVersionTask::DatabaseChangeVersionTask(const String& oldVersion, const String& newVersion, PassRefPtr<VersionChangeCallback> callback)
+    : m_oldVersion(oldVersion.copy())
+    , m_newVersion(newVersion.copy())
+    , m_callback(callback)
+{
+    ASSERT(callback->isThreadSafe());
+}
+
+void DatabaseChangeVersionTask::doPerformTask(Database* db)
+{
+    db->performChangeVersion(m_oldVersion, m_newVersion, m_callback);
+}
+
+// *** DatabaseTableNamesTask ***
+// Retrieves a list of all tables in the database - for WebInspector support
+
+DatabaseTableNamesTask::DatabaseTableNamesTask()
+{
+}
+
+void DatabaseTableNamesTask::doPerformTask(Database* db)
+{
+    m_tableNames = db->performGetTableNames();
+}
+
+
+} // namespace WebCore
diff --git a/WebCore/storage/DatabaseTask.h b/WebCore/storage/DatabaseTask.h
new file mode 100644 (file)
index 0000000..663ff91
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+#ifndef DatabaseTask_h
+#define DatabaseTask_h
+
+#include "ExceptionCode.h"
+#include "PlatformString.h"
+#include "Threading.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Database;
+class DatabaseThread;
+class SQLValue;
+class SQLCallback;
+class VersionChangeCallback;
+
+class DatabaseTask : public ThreadSafeShared<DatabaseTask>
+{
+    friend class Database;
+public:
+    virtual ~DatabaseTask();
+
+    void performTask(Database*);
+
+    bool isComplete() const { return m_complete; }
+protected:
+    DatabaseTask();
+    virtual void doPerformTask(Database* db) = 0;
+
+private:
+    void lockForSynchronousScheduling();
+    void waitForSynchronousCompletion();
+
+    bool m_complete;
+
+    Mutex m_synchronousMutex;
+    bool m_synchronous;
+    ThreadCondition m_synchronousCondition;
+};
+
+class DatabaseOpenTask : public DatabaseTask
+{
+public:
+    DatabaseOpenTask();
+
+    ExceptionCode exceptionCode() const { return m_code; }
+    bool openSuccessful() const { return m_success; }
+
+protected:
+    virtual void doPerformTask(Database* db);
+
+private:
+    ExceptionCode m_code;
+    bool m_success;
+};
+
+class DatabaseChangeVersionTask : public DatabaseTask
+{
+public:
+    DatabaseChangeVersionTask(const String& oldVersion, const String& newVersion, PassRefPtr<VersionChangeCallback>);
+
+protected:
+    virtual void doPerformTask(Database* db);
+
+private:
+    String m_oldVersion;
+    String m_newVersion;
+    RefPtr<VersionChangeCallback> m_callback;
+};
+
+class DatabaseExecuteSqlTask : public DatabaseTask
+{
+public:
+    DatabaseExecuteSqlTask(const String& query, const Vector<SQLValue>& arguments, PassRefPtr<SQLCallback> callback);
+
+protected:
+    virtual void doPerformTask(Database* db);
+
+private:
+    String m_query;
+    Vector<SQLValue> m_arguments;
+    RefPtr<SQLCallback> m_callback;
+};
+
+class DatabaseCloseTransactionTask: public DatabaseTask
+{
+public:
+    DatabaseCloseTransactionTask();
+
+protected:
+    virtual void doPerformTask(Database* db);
+};
+
+class DatabaseTableNamesTask : public DatabaseTask
+{
+public:
+    DatabaseTableNamesTask();
+
+    Vector<String>& tableNames() { return m_tableNames; }
+protected:
+    virtual void doPerformTask(Database* db);
+private:
+    Vector<String> m_tableNames;
+};
+
+} // namespace WebCore
+
+#endif // DatabaseTask_h
diff --git a/WebCore/storage/DatabaseThread.cpp b/WebCore/storage/DatabaseThread.cpp
new file mode 100644 (file)
index 0000000..87ef948
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2007 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 "DatabaseThread.h"
+
+#include "AutodrainedPool.h"
+#include "Database.h"
+#include "DatabaseTask.h"
+#include "Logging.h"
+
+namespace WebCore {
+
+DatabaseThread::DatabaseThread(Document* document)
+    : m_threadID(0)
+    , m_terminationRequested(false)
+{
+    m_selfRef = this;
+}
+
+DatabaseThread::~DatabaseThread()
+{
+    // FIXME: Any cleanup required here?  Since the thread deletes itself after running its detached course, I don't think so.  Lets be sure.
+}
+
+bool DatabaseThread::start()
+{
+    if (m_threadID)
+        return true;
+
+    m_threadID = createThread(DatabaseThread::databaseThreadStart, this);
+
+    return m_threadID;
+}
+
+void DatabaseThread::documentGoingAway()
+{
+    // This document is going away, so this thread is going away.
+    // -Clear records of all Databases out
+    // -Leave the thread main loop
+    // -Detach the thread so the thread itself runs out and releases all thread resources
+    // -Clear the RefPtr<> self so if noone else is hanging on the thread, the object itself is deleted.
+
+    LOG(StorageAPI, "Document owning DatabaseThread %p is going away - starting thread shutdown", this);
+
+    // Clear all database records out, and let Databases know that this DatabaseThread is going away
+    {
+        MutexLocker locker(m_databaseWorkMutex);
+
+        // FIXME - The policy we're enforcing right here is that when a document goes away, any pending
+        // sql queries that were queued up also go away.  Is this appropriate?
+
+        HashSet<RefPtr<Database> >::iterator i = m_activeDatabases.begin();
+        HashSet<RefPtr<Database> >::iterator end = m_activeDatabases.end();
+
+        for (; i != end; ++i) {
+            (*i)->databaseThreadGoingAway();
+            Deque<RefPtr<DatabaseTask> >* databaseQueue = m_databaseTaskQueues.get((*i).get());
+            ASSERT(databaseQueue);
+            m_databaseTaskQueues.remove((*i).get());
+            delete databaseQueue;
+        }
+        ASSERT(m_databaseTaskQueues.isEmpty());
+        m_activeDatabases.clear();
+    }
+
+    // Request the thread to cleanup and shutdown
+    m_terminationRequested = true;
+    wakeWorkThread();
+}
+
+void DatabaseThread::databaseGoingAway(Database* database)
+{
+    MutexLocker locker(m_databaseWorkMutex);
+    if (!m_activeDatabases.contains(database))
+        return;
+
+    // FIXME - The policy we're enforcing right here is that when a document goes away, any pending
+    // sql queries that were queued up also go away.  Is this appropriate?
+    Deque<RefPtr<DatabaseTask> >* databaseQueue = m_databaseTaskQueues.get(database);
+    ASSERT(databaseQueue);
+    m_databaseTaskQueues.remove(database);
+    delete databaseQueue;
+
+    m_activeDatabases.remove(database);
+}
+
+void* DatabaseThread::databaseThreadStart(void* vDatabaseThread)
+{
+    DatabaseThread* dbThread = static_cast<DatabaseThread*>(vDatabaseThread);
+    return dbThread->databaseThread();
+}
+
+void* DatabaseThread::databaseThread()
+{
+    LOG(StorageAPI, "Starting DatabaseThread %p", this);
+
+    while (!m_terminationRequested) {
+        m_threadMutex.unlock();
+        AutodrainedPool pool;
+
+        LOG(StorageAPI, "Iteration of main loop for DatabaseThread %p", this);
+
+        bool result;
+        do {
+            result = dispatchNextTaskIdentifier();
+            if (m_terminationRequested)
+                break;
+        } while(result);
+
+        if (m_terminationRequested)
+            break;
+
+        pool.cycle();
+        m_threadMutex.lock();
+        m_threadCondition.wait(m_threadMutex);
+    }
+    m_threadMutex.unlock();
+
+    LOG(StorageAPI, "About to detach thread %i and clear the ref to DatabaseThread %p, which currently has %i ref(s)", m_threadID, this, refCount());
+
+    // Detach the thread so its resources are no longer of any concern to anyone else
+    detachThread(m_threadID);
+
+    // Clear the self refptr, possibly resulting in deletion
+    m_selfRef = 0;
+
+    return 0;
+}
+
+bool DatabaseThread::dispatchNextTaskIdentifier()
+{
+    Database* workDatabase = 0;
+    RefPtr<DatabaseTask> task;
+
+    {
+        MutexLocker locker(m_databaseWorkMutex);
+        while (!task && m_globalQueue.size()) {
+            Database* database = m_globalQueue.first();
+            m_globalQueue.removeFirst();
+
+            Deque<RefPtr<DatabaseTask> >* databaseQueue = m_databaseTaskQueues.get(database);
+            ASSERT(databaseQueue || !m_activeDatabases.contains(database));
+            if (!databaseQueue)
+                continue;
+
+            ASSERT(databaseQueue->size());
+            task = databaseQueue->first();
+            workDatabase = database;
+            databaseQueue->removeFirst();
+        }
+    }
+
+    if (task) {
+        ASSERT(workDatabase);
+        workDatabase->resetAuthorizer();
+        task->performTask(workDatabase);
+        return true;
+    }
+
+    return false;
+}
+
+void DatabaseThread::scheduleTask(Database* database, DatabaseTask* task)
+{
+    if (m_terminationRequested) {
+        LOG(StorageAPI, "Attempted to schedule task %p from database %p on DatabaseThread %p after it was requested to terminate", task, database, this);
+        return;
+    }
+
+    MutexLocker locker(m_databaseWorkMutex);
+
+    Deque<RefPtr<DatabaseTask> >* databaseQueue = 0;
+
+    if (!m_activeDatabases.contains(database)) {
+        m_activeDatabases.add(database);
+        databaseQueue = new Deque<RefPtr<DatabaseTask> >;
+        m_databaseTaskQueues.set(database, databaseQueue);
+    }
+
+    if (!databaseQueue)
+        databaseQueue = m_databaseTaskQueues.get(database);
+
+    ASSERT(databaseQueue);
+
+    databaseQueue->append(task);
+    m_globalQueue.append(database);
+
+    wakeWorkThread();
+}
+
+void DatabaseThread::scheduleImmediateTask(Database* database, DatabaseTask* task)
+{
+    if (m_terminationRequested) {
+        LOG_ERROR("Attempted to schedule immediate task %p from database %p on DatabaseThread %p after it was requested to terminate", task, database, this);
+        return;
+    }
+    MutexLocker locker(m_databaseWorkMutex);
+
+    Deque<RefPtr<DatabaseTask> >* databaseQueue = 0;
+
+    if (!m_activeDatabases.contains(database)) {
+        m_activeDatabases.add(database);
+        databaseQueue = new Deque<RefPtr<DatabaseTask> >;
+        m_databaseTaskQueues.set(database, databaseQueue);
+    }
+
+    if (!databaseQueue)
+        databaseQueue = m_databaseTaskQueues.get(database);
+
+    ASSERT(databaseQueue);
+
+    databaseQueue->prepend(task);
+    m_globalQueue.prepend(database);
+
+    wakeWorkThread();
+}
+
+void DatabaseThread::wakeWorkThread()
+{
+    MutexLocker locker(m_threadMutex);
+    m_threadCondition.signal();
+}
+
+} // namespace WebCore
diff --git a/WebCore/storage/DatabaseThread.h b/WebCore/storage/DatabaseThread.h
new file mode 100644 (file)
index 0000000..1af5a25
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+#ifndef DatabaseThread_h
+#define DatabaseThread_h
+
+#include "Threading.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/Deque.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Database;
+class DatabaseTask;
+class Document;
+
+class DatabaseThread : public ThreadSafeShared<DatabaseThread>
+{
+public:
+    DatabaseThread(Document*);
+    ~DatabaseThread();
+
+    bool start();
+    void documentGoingAway();
+    void databaseGoingAway(Database*);
+
+    void scheduleTask(Database*, DatabaseTask*);
+    void scheduleImmediateTask(Database*, DatabaseTask*);
+private:
+    static void* databaseThreadStart(void*);
+    void* databaseThread();
+    void wakeWorkThread();
+    bool dispatchNextTaskIdentifier();
+
+    ThreadIdentifier m_threadID;
+    RefPtr<DatabaseThread> m_selfRef;
+
+    // For waking/sleeping the work thread
+    ThreadCondition m_threadCondition;
+    Mutex m_threadMutex;
+    bool m_terminationRequested;
+
+    // FIXME: Need a much better queue structure than the linked-list based queue being used
+
+    // Work unit and Database management
+    Mutex m_databaseWorkMutex;
+    HashMap<Database*, Deque<RefPtr<DatabaseTask> >*> m_databaseTaskQueues;
+    HashSet<RefPtr<Database> > m_activeDatabases;
+    Deque<Database*> m_globalQueue;
+};
+
+} // namespace WebCore
+
+#endif // DatabaseThread_h
diff --git a/WebCore/storage/DatabaseTracker.cpp b/WebCore/storage/DatabaseTracker.cpp
new file mode 100644 (file)
index 0000000..b003a34
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2007 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 "DatabaseTracker.h"
+
+#include "Database.h"
+#include "FileSystem.h"
+#include "NotImplemented.h"
+#include "SQLStatement.h"
+
+namespace WebCore {
+
+String DatabaseTracker::s_databasePath;
+
+void DatabaseTracker::setDatabasePath(const String& path)
+{
+    s_databasePath = path;
+}
+
+const String& DatabaseTracker::databasePath()
+{
+    return s_databasePath;
+}
+
+DatabaseTracker& DatabaseTracker::tracker()
+{
+    static DatabaseTracker tracker;
+
+    return tracker;
+}
+
+DatabaseTracker::DatabaseTracker()
+{
+    String databasePath = DatabaseTracker::databasePath();
+    makeAllDirectories(databasePath);
+    databasePath = pathByAppendingComponent(databasePath, "Databases.db");
+
+    if (!m_database.open(databasePath)) {
+        // FIXME: What do do here?
+        return;
+    }
+
+    if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS Origins (origin TEXT UNIQUE ON CONFLICT REPLACE, creationPolicy INTEGER NOT NULL ON CONFLICT FAIL, sizePolicy INTEGER NOT NULL ON CONFLICT FAIL);")) {
+        // FIXME: and here
+    }
+
+    if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS Databases (guid INTEGER PRIMARY KEY AUTOINCREMENT, origin TEXT UNIQUE ON CONFLICT REPLACE, name TEXT UNIQUE ON CONFLICT REPLACE, path TEXT NOT NULL ON CONFLICT FAIL);")) {
+        // FIXME: and here
+    }
+}
+
+String DatabaseTracker::fullPathForDatabase(const String& origin, const String& name)
+{
+    String databasePath = DatabaseTracker::databasePath();
+    SQLStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;");
+
+    if (statement.prepare() != SQLResultOk)
+        return "";
+
+    statement.bindText16(1, origin, false);
+    statement.bindText16(2, name, false);
+
+    int result = statement.step();
+
+    if (result == SQLResultRow)
+        return pathByAppendingComponent(databasePath, statement.getColumnText16(0));
+    if (result != SQLResultDone) {
+        LOG_ERROR("Failed to retrieve filename from Database Tracker for origin %s, name %s", origin.ascii().data(), name.ascii().data());
+        return "";
+    }
+
+    SQLStatement sequenceStatement(m_database, "SELECT seq FROM sqlite_sequence WHERE name='Databases';");
+
+    // FIXME: More informative error handling here, even though these steps should never fail
+    if (sequenceStatement.prepare() != SQLResultOk)
+        return "";
+    result = sequenceStatement.step();
+
+    // This has a range of 2^63 and starts at 0 for every time a user resets Safari -
+    // I can't imagine it'd over overflow
+    int64_t seq = 0;
+    if (result == SQLResultRow) {
+        seq = sequenceStatement.getColumnInt64(0);
+    } else if (result != SQLResultDone)
+        return "";
+
+    String filename;
+    do {
+        ++seq;
+        filename = pathByAppendingComponent(databasePath, String::format("%016llx.db", seq));
+    } while (fileExists(filename));
+
+    sequenceStatement.finalize();
+
+    if (!addDatabase(origin, name, String::format("%016llx.db", seq)))
+        return "";
+
+    return filename;
+}
+
+void DatabaseTracker::populateOrigins()
+{
+    if (m_origins)
+        return;
+
+    m_origins.set(new HashSet<String>);
+
+    if (!m_database.isOpen())
+        return;
+
+    SQLStatement statement(m_database, "SELECT DISTINCT origin FROM Databases;");
+
+    if (statement.prepare() != SQLResultOk)
+        return;
+
+    int result;
+    while ((result = statement.step()) == SQLResultRow)
+        m_origins->add(statement.getColumnText16(0));
+
+    if (result != SQLResultDone)
+        LOG_ERROR("Failed to read in all origins from the database");
+
+    return;
+}
+
+const HashSet<String>& DatabaseTracker::origins()
+{
+    if (!m_origins)
+        populateOrigins();
+
+    return *(m_origins.get());
+}
+
+bool DatabaseTracker::databaseNamesForOrigin(const String& origin, Vector<String>& resultVector)
+{
+    if (!m_database.isOpen())
+        return false;
+
+    SQLStatement statement(m_database, "SELECT name FROM Databases where origin=?;");
+
+    if (statement.prepare() != SQLResultOk)
+        return false;
+
+    statement.bindText16(1, origin, false);
+
+    int result;
+    while ((result = statement.step()) == SQLResultRow)
+        resultVector.append(statement.getColumnText16(0));
+
+    if (result != SQLResultDone) {
+        LOG_ERROR("Failed to retrieve all database names for origin %s", origin.ascii().data());
+        return false;
+    }
+
+    return true;
+}
+
+bool DatabaseTracker::addDatabase(const String& origin, const String& name, const String& path)
+{
+    if (!m_database.isOpen())
+        return false;
+
+    SQLStatement statement(m_database, "INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);");
+
+    if (statement.prepare() != SQLResultOk)
+        return false;
+
+    statement.bindText16(1, origin, true);
+    statement.bindText16(2, name, true);
+    statement.bindText16(3, path, true);
+
+    if (!statement.executeCommand()) {
+        LOG_ERROR("Failed to add database %s to origin %s: %s\n", name.ascii().data(), origin.ascii().data(), statement.lastErrorMsg());
+        return false;
+    }
+
+    populateOrigins();
+    m_origins->add(origin);
+    return true;
+}
+
+void DatabaseTracker::deleteAllDatabases()
+{
+    notImplemented();
+}
+
+void DatabaseTracker::deleteAllDatabasesForOrigin(const String& origin)
+{
+    notImplemented();
+}
+
+void DatabaseTracker::deleteDatabase(const String& origin, const String& name)
+{
+    notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/storage/DatabaseTracker.h b/WebCore/storage/DatabaseTracker.h
new file mode 100644 (file)
index 0000000..d758cf7
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+#ifndef DatabaseTracker_h
+#define DatabaseTracker_h
+
+#include "PlatformString.h"
+#include "SQLDatabase.h"
+#include "StringHash.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class DatabaseTracker {
+public:
+    static void setDatabasePath(const String&);
+    static const String& databasePath();
+
+    String fullPathForDatabase(const String& origin, const String& name);
+
+    const HashSet<String>& origins();
+    bool databaseNamesForOrigin(const String& origin, Vector<String>& result);
+
+    void deleteAllDatabases();
+    void deleteAllDatabasesForOrigin(const String& origin);
+    void deleteDatabase(const String& origin, const String& name);
+
+    static DatabaseTracker& tracker();
+private:
+    DatabaseTracker();
+
+    bool addDatabase(const String& origin, const String& name, const String& path);
+    void populateOrigins();
+
+    SQLDatabase m_database;
+    mutable OwnPtr<HashSet<String> > m_origins;
+
+    static String s_databasePath;
+};
+
+} // namespace WebCore
+
+#endif // DatabaseTracker_h
diff --git a/WebCore/storage/SQLCallback.h b/WebCore/storage/SQLCallback.h
new file mode 100644 (file)
index 0000000..59f36af
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef SQLCallback_h
+#define SQLCallback_h
+
+#include "Threading.h"
+
+namespace WebCore {
+
+class SQLResultSet;
+
+class SQLCallback : public ThreadSafeShared<SQLCallback> {
+public:
+    virtual ~SQLCallback() { }
+    virtual void handleEvent(SQLResultSet*) = 0;
+};
+
+} // namespace WebCore
+
+#endif // SQLCallback_h
diff --git a/WebCore/storage/SQLCallback.idl b/WebCore/storage/SQLCallback.idl
new file mode 100644 (file)
index 0000000..