Have is<>(T*) function do a null check on the pointer argument
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBFactory.cpp
1 /*
2  * Copyright (C) 2010 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 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 "IDBFactory.h"
31
32 #if ENABLE(INDEXED_DATABASE)
33
34 #include "Document.h"
35 #include "ExceptionCode.h"
36 #include "Frame.h"
37 #include "GroupSettings.h"
38 #include "IDBBindingUtilities.h"
39 #include "IDBDatabase.h"
40 #include "IDBDatabaseCallbacksImpl.h"
41 #include "IDBDatabaseException.h"
42 #include "IDBFactoryBackendInterface.h"
43 #include "IDBKey.h"
44 #include "IDBKeyRange.h"
45 #include "IDBOpenDBRequest.h"
46 #include "Logging.h"
47 #include "Page.h"
48 #include "PageGroup.h"
49 #include "SchemeRegistry.h"
50 #include "SecurityOrigin.h"
51 #include "WorkerGlobalScope.h"
52 #include "WorkerLoaderProxy.h"
53 #include "WorkerThread.h"
54
55 namespace WebCore {
56
57 IDBFactory::IDBFactory(IDBFactoryBackendInterface* factory)
58     : m_backend(factory)
59 {
60     // We pass a reference to this object before it can be adopted.
61     relaxAdoptionRequirement();
62 }
63
64 IDBFactory::~IDBFactory()
65 {
66 }
67
68 namespace {
69 static bool isContextValid(ScriptExecutionContext* context)
70 {
71     ASSERT(is<Document>(*context) || context->isWorkerGlobalScope());
72     if (is<Document>(*context)) {
73         Document& document = downcast<Document>(*context);
74         return document.frame() && document.page() && (!document.page()->usesEphemeralSession() || SchemeRegistry::allowsDatabaseAccessInPrivateBrowsing(document.securityOrigin()->protocol()));
75     }
76     return true;
77 }
78
79 static String getIndexedDBDatabasePath(ScriptExecutionContext* context)
80 {
81     ASSERT(isContextValid(context));
82     if (is<Document>(*context)) {
83         Document& document = downcast<Document>(*context);
84         return document.page()->group().groupSettings().indexedDBDatabasePath();
85     }
86     const GroupSettings* groupSettings = downcast<WorkerGlobalScope>(*context).groupSettings();
87     if (groupSettings)
88         return groupSettings->indexedDBDatabasePath();
89     return String();
90 }
91 }
92
93 PassRefPtr<IDBRequest> IDBFactory::getDatabaseNames(ScriptExecutionContext* context, ExceptionCode& ec)
94 {
95     LOG(StorageAPI, "IDBFactory::getDatabaseNames");
96     if (!isContextValid(context))
97         return 0;
98     if (!context->securityOrigin()->canAccessDatabase(context->topOrigin())) {
99         ec = SECURITY_ERR;
100         return 0;
101     }
102
103     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), 0);
104     m_backend->getDatabaseNames(request, *(context->securityOrigin()), *(context->topOrigin()), context, getIndexedDBDatabasePath(context));
105     return request;
106 }
107
108 PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, ExceptionCode& ec)
109 {
110     LOG(StorageAPI, "IDBFactory::open");
111     return openInternal(context, name, 0, IndexedDB::VersionNullness::Null, ec);
112 }
113
114 PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, unsigned long long version, ExceptionCode& ec)
115 {
116     LOG(StorageAPI, "IDBFactory::open");
117     if (!version) {
118         ec = TypeError;
119         return 0;
120     }
121     return openInternal(context, name, version, IndexedDB::VersionNullness::NonNull, ec);
122 }
123
124 PassRefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ScriptExecutionContext* context, const String& name, uint64_t version, IndexedDB::VersionNullness versionNullness, ExceptionCode& ec)
125 {
126     ASSERT(version >= 1 || versionNullness == IndexedDB::VersionNullness::Null);
127     if (name.isNull()) {
128         ec = TypeError;
129         return 0;
130     }
131     if (!isContextValid(context))
132         return 0;
133     if (!context->securityOrigin()->canAccessDatabase(context->topOrigin())) {
134         ec = SECURITY_ERR;
135         return 0;
136     }
137
138     RefPtr<IDBDatabaseCallbacks> databaseCallbacks = IDBDatabaseCallbacksImpl::create();
139     int64_t transactionId = IDBDatabase::nextTransactionId();
140     RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, databaseCallbacks, transactionId, version, versionNullness);
141     m_backend->open(name, version, transactionId, request, databaseCallbacks, *(context->securityOrigin()), *(context->topOrigin()));
142     return request;
143 }
144
145 PassRefPtr<IDBOpenDBRequest> IDBFactory::deleteDatabase(ScriptExecutionContext* context, const String& name, ExceptionCode& ec)
146 {
147     LOG(StorageAPI, "IDBFactory::deleteDatabase");
148     if (name.isNull()) {
149         ec = TypeError;
150         return 0;
151     }
152     if (!isContextValid(context))
153         return 0;
154     if (!context->securityOrigin()->canAccessDatabase(context->topOrigin())) {
155         ec = SECURITY_ERR;
156         return 0;
157     }
158
159     RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, 0, 0, 0, IndexedDB::VersionNullness::Null);
160     m_backend->deleteDatabase(name, *context->securityOrigin(), *context->topOrigin(), request, context, getIndexedDBDatabasePath(context));
161     return request;
162 }
163
164 short IDBFactory::cmp(ScriptExecutionContext* context, const Deprecated::ScriptValue& firstValue, const Deprecated::ScriptValue& secondValue, ExceptionCode& ec)
165 {
166     DOMRequestState requestState(context);
167     RefPtr<IDBKey> first = scriptValueToIDBKey(&requestState, firstValue);
168     RefPtr<IDBKey> second = scriptValueToIDBKey(&requestState, secondValue);
169
170     ASSERT(first);
171     ASSERT(second);
172
173     if (!first->isValid() || !second->isValid()) {
174         ec = IDBDatabaseException::DataError;
175         return 0;
176     }
177
178     return static_cast<short>(first->compare(second.get()));
179 }
180
181 } // namespace WebCore
182
183 #endif // ENABLE(INDEXED_DATABASE)