2d3c0d3d073b1e93496bae8cdd97bb9684178702
[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 Computer, 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 "Page.h"
47 #include "PageGroup.h"
48 #include "SecurityOrigin.h"
49 #include "WorkerContext.h"
50 #include "WorkerLoaderProxy.h"
51 #include "WorkerThread.h"
52
53 namespace WebCore {
54
55 IDBFactory::IDBFactory(IDBFactoryBackendInterface* factory)
56     : m_backend(factory)
57 {
58     // We pass a reference to this object before it can be adopted.
59     relaxAdoptionRequirement();
60 }
61
62 IDBFactory::~IDBFactory()
63 {
64 }
65
66 namespace {
67 static bool isContextValid(ScriptExecutionContext* context)
68 {
69     ASSERT(context->isDocument() || context->isWorkerContext());
70     if (context->isDocument()) {
71         Document* document = static_cast<Document*>(context);
72         return document->frame() && document->page();
73     }
74 #if !ENABLE(WORKERS)
75     if (context->isWorkerContext())
76         return false;
77 #endif
78     return true;
79 }
80
81 static String getIndexedDBDatabasePath(ScriptExecutionContext* context)
82 {
83     ASSERT(isContextValid(context));
84     if (context->isDocument()) {
85         Document* document = static_cast<Document*>(context);
86         return document->page()->group().groupSettings()->indexedDBDatabasePath();
87     }
88 #if ENABLE(WORKERS)
89     WorkerContext* workerContext = static_cast<WorkerContext*>(context);
90     const GroupSettings* groupSettings = workerContext->groupSettings();
91     if (groupSettings)
92         return groupSettings->indexedDBDatabasePath();
93 #endif
94     return String();
95 }
96 }
97
98 PassRefPtr<IDBRequest> IDBFactory::getDatabaseNames(ScriptExecutionContext* context, ExceptionCode&)
99 {
100     if (!isContextValid(context))
101         return 0;
102
103     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), 0);
104     m_backend->getDatabaseNames(request, context->securityOrigin(), context, getIndexedDBDatabasePath(context));
105     return request;
106 }
107
108 PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, int64_t version, ExceptionCode& ec)
109 {
110     // FIXME: This should only need to check for 0 once webkit.org/b/96798 lands.
111     const int64_t maxECMAScriptInteger = 0x20000000000000LL - 1;
112     if (version < 1 || version > maxECMAScriptInteger) {
113         ec = TypeError;
114         return 0;
115     }
116     return openInternal(context, name, version, ec);
117 }
118
119 PassRefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ScriptExecutionContext* context, const String& name, int64_t version, ExceptionCode& ec)
120 {
121     ASSERT(version >= 1 || version == IDBDatabaseMetadata::NoIntVersion);
122     if (name.isNull()) {
123         ec = TypeError;
124         return 0;
125     }
126     if (!isContextValid(context))
127         return 0;
128
129     RefPtr<IDBDatabaseCallbacksImpl> databaseCallbacks = IDBDatabaseCallbacksImpl::create();
130     int64_t transactionId = IDBDatabase::nextTransactionId();
131     RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, databaseCallbacks, transactionId, version);
132     m_backend->open(name, version, transactionId, request, databaseCallbacks, context->securityOrigin(), context, getIndexedDBDatabasePath(context));
133     return request;
134 }
135
136 PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, ExceptionCode& ec)
137 {
138     return openInternal(context, name, IDBDatabaseMetadata::NoIntVersion, ec);
139 }
140
141 PassRefPtr<IDBOpenDBRequest> IDBFactory::deleteDatabase(ScriptExecutionContext* context, const String& name, ExceptionCode& ec)
142 {
143     if (name.isNull()) {
144         ec = TypeError;
145         return 0;
146     }
147     if (!isContextValid(context))
148         return 0;
149
150     RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, 0, 0, IDBDatabaseMetadata::DefaultIntVersion);
151     m_backend->deleteDatabase(name, request, context->securityOrigin(), context, getIndexedDBDatabasePath(context));
152     return request;
153 }
154
155 short IDBFactory::cmp(ScriptExecutionContext* context, const ScriptValue& firstValue, const ScriptValue& secondValue, ExceptionCode& ec)
156 {
157     DOMRequestState requestState(context);
158     RefPtr<IDBKey> first = scriptValueToIDBKey(&requestState, firstValue);
159     RefPtr<IDBKey> second = scriptValueToIDBKey(&requestState, secondValue);
160
161     ASSERT(first);
162     ASSERT(second);
163
164     if (!first->isValid() || !second->isValid()) {
165         ec = IDBDatabaseException::DataError;
166         return 0;
167     }
168
169     return static_cast<short>(first->compare(second.get()));
170 }
171
172 } // namespace WebCore
173
174 #endif // ENABLE(INDEXED_DATABASE)