Transition most IDB interfaces from ScriptExecutionContext to ExecState.
[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 RefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext& context, const String& name, Optional<uint64_t> version, ExceptionCodeWithMessage& ec)
80 {
81     LOG(IndexedDB, "IDBFactory::open");
82     
83     if (version && !version.value()) {
84         ec.code = TypeError;
85         ec.message = ASCIILiteral("IDBFactory.open() called with a version of 0");
86         return nullptr;
87     }
88
89     return openInternal(context, name, version.valueOr(0), ec);
90 }
91
92 RefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ScriptExecutionContext& context, const String& name, unsigned long long version, ExceptionCodeWithMessage& ec)
93 {
94     if (name.isNull()) {
95         ec.code = TypeError;
96         ec.message = ASCIILiteral("IDBFactory.open() called without a database name");
97         return nullptr;
98     }
99
100     if (shouldThrowSecurityException(context)) {
101         ec.code = SECURITY_ERR;
102         ec.message = ASCIILiteral("IDBFactory.open() called in an invalid security context");
103         return nullptr;
104     }
105
106     ASSERT(context.securityOrigin());
107     ASSERT(context.topOrigin());
108     IDBDatabaseIdentifier databaseIdentifier(name, *context.securityOrigin(), *context.topOrigin());
109     if (!databaseIdentifier.isValid()) {
110         ec.code = TypeError;
111         ec.message = ASCIILiteral("IDBFactory.open() called with an invalid security origin");
112         return nullptr;
113     }
114
115     return m_connectionProxy->openDatabase(context, databaseIdentifier, version);
116 }
117
118 RefPtr<IDBOpenDBRequest> IDBFactory::deleteDatabase(ScriptExecutionContext& context, const String& name, ExceptionCodeWithMessage& ec)
119 {
120     LOG(IndexedDB, "IDBFactory::deleteDatabase - %s", name.utf8().data());
121
122     if (name.isNull()) {
123         ec.code = TypeError;
124         ec.message = ASCIILiteral("IDBFactory.deleteDatabase() called without a database name");
125     }
126     
127     if (shouldThrowSecurityException(context)) {
128         ec.code = SECURITY_ERR;
129         ec.message = ASCIILiteral("IDBFactory.deleteDatabase() called in an invalid security context");
130         return nullptr;
131     }
132
133     ASSERT(context.securityOrigin());
134     ASSERT(context.topOrigin());
135     IDBDatabaseIdentifier databaseIdentifier(name, *context.securityOrigin(), *context.topOrigin());
136     if (!databaseIdentifier.isValid()) {
137         ec.code = TypeError;
138         ec.message = ASCIILiteral("IDBFactory.deleteDatabase() called with an invalid security origin");
139         return nullptr;
140     }
141
142     return m_connectionProxy->deleteDatabase(context, databaseIdentifier);
143 }
144
145 short IDBFactory::cmp(ExecState& execState, JSValue firstValue, JSValue secondValue, ExceptionCodeWithMessage& ec)
146 {
147     Ref<IDBKey> first = scriptValueToIDBKey(execState, firstValue);
148     Ref<IDBKey> second = scriptValueToIDBKey(execState, secondValue);
149
150     if (!first->isValid() || !second->isValid()) {
151         ec.code = IDBDatabaseException::DataError;
152         ec.message = ASCIILiteral("Failed to execute 'cmp' on 'IDBFactory': The parameter is not a valid key.");
153         return 0;
154     }
155
156     return first->compare(second.get());
157 }
158
159 void IDBFactory::getAllDatabaseNames(const SecurityOrigin& mainFrameOrigin, const SecurityOrigin& openingOrigin, std::function<void (const Vector<String>&)> callback)
160 {
161     m_connectionProxy->getAllDatabaseNames(mainFrameOrigin, openingOrigin, callback);
162 }
163
164 } // namespace WebCore
165
166 #endif // ENABLE(INDEXED_DATABASE)