23c616ea75694484b6a23c8fdbb304633519fd8b
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBFactoryBackendImpl.cpp
1 /*
2  * Copyright (C) 2011 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 "IDBFactoryBackendImpl.h"
31
32 #include "DOMStringList.h"
33 #include "IDBBackingStore.h"
34 #include "IDBDatabaseBackendImpl.h"
35 #include "IDBDatabaseException.h"
36 #include "IDBTransactionCoordinator.h"
37 #include "SecurityOrigin.h"
38 #include <wtf/UnusedParam.h>
39
40 #if ENABLE(INDEXED_DATABASE)
41
42 namespace WebCore {
43
44 static String computeFileIdentifier(SecurityOrigin* securityOrigin)
45 {
46     static const char levelDBFileSuffix[] = "@1";
47     return securityOrigin->databaseIdentifier() + levelDBFileSuffix;
48 }
49
50 static String computeUniqueIdentifier(const String& name, SecurityOrigin* securityOrigin)
51 {
52     return computeFileIdentifier(securityOrigin) + name;
53 }
54
55 IDBFactoryBackendImpl::IDBFactoryBackendImpl()
56 {
57 }
58
59 IDBFactoryBackendImpl::~IDBFactoryBackendImpl()
60 {
61 }
62
63 void IDBFactoryBackendImpl::removeIDBDatabaseBackend(const String& uniqueIdentifier)
64 {
65     ASSERT(m_databaseBackendMap.contains(uniqueIdentifier));
66     m_databaseBackendMap.remove(uniqueIdentifier);
67 }
68
69 void IDBFactoryBackendImpl::addIDBBackingStore(const String& fileIdentifier, IDBBackingStore* backingStore)
70 {
71     ASSERT(!m_backingStoreMap.contains(fileIdentifier));
72     m_backingStoreMap.set(fileIdentifier, backingStore);
73 }
74
75 void IDBFactoryBackendImpl::removeIDBBackingStore(const String& fileIdentifier)
76 {
77     ASSERT(m_backingStoreMap.contains(fileIdentifier));
78     m_backingStoreMap.remove(fileIdentifier);
79 }
80
81 void IDBFactoryBackendImpl::getDatabaseNames(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, ScriptExecutionContext*, const String& dataDirectory)
82 {
83     RefPtr<IDBBackingStore> backingStore = openBackingStore(securityOrigin, dataDirectory);
84     if (!backingStore) {
85         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error opening backing store for indexedDB.webkitGetDatabaseNames."));
86         return;
87     }
88
89     RefPtr<DOMStringList> databaseNames = DOMStringList::create();
90
91     Vector<String> foundNames = backingStore->getDatabaseNames();
92     for (Vector<String>::const_iterator it = foundNames.begin(); it != foundNames.end(); ++it)
93         databaseNames->append(*it);
94
95     callbacks->onSuccess(databaseNames.release());
96 }
97
98 void IDBFactoryBackendImpl::deleteDatabase(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, ScriptExecutionContext*, const String& dataDirectory)
99 {
100     const String uniqueIdentifier = computeUniqueIdentifier(name, securityOrigin.get());
101
102     IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier);
103     if (it != m_databaseBackendMap.end()) {
104         // If there are any connections to the database, directly delete the
105         // database.
106         it->value->deleteDatabase(callbacks);
107         return;
108     }
109
110     // FIXME: Everything from now on should be done on another thread.
111     RefPtr<IDBBackingStore> backingStore = openBackingStore(securityOrigin, dataDirectory);
112     if (!backingStore) {
113         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error opening backing store for indexedDB.deleteDatabase."));
114         return;
115     }
116
117     RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, backingStore.get(), this, uniqueIdentifier);
118     if (databaseBackend) {
119         m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
120         databaseBackend->deleteDatabase(callbacks);
121         m_databaseBackendMap.remove(uniqueIdentifier);
122     } else
123         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error creating database backend for indexedDB.deleteDatabase."));
124 }
125
126 PassRefPtr<IDBBackingStore> IDBFactoryBackendImpl::openBackingStore(PassRefPtr<SecurityOrigin> securityOrigin, const String& dataDirectory)
127 {
128     const String fileIdentifier = computeFileIdentifier(securityOrigin.get());
129
130     RefPtr<IDBBackingStore> backingStore;
131     IDBBackingStoreMap::iterator it2 = m_backingStoreMap.find(fileIdentifier);
132     if (it2 != m_backingStoreMap.end())
133         backingStore = it2->value;
134     else {
135         backingStore = IDBBackingStore::open(securityOrigin.get(), dataDirectory, fileIdentifier, this);
136     }
137
138     if (backingStore)
139         return backingStore.release();
140
141     return 0;
142 }
143
144 void IDBFactoryBackendImpl::open(const String& name, int64_t version, int64_t transactionId, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, PassRefPtr<SecurityOrigin> prpSecurityOrigin, ScriptExecutionContext*, const String& dataDirectory)
145 {
146     RefPtr<SecurityOrigin> securityOrigin = prpSecurityOrigin;
147     const String uniqueIdentifier = computeUniqueIdentifier(name, securityOrigin.get());
148
149     RefPtr<IDBDatabaseBackendImpl> databaseBackend;
150     IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier);
151     if (it == m_databaseBackendMap.end()) {
152         RefPtr<IDBBackingStore> backingStore = openBackingStore(securityOrigin, dataDirectory);
153         if (!backingStore) {
154             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error opening backing store for indexedDB.open."));
155             return;
156         }
157
158         databaseBackend = IDBDatabaseBackendImpl::create(name, backingStore.get(), this, uniqueIdentifier);
159         if (databaseBackend)
160             m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
161         else {
162             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error creating database backend for indexeddb.open."));
163             return;
164         }
165     } else
166         databaseBackend = it->value;
167
168     databaseBackend->openConnection(callbacks, databaseCallbacks, transactionId, version);
169 }
170
171 } // namespace WebCore
172
173 #endif // ENABLE(INDEXED_DATABASE)