5a2b6ecda9d7387274151d3b0483c3eaf8e774ff
[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 "IDBBindingUtilities.h"
33 #include "IDBConnectionProxy.h"
34 #include "IDBDatabaseIdentifier.h"
35 #include "IDBKey.h"
36 #include "IDBOpenDBRequest.h"
37 #include "Logging.h"
38 #include "Page.h"
39 #include "ScriptExecutionContext.h"
40 #include "SecurityOrigin.h"
41
42
43 namespace WebCore {
44 using namespace JSC;
45
46 static bool shouldThrowSecurityException(ScriptExecutionContext& context)
47 {
48     ASSERT(is<Document>(context) || context.isWorkerGlobalScope());
49     if (is<Document>(context)) {
50         Document& document = downcast<Document>(context);
51         if (!document.frame())
52             return true;
53         if (!document.page())
54             return true;
55     }
56
57     if (!context.securityOrigin()->canAccessDatabase(context.topOrigin()))
58         return true;
59
60     return false;
61 }
62
63 Ref<IDBFactory> IDBFactory::create(IDBClient::IDBConnectionProxy& connectionProxy)
64 {
65     return adoptRef(*new IDBFactory(connectionProxy));
66 }
67
68 IDBFactory::IDBFactory(IDBClient::IDBConnectionProxy& connectionProxy)
69     : m_connectionProxy(connectionProxy)
70 {
71 }
72
73 IDBFactory::~IDBFactory() = default;
74
75 ExceptionOr<Ref<IDBOpenDBRequest>> IDBFactory::open(ScriptExecutionContext& context, const String& name, std::optional<uint64_t> version)
76 {
77     LOG(IndexedDB, "IDBFactory::open");
78     
79     if (version && !version.value())
80         return Exception { TypeError, ASCIILiteral("IDBFactory.open() called with a version of 0") };
81
82     return openInternal(context, name, version.value_or(0));
83 }
84
85 ExceptionOr<Ref<IDBOpenDBRequest>> IDBFactory::openInternal(ScriptExecutionContext& context, const String& name, uint64_t version)
86 {
87     if (name.isNull())
88         return Exception { TypeError, ASCIILiteral("IDBFactory.open() called without a database name") };
89
90     if (shouldThrowSecurityException(context))
91         return Exception { SecurityError, ASCIILiteral("IDBFactory.open() called in an invalid security context") };
92
93     ASSERT(context.securityOrigin());
94     IDBDatabaseIdentifier databaseIdentifier(name, SecurityOriginData::fromSecurityOrigin(*context.securityOrigin()), SecurityOriginData::fromSecurityOrigin(context.topOrigin()));
95     if (!databaseIdentifier.isValid())
96         return Exception { TypeError, ASCIILiteral("IDBFactory.open() called with an invalid security origin") };
97
98     LOG(IndexedDBOperations, "IDB opening database: %s %" PRIu64, name.utf8().data(), version);
99
100     return m_connectionProxy->openDatabase(context, databaseIdentifier, version);
101 }
102
103 ExceptionOr<Ref<IDBOpenDBRequest>> IDBFactory::deleteDatabase(ScriptExecutionContext& context, const String& name)
104 {
105     LOG(IndexedDB, "IDBFactory::deleteDatabase - %s", name.utf8().data());
106
107     if (name.isNull())
108         return Exception { TypeError, ASCIILiteral("IDBFactory.deleteDatabase() called without a database name") };
109
110     if (shouldThrowSecurityException(context))
111         return Exception { SecurityError, ASCIILiteral("IDBFactory.deleteDatabase() called in an invalid security context") };
112
113     ASSERT(context.securityOrigin());
114     IDBDatabaseIdentifier databaseIdentifier(name, SecurityOriginData::fromSecurityOrigin(*context.securityOrigin()), SecurityOriginData::fromSecurityOrigin(context.topOrigin()));
115     if (!databaseIdentifier.isValid())
116         return Exception { TypeError, ASCIILiteral("IDBFactory.deleteDatabase() called with an invalid security origin") };
117
118     LOG(IndexedDBOperations, "IDB deleting database: %s", name.utf8().data());
119
120     return m_connectionProxy->deleteDatabase(context, databaseIdentifier);
121 }
122
123 ExceptionOr<short> IDBFactory::cmp(ExecState& execState, JSValue firstValue, JSValue secondValue)
124 {
125     auto first = scriptValueToIDBKey(execState, firstValue);
126     auto second = scriptValueToIDBKey(execState, secondValue);
127
128     if (!first->isValid() || !second->isValid())
129         return Exception { DataError, ASCIILiteral("Failed to execute 'cmp' on 'IDBFactory': The parameter is not a valid key.") };
130
131     return first->compare(second.get());
132 }
133
134 void IDBFactory::getAllDatabaseNames(const SecurityOrigin& mainFrameOrigin, const SecurityOrigin& openingOrigin, Function<void (const Vector<String>&)>&& callback)
135 {
136     m_connectionProxy->getAllDatabaseNames(mainFrameOrigin, openingOrigin, WTFMove(callback));
137 }
138
139 } // namespace WebCore
140
141 #endif // ENABLE(INDEXED_DATABASE)