[WTF] Import std::optional reference implementation as WTF::Optional
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBFactory.cpp
1 /*
2  * Copyright (C) 2015, 2016 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "IDBFactory.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "Document.h"
32 #include "ExceptionCode.h"
33 #include "IDBBindingUtilities.h"
34 #include "IDBConnectionProxy.h"
35 #include "IDBDatabaseIdentifier.h"
36 #include "IDBKey.h"
37 #include "IDBOpenDBRequest.h"
38 #include "Logging.h"
39 #include "Page.h"
40 #include "SchemeRegistry.h"
41 #include "ScriptExecutionContext.h"
42 #include "SecurityOrigin.h"
43
44 using namespace JSC;
45
46 namespace WebCore {
47
48 static bool shouldThrowSecurityException(ScriptExecutionContext& context)
49 {
50     ASSERT(is<Document>(context) || context.isWorkerGlobalScope());
51     if (is<Document>(context)) {
52         Document& document = downcast<Document>(context);
53         if (!document.frame())
54             return true;
55         if (!document.page())
56             return true;
57     }
58
59     if (!context.securityOrigin()->canAccessDatabase(context.topOrigin()))
60         return true;
61
62     return false;
63 }
64
65 Ref<IDBFactory> IDBFactory::create(IDBClient::IDBConnectionProxy& connectionProxy)
66 {
67     return adoptRef(*new IDBFactory(connectionProxy));
68 }
69
70 IDBFactory::IDBFactory(IDBClient::IDBConnectionProxy& connectionProxy)
71     : m_connectionProxy(connectionProxy)
72 {
73 }
74
75 IDBFactory::~IDBFactory()
76 {
77 }
78
79 ExceptionOr<Ref<IDBOpenDBRequest>> IDBFactory::open(ScriptExecutionContext& context, const String& name, std::optional<uint64_t> version)
80 {
81     LOG(IndexedDB, "IDBFactory::open");
82     
83     if (version && !version.value())
84         return Exception { TypeError, ASCIILiteral("IDBFactory.open() called with a version of 0") };
85
86     return openInternal(context, name, version.value_or(0));
87 }
88
89 ExceptionOr<Ref<IDBOpenDBRequest>> IDBFactory::openInternal(ScriptExecutionContext& context, const String& name, unsigned long long version)
90 {
91     if (name.isNull())
92         return Exception { TypeError, ASCIILiteral("IDBFactory.open() called without a database name") };
93
94     if (shouldThrowSecurityException(context))
95         return Exception { SECURITY_ERR, ASCIILiteral("IDBFactory.open() called in an invalid security context") };
96
97     ASSERT(context.securityOrigin());
98     ASSERT(context.topOrigin());
99     IDBDatabaseIdentifier databaseIdentifier(name, *context.securityOrigin(), *context.topOrigin());
100     if (!databaseIdentifier.isValid())
101         return Exception { TypeError, ASCIILiteral("IDBFactory.open() called with an invalid security origin") };
102
103     return m_connectionProxy->openDatabase(context, databaseIdentifier, version);
104 }
105
106 ExceptionOr<Ref<IDBOpenDBRequest>> IDBFactory::deleteDatabase(ScriptExecutionContext& context, const String& name)
107 {
108     LOG(IndexedDB, "IDBFactory::deleteDatabase - %s", name.utf8().data());
109
110     if (name.isNull())
111         return Exception { TypeError, ASCIILiteral("IDBFactory.deleteDatabase() called without a database name") };
112
113     if (shouldThrowSecurityException(context))
114         return Exception { SECURITY_ERR, ASCIILiteral("IDBFactory.deleteDatabase() called in an invalid security context") };
115
116     ASSERT(context.securityOrigin());
117     ASSERT(context.topOrigin());
118     IDBDatabaseIdentifier databaseIdentifier(name, *context.securityOrigin(), *context.topOrigin());
119     if (!databaseIdentifier.isValid())
120         return Exception { TypeError, ASCIILiteral("IDBFactory.deleteDatabase() called with an invalid security origin") };
121
122     return m_connectionProxy->deleteDatabase(context, databaseIdentifier);
123 }
124
125 ExceptionOr<short> IDBFactory::cmp(ExecState& execState, JSValue firstValue, JSValue secondValue)
126 {
127     auto first = scriptValueToIDBKey(execState, firstValue);
128     auto second = scriptValueToIDBKey(execState, secondValue);
129
130     if (!first->isValid() || !second->isValid())
131         return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'cmp' on 'IDBFactory': The parameter is not a valid key.") };
132
133     return first->compare(second.get());
134 }
135
136 void IDBFactory::getAllDatabaseNames(const SecurityOrigin& mainFrameOrigin, const SecurityOrigin& openingOrigin, std::function<void (const Vector<String>&)> callback)
137 {
138     m_connectionProxy->getAllDatabaseNames(mainFrameOrigin, openingOrigin, callback);
139 }
140
141 } // namespace WebCore
142
143 #endif // ENABLE(INDEXED_DATABASE)