1/* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "IDBFactory.h" 31 32#if ENABLE(INDEXED_DATABASE) 33 34#include "Document.h" 35#include "ExceptionCode.h" 36#include "Frame.h" 37#include "GroupSettings.h" 38#include "HistogramSupport.h" 39#include "IDBBindingUtilities.h" 40#include "IDBDatabase.h" 41#include "IDBDatabaseCallbacksImpl.h" 42#include "IDBDatabaseException.h" 43#include "IDBFactoryBackendInterface.h" 44#include "IDBHistograms.h" 45#include "IDBKey.h" 46#include "IDBKeyRange.h" 47#include "IDBOpenDBRequest.h" 48#include "IDBTracing.h" 49#include "Page.h" 50#include "PageGroup.h" 51#include "SecurityOrigin.h" 52#include "WorkerContext.h" 53#include "WorkerLoaderProxy.h" 54#include "WorkerThread.h" 55 56namespace WebCore { 57 58IDBFactory::IDBFactory(IDBFactoryBackendInterface* factory) 59 : m_backend(factory) 60{ 61 // We pass a reference to this object before it can be adopted. 62 relaxAdoptionRequirement(); 63} 64 65IDBFactory::~IDBFactory() 66{ 67} 68 69namespace { 70static bool isContextValid(ScriptExecutionContext* context) 71{ 72 ASSERT(context->isDocument() || context->isWorkerContext()); 73 if (context->isDocument()) { 74 Document* document = toDocument(context); 75 return document->frame() && document->page(); 76 } 77#if !ENABLE(WORKERS) 78 if (context->isWorkerContext()) 79 return false; 80#endif 81 return true; 82} 83 84static String getIndexedDBDatabasePath(ScriptExecutionContext* context) 85{ 86 ASSERT(isContextValid(context)); 87 if (context->isDocument()) { 88 Document* document = toDocument(context); 89 return document->page()->group().groupSettings()->indexedDBDatabasePath(); 90 } 91#if ENABLE(WORKERS) 92 WorkerContext* workerContext = static_cast<WorkerContext*>(context); 93 const GroupSettings* groupSettings = workerContext->groupSettings(); 94 if (groupSettings) 95 return groupSettings->indexedDBDatabasePath(); 96#endif 97 return String(); 98} 99} 100 101PassRefPtr<IDBRequest> IDBFactory::getDatabaseNames(ScriptExecutionContext* context, ExceptionCode& ec) 102{ 103 IDB_TRACE("IDBFactory::getDatabaseNames"); 104 if (!isContextValid(context)) 105 return 0; 106 if (!context->securityOrigin()->canAccessDatabase(context->topOrigin())) { 107 ec = SECURITY_ERR; 108 return 0; 109 } 110 111 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), 0); 112 m_backend->getDatabaseNames(request, context->securityOrigin(), context, getIndexedDBDatabasePath(context)); 113 return request; 114} 115 116PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, unsigned long long version, ExceptionCode& ec) 117{ 118 IDB_TRACE("IDBFactory::open"); 119 if (!version) { 120 ec = TypeError; 121 return 0; 122 } 123 return openInternal(context, name, version, ec); 124} 125 126PassRefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ScriptExecutionContext* context, const String& name, int64_t version, ExceptionCode& ec) 127{ 128 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBOpenCall, IDBMethodsMax); 129 ASSERT(version >= 1 || version == IDBDatabaseMetadata::NoIntVersion); 130 if (name.isNull()) { 131 ec = TypeError; 132 return 0; 133 } 134 if (!isContextValid(context)) 135 return 0; 136 if (!context->securityOrigin()->canAccessDatabase(context->topOrigin())) { 137 ec = SECURITY_ERR; 138 return 0; 139 } 140 141 RefPtr<IDBDatabaseCallbacksImpl> databaseCallbacks = IDBDatabaseCallbacksImpl::create(); 142 int64_t transactionId = IDBDatabase::nextTransactionId(); 143 RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, databaseCallbacks, transactionId, version); 144 m_backend->open(name, version, transactionId, request, databaseCallbacks, context->securityOrigin(), context, getIndexedDBDatabasePath(context)); 145 return request; 146} 147 148PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, ExceptionCode& ec) 149{ 150 IDB_TRACE("IDBFactory::open"); 151 return openInternal(context, name, IDBDatabaseMetadata::NoIntVersion, ec); 152} 153 154PassRefPtr<IDBOpenDBRequest> IDBFactory::deleteDatabase(ScriptExecutionContext* context, const String& name, ExceptionCode& ec) 155{ 156 IDB_TRACE("IDBFactory::deleteDatabase"); 157 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBDeleteDatabaseCall, IDBMethodsMax); 158 if (name.isNull()) { 159 ec = TypeError; 160 return 0; 161 } 162 if (!isContextValid(context)) 163 return 0; 164 if (!context->securityOrigin()->canAccessDatabase(context->topOrigin())) { 165 ec = SECURITY_ERR; 166 return 0; 167 } 168 169 RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, 0, 0, IDBDatabaseMetadata::DefaultIntVersion); 170 m_backend->deleteDatabase(name, request, context->securityOrigin(), context, getIndexedDBDatabasePath(context)); 171 return request; 172} 173 174short IDBFactory::cmp(ScriptExecutionContext* context, const ScriptValue& firstValue, const ScriptValue& secondValue, ExceptionCode& ec) 175{ 176 DOMRequestState requestState(context); 177 RefPtr<IDBKey> first = scriptValueToIDBKey(&requestState, firstValue); 178 RefPtr<IDBKey> second = scriptValueToIDBKey(&requestState, secondValue); 179 180 ASSERT(first); 181 ASSERT(second); 182 183 if (!first->isValid() || !second->isValid()) { 184 ec = IDBDatabaseException::DataError; 185 return 0; 186 } 187 188 return static_cast<short>(first->compare(second.get())); 189} 190 191} // namespace WebCore 192 193#endif // ENABLE(INDEXED_DATABASE) 194