Reviewed by Adam.
[WebKit-https.git] / WebKit / win / WebDatabaseManager.cpp
1 /*\r
2  * Copyright (C) 2007 Apple Inc. All rights reserved.\r
3  *\r
4  * Redistribution and use in source and binary forms, with or without\r
5  * modification, are permitted provided that the following conditions\r
6  * are met:\r
7  *\r
8  * 1.  Redistributions of source code must retain the above copyright\r
9  *     notice, this list of conditions and the following disclaimer.\r
10  * 2.  Redistributions in binary form must reproduce the above copyright\r
11  *     notice, this list of conditions and the following disclaimer in the\r
12  *     documentation and/or other materials provided with the distribution.\r
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of\r
14  *     its contributors may be used to endorse or promote products derived\r
15  *     from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY\r
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\r
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 #include "config.h"\r
29 #include "WebDatabaseManager.h"\r
30 #include "WebKitDLL.h"\r
31 \r
32 #include "COMEnumVariant.h"\r
33 #include "WebSecurityOrigin.h"\r
34 \r
35 #include <WebCore/BString.h>\r
36 #include <WebCore/COMPtr.h>\r
37 #include <WebCore/DatabaseTracker.h>\r
38 #include <WebCore/FileSystem.h>\r
39 #include <WebCore/SecurityOriginData.h>\r
40 \r
41 using namespace WebCore;\r
42 \r
43 static inline bool isEqual(LPCWSTR s1, LPCWSTR s2)
44 {
45     return !wcscmp(s1, s2);
46 }
47 \r
48 class DatabaseDetailsPropertyBag : public IPropertyBag, Noncopyable {\r
49 public:\r
50     static DatabaseDetailsPropertyBag* createInstance(const DatabaseDetails&);\r
51 \r
52     // IUnknown\r
53     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);\r
54     virtual ULONG STDMETHODCALLTYPE AddRef();\r
55     virtual ULONG STDMETHODCALLTYPE Release();\r
56 \r
57     // IPropertyBag\r
58     virtual HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog);\r
59     virtual HRESULT STDMETHODCALLTYPE Write(LPCOLESTR pszPropName, VARIANT* pVar);\r
60 private:\r
61     DatabaseDetailsPropertyBag(const DatabaseDetails& details) \r
62         : m_refCount(0)\r
63         , m_details(details) { }\r
64     ~DatabaseDetailsPropertyBag() { }\r
65 \r
66     ULONG m_refCount;\r
67     DatabaseDetails m_details;\r
68 };\r
69 \r
70 // DatabaseDetailsPropertyBag ------------------------------------------------------\r
71 DatabaseDetailsPropertyBag* DatabaseDetailsPropertyBag::createInstance(const DatabaseDetails& details)\r
72 {\r
73     DatabaseDetailsPropertyBag* instance = new DatabaseDetailsPropertyBag(details);\r
74     instance->AddRef();\r
75     return instance;\r
76 }\r
77 \r
78 // IUnknown ------------------------------------------------------------------------\r
79 ULONG STDMETHODCALLTYPE DatabaseDetailsPropertyBag::AddRef()\r
80 {\r
81     return ++m_refCount;\r
82 }\r
83 \r
84 ULONG STDMETHODCALLTYPE DatabaseDetailsPropertyBag::Release()\r
85 {\r
86     ULONG newRef = --m_refCount;\r
87     if (!newRef)\r
88         delete this;\r
89 \r
90     return newRef;\r
91 }\r
92 \r
93 HRESULT STDMETHODCALLTYPE DatabaseDetailsPropertyBag::QueryInterface(REFIID riid, void** ppvObject)\r
94 {\r
95     *ppvObject = 0;\r
96     if (IsEqualGUID(riid, IID_IUnknown))\r
97         *ppvObject = static_cast<DatabaseDetailsPropertyBag*>(this);\r
98     else if (IsEqualGUID(riid, IID_IPropertyBag))\r
99         *ppvObject = static_cast<DatabaseDetailsPropertyBag*>(this);\r
100     else\r
101         return E_NOINTERFACE;\r
102 \r
103     AddRef();\r
104     return S_OK;\r
105 }\r
106 \r
107 // IPropertyBag --------------------------------------------------------------------\r
108 HRESULT STDMETHODCALLTYPE DatabaseDetailsPropertyBag::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog*)\r
109 {\r
110     if (!pszPropName || !pVar)\r
111         return E_POINTER;\r
112 \r
113     VariantInit(pVar);\r
114 \r
115     if (isEqual(pszPropName, WebDatabaseDisplayNameKey)) {\r
116         COMVariantSetter<String>::setVariant(pVar, m_details.displayName());\r
117         return S_OK;\r
118     } else if (isEqual(pszPropName, WebDatabaseExpectedSizeKey)) {\r
119         COMVariantSetter<unsigned long long>::setVariant(pVar, m_details.expectedUsage());\r
120         return S_OK;\r
121     } else if (isEqual(pszPropName, WebDatabaseUsageKey)) {\r
122         COMVariantSetter<unsigned long long>::setVariant(pVar, m_details.currentUsage());\r
123         return S_OK;\r
124     }\r
125 \r
126     return E_INVALIDARG;\r
127 }\r
128 \r
129 HRESULT STDMETHODCALLTYPE DatabaseDetailsPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar)\r
130 {\r
131     if (!pszPropName || !pVar)\r
132         return E_POINTER;\r
133 \r
134     return E_FAIL;\r
135 }\r
136 \r
137 static COMPtr<WebDatabaseManager> s_sharedWebDatabaseManager;\r
138 \r
139 // WebDatabaseManager --------------------------------------------------------------\r
140 WebDatabaseManager* WebDatabaseManager::createInstance()\r
141 {\r
142     WebDatabaseManager* manager = new WebDatabaseManager();\r
143     manager->AddRef();\r
144     return manager;    \r
145 }\r
146 \r
147 WebDatabaseManager::WebDatabaseManager()\r
148     : m_refCount(0)\r
149 {\r
150     gClassCount++;\r
151 }\r
152 \r
153 WebDatabaseManager::~WebDatabaseManager()\r
154 {\r
155     gClassCount--;\r
156 }\r
157 \r
158 // IUnknown ------------------------------------------------------------------------\r
159 HRESULT STDMETHODCALLTYPE WebDatabaseManager::QueryInterface(REFIID riid, void** ppvObject)\r
160 {\r
161     *ppvObject = 0;\r
162     if (IsEqualGUID(riid, IID_IUnknown))\r
163         *ppvObject = static_cast<WebDatabaseManager*>(this);\r
164     else if (IsEqualGUID(riid, IID_IWebDatabaseManager))\r
165         *ppvObject = static_cast<WebDatabaseManager*>(this);\r
166     else\r
167         return E_NOINTERFACE;\r
168 \r
169     AddRef();\r
170     return S_OK;\r
171 }\r
172 \r
173 ULONG STDMETHODCALLTYPE WebDatabaseManager::AddRef()\r
174 {\r
175     return ++m_refCount;\r
176 }\r
177 \r
178 ULONG STDMETHODCALLTYPE WebDatabaseManager::Release()\r
179 {\r
180     ULONG newRef = --m_refCount;\r
181     if (!newRef)\r
182         delete this;\r
183 \r
184     return newRef;\r
185 }\r
186 \r
187 template<> struct COMVariantSetter<SecurityOriginData> : COMIUnknownVariantSetter<WebSecurityOrigin, SecurityOriginData> {};\r
188 \r
189 // IWebDatabaseManager -------------------------------------------------------------\r
190 HRESULT STDMETHODCALLTYPE WebDatabaseManager::sharedWebDatabaseManager( \r
191     /* [retval][out] */ IWebDatabaseManager** result)\r
192 {\r
193     if (!s_sharedWebDatabaseManager)\r
194         s_sharedWebDatabaseManager.adoptRef(WebDatabaseManager::createInstance());\r
195 \r
196     return s_sharedWebDatabaseManager.copyRefTo(result);\r
197 }\r
198 \r
199 HRESULT STDMETHODCALLTYPE WebDatabaseManager::origins( \r
200     /* [retval][out] */ IEnumVARIANT** result)\r
201 {\r
202     if (!result)\r
203         return E_POINTER;\r
204 \r
205     *result = 0;\r
206 \r
207     if (this != s_sharedWebDatabaseManager)\r
208         return E_FAIL;\r
209 \r
210     Vector<SecurityOriginData> origins;\r
211     DatabaseTracker::tracker().origins(origins);\r
212     COMPtr<COMEnumVariant<Vector<SecurityOriginData> > > enumVariant(AdoptCOM, COMEnumVariant<Vector<SecurityOriginData> >::adopt(origins));\r
213 \r
214     *result = enumVariant.releaseRef();\r
215     return S_OK;\r
216 }\r
217     \r
218 HRESULT STDMETHODCALLTYPE WebDatabaseManager::databasesWithOrigin( \r
219     /* [in] */ IWebSecurityOrigin* origin,\r
220     /* [retval][out] */ IEnumVARIANT** result)\r
221 {\r
222     if (!origin || !result)\r
223         return E_POINTER;\r
224 \r
225     *result = 0;\r
226 \r
227     if (this != s_sharedWebDatabaseManager)\r
228         return E_FAIL;\r
229 \r
230     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
231     if (!webSecurityOrigin)\r
232         return E_FAIL;\r
233 \r
234     Vector<String> databaseNames;\r
235     DatabaseTracker::tracker().databaseNamesForOrigin(webSecurityOrigin->securityOriginData(), databaseNames);\r
236 \r
237     COMPtr<COMEnumVariant<Vector<String> > > enumVariant(AdoptCOM, COMEnumVariant<Vector<String> >::adopt(databaseNames));\r
238 \r
239     *result = enumVariant.releaseRef();\r
240     return S_OK;\r
241 }\r
242 \r
243 HRESULT STDMETHODCALLTYPE WebDatabaseManager::detailsForDatabaseWithOrigin( \r
244     /* [in] */ BSTR databaseName,\r
245     /* [in] */ IWebSecurityOrigin* origin,\r
246     /* [retval][out] */ IPropertyBag** result)\r
247 {\r
248     if (!databaseName || !origin || !result)\r
249         return E_POINTER;\r
250 \r
251     *result = 0;\r
252 \r
253     if (this != s_sharedWebDatabaseManager)\r
254         return E_FAIL;\r
255 \r
256     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
257     if (!webSecurityOrigin)\r
258         return E_FAIL;\r
259 \r
260     DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(String(databaseName, SysStringLen(databaseName)),\r
261         webSecurityOrigin->securityOriginData());\r
262 \r
263     if (!details.isValid())\r
264         return E_INVALIDARG;\r
265 \r
266     *result = DatabaseDetailsPropertyBag::createInstance(details);\r
267     return S_OK;\r
268 }\r
269     \r
270 HRESULT STDMETHODCALLTYPE WebDatabaseManager::deleteAllDatabases()\r
271 {\r
272     if (this != s_sharedWebDatabaseManager)\r
273         return E_FAIL;\r
274 \r
275     DatabaseTracker::tracker().deleteAllDatabases();\r
276 \r
277     return S_OK;\r
278 }\r
279    \r
280 HRESULT STDMETHODCALLTYPE WebDatabaseManager::deleteDatabasesWithOrigin( \r
281     /* [in] */ IWebSecurityOrigin* origin)\r
282 {\r
283     if (!origin)\r
284         return E_POINTER;\r
285 \r
286     if (this != s_sharedWebDatabaseManager)\r
287         return E_FAIL;\r
288 \r
289     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
290     if (!webSecurityOrigin)\r
291         return E_FAIL;\r
292 \r
293     DatabaseTracker::tracker().deleteDatabasesWithOrigin(webSecurityOrigin->securityOriginData());\r
294 \r
295     return S_OK;\r
296 }\r
297     \r
298 HRESULT STDMETHODCALLTYPE WebDatabaseManager::deleteDatabaseWithOrigin( \r
299     /* [in] */ BSTR databaseName,\r
300     /* [in] */ IWebSecurityOrigin* origin)\r
301 {\r
302     if (!databaseName || !origin)\r
303         return E_POINTER;\r
304 \r
305     if (this != s_sharedWebDatabaseManager)\r
306         return E_FAIL;\r
307 \r
308     COMPtr<WebSecurityOrigin> webSecurityOrigin(Query, origin);\r
309     if (!webSecurityOrigin)\r
310         return E_FAIL;\r
311 \r
312     DatabaseTracker::tracker().deleteDatabase(webSecurityOrigin->securityOriginData(), String(databaseName, SysStringLen(databaseName)));\r
313 \r
314     return S_OK;\r
315 }\r
316 \r
317 void WebKitSetWebDatabasesPathIfNecessary()\r
318 {\r
319     static bool pathSet = false;\r
320     if (pathSet)\r
321         return;\r
322 \r
323     WebCore::String databasesDirectory = WebCore::pathByAppendingComponent(WebCore::localUserSpecificStorageDirectory(), "Databases");\r
324     WebCore::DatabaseTracker::tracker().setDatabasePath(databasesDirectory);\r
325 \r
326     pathSet = true;\r
327 }\r
328 \r