1/* 2 * Copyright (C) 2012 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 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "IDBOpenDBRequest.h" 28 29#if ENABLE(INDEXED_DATABASE) 30 31#include "IDBDatabase.h" 32#include "IDBDatabaseCallbacksImpl.h" 33#include "IDBPendingTransactionMonitor.h" 34#include "IDBVersionChangeEvent.h" 35#include "Logging.h" 36#include "ScriptExecutionContext.h" 37 38namespace WebCore { 39 40PassRefPtr<IDBOpenDBRequest> IDBOpenDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseCallbacks> callbacks, int64_t transactionId, uint64_t version, IndexedDB::VersionNullness versionNullness) 41{ 42 RefPtr<IDBOpenDBRequest> request(adoptRef(new IDBOpenDBRequest(context, callbacks, transactionId, version, versionNullness))); 43 request->suspendIfNeeded(); 44 return request.release(); 45} 46 47IDBOpenDBRequest::IDBOpenDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseCallbacks> callbacks, int64_t transactionId, uint64_t version, IndexedDB::VersionNullness versionNullness) 48 : IDBRequest(context, IDBAny::createNull(), IDBDatabaseBackend::NormalTask, 0) 49 , m_databaseCallbacks(callbacks) 50 , m_transactionId(transactionId) 51 , m_version(version) 52 , m_versionNullness(versionNullness) 53{ 54 ASSERT(!m_result); 55} 56 57IDBOpenDBRequest::~IDBOpenDBRequest() 58{ 59} 60 61EventTargetInterface IDBOpenDBRequest::eventTargetInterface() const 62{ 63 return IDBOpenDBRequestEventTargetInterfaceType; 64} 65 66void IDBOpenDBRequest::onBlocked(uint64_t oldVersion) 67{ 68 LOG(StorageAPI, "IDBOpenDBRequest::onBlocked()"); 69 if (!shouldEnqueueEvent()) 70 return; 71 72 enqueueEvent(IDBVersionChangeEvent::create(oldVersion, m_version, m_versionNullness, eventNames().blockedEvent)); 73} 74 75void IDBOpenDBRequest::onUpgradeNeeded(uint64_t oldVersion, PassRefPtr<IDBDatabaseBackend> prpDatabaseBackend, const IDBDatabaseMetadata& metadata) 76{ 77 LOG(StorageAPI, "IDBOpenDBRequest::onUpgradeNeeded()"); 78 if (m_contextStopped || !scriptExecutionContext()) { 79 RefPtr<IDBDatabaseBackend> db = prpDatabaseBackend; 80 db->abort(m_transactionId); 81 db->close(m_databaseCallbacks); 82 return; 83 } 84 if (!shouldEnqueueEvent()) 85 return; 86 87 ASSERT(m_databaseCallbacks); 88 89 RefPtr<IDBDatabaseBackend> databaseBackend = prpDatabaseBackend; 90 91 RefPtr<IDBDatabase> idbDatabase = IDBDatabase::create(scriptExecutionContext(), databaseBackend, m_databaseCallbacks); 92 idbDatabase->setMetadata(metadata); 93 m_databaseCallbacks->connect(idbDatabase.get()); 94 m_databaseCallbacks = 0; 95 96 IDBDatabaseMetadata oldMetadata(metadata); 97 oldMetadata.version = oldVersion; 98 99 m_transaction = IDBTransaction::create(scriptExecutionContext(), m_transactionId, idbDatabase.get(), this, oldMetadata); 100 m_result = IDBAny::create(idbDatabase.release()); 101 102 if (m_versionNullness == IndexedDB::VersionNullness::Null) 103 m_version = 1; 104 enqueueEvent(IDBVersionChangeEvent::create(oldVersion, m_version, m_versionNullness, eventNames().upgradeneededEvent)); 105} 106 107void IDBOpenDBRequest::onSuccess(PassRefPtr<IDBDatabaseBackend> prpBackend, const IDBDatabaseMetadata& metadata) 108{ 109 LOG(StorageAPI, "IDBOpenDBRequest::onSuccess()"); 110 if (!shouldEnqueueEvent()) 111 return; 112 113 RefPtr<IDBDatabaseBackend> backend = prpBackend; 114 RefPtr<IDBDatabase> idbDatabase; 115 if (m_result) { 116 idbDatabase = m_result->idbDatabase(); 117 ASSERT(idbDatabase); 118 ASSERT(!m_databaseCallbacks); 119 } else { 120 ASSERT(m_databaseCallbacks); 121 idbDatabase = IDBDatabase::create(scriptExecutionContext(), backend.release(), m_databaseCallbacks); 122 m_databaseCallbacks->connect(idbDatabase.get()); 123 m_databaseCallbacks = 0; 124 m_result = IDBAny::create(idbDatabase.get()); 125 } 126 idbDatabase->setMetadata(metadata); 127 enqueueEvent(Event::create(eventNames().successEvent, false, false)); 128} 129 130bool IDBOpenDBRequest::shouldEnqueueEvent() const 131{ 132 if (m_contextStopped || !scriptExecutionContext()) 133 return false; 134 ASSERT(m_readyState == PENDING || m_readyState == DONE); 135 if (m_requestAborted) 136 return false; 137 return true; 138} 139 140bool IDBOpenDBRequest::dispatchEvent(PassRefPtr<Event> event) 141{ 142 // If the connection closed between onUpgradeNeeded and the delivery of the "success" event, 143 // an "error" event should be fired instead. 144 if (event->type() == eventNames().successEvent && m_result->type() == IDBAny::IDBDatabaseType && m_result->idbDatabase()->isClosePending()) { 145 m_result.clear(); 146 onError(IDBDatabaseError::create(IDBDatabaseException::AbortError, "The connection was closed.")); 147 return false; 148 } 149 150 return IDBRequest::dispatchEvent(event); 151} 152 153} // namespace WebCore 154 155#endif 156