Unreviewed test gardening.
[WebKit-https.git] / Source / WebKit2 / WebProcess / Databases / IndexedDB / WebIDBFactoryBackend.cpp
1 /*
2  * Copyright (C) 2013 Apple 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26
27 #include "config.h"
28 #include "WebIDBFactoryBackend.h"
29
30 #include "IDBUtilities.h"
31 #include "Logging.h"
32 #include "WebIDBServerConnection.h"
33 #include "WebProcess.h"
34 #include "WebToDatabaseProcessConnection.h"
35 #include <WebCore/DOMStringList.h>
36 #include <WebCore/IDBCallbacks.h>
37 #include <WebCore/IDBCursorBackend.h>
38 #include <WebCore/IDBDatabaseCallbacks.h>
39 #include <WebCore/IDBTransactionBackend.h>
40 #include <WebCore/SecurityOrigin.h>
41 #include <wtf/MainThread.h>
42 #include <wtf/NeverDestroyed.h>
43
44 #if ENABLE(INDEXED_DATABASE)
45 #if ENABLE(DATABASE_PROCESS)
46
47 using namespace WebCore;
48
49 namespace WebKit {
50
51 typedef HashMap<String, IDBDatabaseBackend*> IDBDatabaseBackendMap;
52
53 static IDBDatabaseBackendMap& sharedDatabaseBackendMap()
54 {
55     static NeverDestroyed<IDBDatabaseBackendMap> databaseBackendMap;
56     return databaseBackendMap;
57 }
58
59 static HashMap<String, HashSet<String>>& sharedRecentDatabaseNameMap()
60 {
61     static NeverDestroyed<HashMap<String, HashSet<String>>> recentDatabaseNameMap;
62     return recentDatabaseNameMap;
63 }
64
65 static String combinedSecurityOriginIdentifier(const WebCore::SecurityOrigin& openingOrigin, const WebCore::SecurityOrigin& mainFrameOrigin)
66 {
67     StringBuilder stringBuilder;
68
69     String originString = openingOrigin.toString();
70     if (originString == "null")
71         return String();
72     stringBuilder.append(originString);
73     stringBuilder.append('_');
74
75     originString = mainFrameOrigin.toString();
76     if (originString == "null")
77         return String();
78     stringBuilder.append(originString);
79
80     return stringBuilder.toString();
81 }
82
83 WebIDBFactoryBackend::WebIDBFactoryBackend()
84 {
85 }
86
87 WebIDBFactoryBackend::~WebIDBFactoryBackend()
88 {
89 }
90
91 void WebIDBFactoryBackend::getDatabaseNames(PassRefPtr<IDBCallbacks> callbacks, const SecurityOrigin& openingOrigin, const SecurityOrigin& mainFrameOrigin, ScriptExecutionContext* context)
92 {
93     LOG(IDB, "WebIDBFactoryBackend::getDatabaseNames");
94
95     String securityOriginIdentifier = combinedSecurityOriginIdentifier(openingOrigin, mainFrameOrigin);
96     if (securityOriginIdentifier.isEmpty()) {
97         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::InvalidAccessError, ASCIILiteral("Document is not allowed to use Indexed Databases")));
98         return;
99     }
100
101     RefPtr<DOMStringList> databaseNames = DOMStringList::create();
102
103     auto recentNameIterator = sharedRecentDatabaseNameMap().find(securityOriginIdentifier);
104     if (recentNameIterator != sharedRecentDatabaseNameMap().end()) {
105         HashSet<String>& foundNames = recentNameIterator->value;
106         for (const String& name : foundNames)
107             databaseNames->append(name);
108     }
109
110     callbacks->onSuccess(databaseNames.release());
111 }
112
113 void WebIDBFactoryBackend::open(const String& databaseName, uint64_t version, int64_t transactionId, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, const SecurityOrigin& openingOrigin, const SecurityOrigin& mainFrameOrigin)
114 {
115     ASSERT(RunLoop::isMain());
116     LOG(IDB, "WebIDBFactoryBackend::open");
117
118     String databaseIdentifier = uniqueDatabaseIdentifier(databaseName, openingOrigin, mainFrameOrigin);
119     if (databaseIdentifier.isNull()) {
120         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::InvalidAccessError, "Document is not allowed to use Indexed Databases"));
121         return;
122     }
123
124     String securityOriginIdentifier = combinedSecurityOriginIdentifier(openingOrigin, mainFrameOrigin);
125     ASSERT(!securityOriginIdentifier.isEmpty());
126
127     auto recentNameIterator = sharedRecentDatabaseNameMap().find(securityOriginIdentifier);
128     if (recentNameIterator == sharedRecentDatabaseNameMap().end()) {
129         HashSet<String> names;
130         names.add(databaseName);
131         sharedRecentDatabaseNameMap().set(securityOriginIdentifier, names);
132     } else
133         recentNameIterator->value.add(databaseName);
134
135     IDBDatabaseBackendMap::iterator it = sharedDatabaseBackendMap().find(databaseIdentifier);
136
137     RefPtr<IDBDatabaseBackend> databaseBackend;
138     if (it == sharedDatabaseBackendMap().end()) {
139         RefPtr<IDBServerConnection> serverConnection = WebIDBServerConnection::create(databaseName, openingOrigin, mainFrameOrigin);
140         databaseBackend = IDBDatabaseBackend::create(databaseName, databaseIdentifier, this, *serverConnection);
141         sharedDatabaseBackendMap().set(databaseIdentifier, databaseBackend.get());
142     } else
143         databaseBackend = it->value;
144
145     databaseBackend->openConnection(callbacks, databaseCallbacks, transactionId, version);
146 }
147
148 void WebIDBFactoryBackend::deleteDatabase(const String& databaseName, const SecurityOrigin& openingOrigin, const SecurityOrigin& mainFrameOrigin, PassRefPtr<IDBCallbacks> callbacks, ScriptExecutionContext*)
149 {
150     ASSERT(RunLoop::isMain());
151     LOG(IDB, "WebIDBFactoryBackend::deleteDatabase");
152
153     String databaseIdentifier = uniqueDatabaseIdentifier(databaseName, openingOrigin, mainFrameOrigin);
154     if (databaseIdentifier.isNull()) {
155         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::InvalidAccessError, "Document is not allowed to use Indexed Databases"));
156         return;
157     }
158
159     String securityOriginIdentifier = combinedSecurityOriginIdentifier(openingOrigin, mainFrameOrigin);
160     ASSERT(!securityOriginIdentifier.isEmpty());
161
162     auto recentNameIterator = sharedRecentDatabaseNameMap().find(securityOriginIdentifier);
163     if (recentNameIterator != sharedRecentDatabaseNameMap().end()) {
164         recentNameIterator->value.remove(databaseName);
165         if (recentNameIterator->value.isEmpty())
166             sharedRecentDatabaseNameMap().remove(recentNameIterator);
167     }
168
169     // If there's already a connection to the database, delete it directly.
170     IDBDatabaseBackendMap::iterator it = sharedDatabaseBackendMap().find(databaseIdentifier);
171     if (it != sharedDatabaseBackendMap().end()) {
172         it->value->deleteDatabase(callbacks);
173         return;
174     }
175
176     RefPtr<IDBServerConnection> serverConnection = WebIDBServerConnection::create(databaseName, openingOrigin, mainFrameOrigin);
177     RefPtr<IDBDatabaseBackend> databaseBackend = IDBDatabaseBackend::create(databaseName, databaseIdentifier, this, *serverConnection);
178
179     sharedDatabaseBackendMap().set(databaseIdentifier, databaseBackend.get());
180     databaseBackend->deleteDatabase(callbacks);
181     sharedDatabaseBackendMap().remove(databaseIdentifier);
182 }
183
184 void WebIDBFactoryBackend::removeIDBDatabaseBackend(const String& identifier)
185 {
186     sharedDatabaseBackendMap().remove(identifier);
187 }
188
189 } // namespace WebKit
190
191 #endif // ENABLE(DATABASE_PROCESS)
192 #endif // ENABLE(INDEXED_DATABASE)